Compare commits
2 Commits
1ef1f61615
...
67099a2369
Author | SHA1 | Date | |
---|---|---|---|
67099a2369 | |||
52462d141e |
30
spec/benchmark-ramdb.cr
Normal file
30
spec/benchmark-ramdb.cr
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
require "benchmark"
|
||||||
|
require "./benchmark-utilities.cr"
|
||||||
|
require "./cars.cr"
|
||||||
|
|
||||||
|
cars_ram = DODB::RAMOnlySpecDataBase(Car).new
|
||||||
|
cached_searchby_name, cached_searchby_color, cached_searchby_keywords = ram_indexes cars_ram
|
||||||
|
add_cars cars_ram, 1_000
|
||||||
|
|
||||||
|
# Searching for data with an index.
|
||||||
|
Benchmark.ips do |x|
|
||||||
|
x.report("(cars db) searching a data with an index (with a cache)") do
|
||||||
|
corvet = cached_searchby_name.get "Corvet-500"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Searching for data with a partition.
|
||||||
|
Benchmark.ips do |x|
|
||||||
|
x.report("(cars db) searching a data with a partition (with a cache)") do
|
||||||
|
red_cars = cached_searchby_color.get "red"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Searching for data with a tag.
|
||||||
|
Benchmark.ips do |x|
|
||||||
|
x.report("(cars db) searching a data with a tag (with a cache)") do
|
||||||
|
red_cars = cached_searchby_keywords.get "spacious"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
cars_ram.rm_storage_dir
|
78
spec/cars.cr
Normal file
78
spec/cars.cr
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# This file contains all the necessary code to perform tests based on the following Car database.
|
||||||
|
|
||||||
|
require "json"
|
||||||
|
require "../src/dodb.cr"
|
||||||
|
require "./spec-database.cr"
|
||||||
|
|
||||||
|
class Car
|
||||||
|
include JSON::Serializable
|
||||||
|
|
||||||
|
property name : String # unique to each instance (1-1 relations)
|
||||||
|
property color : String # a simple attribute (1-n relations)
|
||||||
|
property keywords : Array(String) # tags about a car, example: "shiny" (n-n relations)
|
||||||
|
|
||||||
|
def_clone
|
||||||
|
|
||||||
|
def initialize(@name, @color, @keywords)
|
||||||
|
end
|
||||||
|
class_getter cars = [
|
||||||
|
Car.new("Corvet", "red", [ "shiny", "impressive", "fast", "elegant" ]),
|
||||||
|
Car.new("SUV", "red", [ "solid", "impressive" ]),
|
||||||
|
Car.new("Mustang", "red", [ "shiny", "impressive", "elegant" ]),
|
||||||
|
Car.new("Bullet-GT", "red", [ "shiny", "impressive", "fast", "elegant" ]),
|
||||||
|
Car.new("GTI", "blue", [ "average" ]),
|
||||||
|
Car.new("Deudeuch", "violet", [ "dirty", "slow", "only French will understand" ])
|
||||||
|
]
|
||||||
|
|
||||||
|
# Equality is true if every property is identical.
|
||||||
|
def ==(other)
|
||||||
|
@name == other.name && @color == other.color && @keywords == other.keywords
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def ram_indexes(storage : DODB::Storage)
|
||||||
|
n = storage.new_RAM_index "name", &.name
|
||||||
|
c = storage.new_RAM_partition "color", &.color
|
||||||
|
k = storage.new_RAM_tags "keyword", &.keywords
|
||||||
|
return n, c, k
|
||||||
|
end
|
||||||
|
|
||||||
|
def cached_indexes(storage : DODB::Storage)
|
||||||
|
n = storage.new_index "name", &.name
|
||||||
|
c = storage.new_partition "color", &.color
|
||||||
|
k = storage.new_tags "keyword", &.keywords
|
||||||
|
return n, c, k
|
||||||
|
end
|
||||||
|
|
||||||
|
def uncached_indexes(storage : DODB::Storage)
|
||||||
|
n = storage.new_uncached_index "name", &.name
|
||||||
|
c = storage.new_uncached_partition "color", &.color
|
||||||
|
k = storage.new_uncached_tags "keyword", &.keywords
|
||||||
|
return n, c, k
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_cars(storage : DODB::Storage, nb_iterations : Int32, from = 0)
|
||||||
|
i = from
|
||||||
|
car1 = Car.new "Corvet", "red", [ "shiny", "impressive", "fast", "elegant" ]
|
||||||
|
car2 = Car.new "Bullet-GT", "blue", [ "shiny", "fast", "expensive" ]
|
||||||
|
car3 = Car.new "Deudeuche", "beige", [ "curvy", "sublime" ]
|
||||||
|
car4 = Car.new "Ford-5", "red", [ "unknown" ]
|
||||||
|
car5 = Car.new "C-MAX", "gray", [ "spacious", "affordable" ]
|
||||||
|
|
||||||
|
while i < nb_iterations
|
||||||
|
car1.name = "Corvet-#{i}"
|
||||||
|
car2.name = "Bullet-GT-#{i}"
|
||||||
|
car3.name = "Deudeuche-#{i}"
|
||||||
|
car4.name = "Ford-5-#{i}"
|
||||||
|
car5.name = "C-MAX-#{i}"
|
||||||
|
|
||||||
|
storage << car1
|
||||||
|
storage << car2
|
||||||
|
storage << car3
|
||||||
|
storage << car4
|
||||||
|
storage << car5
|
||||||
|
i += 1
|
||||||
|
#STDOUT.write "\radding value #{i}".to_slice
|
||||||
|
end
|
||||||
|
#puts ""
|
||||||
|
end
|
50
spec/spec-database.cr
Normal file
50
spec/spec-database.cr
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
class DODB::SpecDataBase(V) < DODB::DataBase(V)
|
||||||
|
property storage_dir : String
|
||||||
|
def initialize(storage_ext = "", remove_previous_data = true)
|
||||||
|
@storage_dir = "test-spec-storage#{storage_ext}"
|
||||||
|
|
||||||
|
if remove_previous_data
|
||||||
|
::FileUtils.rm_rf storage_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
super storage_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
def rm_storage_dir
|
||||||
|
::FileUtils.rm_rf @storage_dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class DODB::CachedSpecDataBase(V) < DODB::CachedDataBase(V)
|
||||||
|
property storage_dir : String
|
||||||
|
def initialize(storage_ext = "", remove_previous_data = true)
|
||||||
|
@storage_dir = "test-spec-storage-cached#{storage_ext}"
|
||||||
|
|
||||||
|
if remove_previous_data
|
||||||
|
::FileUtils.rm_rf storage_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
super storage_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
def rm_storage_dir
|
||||||
|
::FileUtils.rm_rf @storage_dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class DODB::RAMOnlySpecDataBase(V) < DODB::RAMOnlyDataBase(V)
|
||||||
|
property storage_dir : String
|
||||||
|
def initialize(storage_ext = "", remove_previous_data = true)
|
||||||
|
@storage_dir = "test-spec-storage-ram#{storage_ext}"
|
||||||
|
|
||||||
|
if remove_previous_data
|
||||||
|
::FileUtils.rm_rf storage_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
super storage_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
def rm_storage_dir
|
||||||
|
::FileUtils.rm_rf @storage_dir
|
||||||
|
end
|
||||||
|
end
|
@ -85,24 +85,3 @@ class PrimitiveShip
|
|||||||
@@asakaze
|
@@asakaze
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
class Car
|
|
||||||
include JSON::Serializable
|
|
||||||
|
|
||||||
property name : String # unique to each instance (1-1 relations)
|
|
||||||
property color : String # a simple attribute (1-n relations)
|
|
||||||
property keywords : Array(String) # tags about a car, example: "shiny" (n-n relations)
|
|
||||||
|
|
||||||
def_clone
|
|
||||||
|
|
||||||
def initialize(@name, @color, @keywords)
|
|
||||||
end
|
|
||||||
class_getter cars = [
|
|
||||||
Car.new("Corvet", "red", [ "shiny", "impressive", "fast", "elegant" ]),
|
|
||||||
Car.new("SUV", "red", [ "solid", "impressive" ]),
|
|
||||||
Car.new("Mustang", "red", [ "shiny", "impressive", "elegant" ]),
|
|
||||||
Car.new("Bullet-GT", "red", [ "shiny", "impressive", "fast", "elegant" ]),
|
|
||||||
Car.new("GTI", "blue", [ "average" ]),
|
|
||||||
Car.new("Deudeuch", "violet", [ "dirty", "slow", "only French will understand" ])
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
59
spec/test.cr
59
spec/test.cr
@ -2,28 +2,17 @@ require "spec"
|
|||||||
require "file_utils"
|
require "file_utils"
|
||||||
|
|
||||||
require "../src/dodb.cr"
|
require "../src/dodb.cr"
|
||||||
|
require "./spec-database.cr"
|
||||||
require "./test-data.cr"
|
require "./test-data.cr"
|
||||||
|
|
||||||
def fork_process(&)
|
def fork_process(&)
|
||||||
Process.new Crystal::System::Process.fork { yield }
|
Process.new Crystal::System::Process.fork { yield }
|
||||||
end
|
end
|
||||||
|
|
||||||
class DODB::SpecDataBase < DODB::DataBase(Ship)
|
|
||||||
def initialize(storage_ext = "", remove_previous_data = true)
|
|
||||||
storage_dir = "test-storage#{storage_ext}"
|
|
||||||
|
|
||||||
if remove_previous_data
|
|
||||||
::FileUtils.rm_rf storage_dir
|
|
||||||
end
|
|
||||||
|
|
||||||
super storage_dir
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "DODB::DataBase" do
|
describe "DODB::DataBase" do
|
||||||
describe "basics" do
|
describe "basics" do
|
||||||
it "store and get data" do
|
it "store and get data" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
Ship.all_ships.each do |ship|
|
Ship.all_ships.each do |ship|
|
||||||
db << ship
|
db << ship
|
||||||
@ -33,7 +22,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "rewrite already stored data" do
|
it "rewrite already stored data" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
ship = Ship.all_ships[0]
|
ship = Ship.all_ships[0]
|
||||||
|
|
||||||
key = db << ship
|
key = db << ship
|
||||||
@ -45,7 +34,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "properly remove data" do
|
it "properly remove data" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
Ship.all_ships.each do |ship|
|
Ship.all_ships.each do |ship|
|
||||||
db << ship
|
db << ship
|
||||||
@ -66,19 +55,19 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "preserves data on reopening" do
|
it "preserves data on reopening" do
|
||||||
db1 = DODB::SpecDataBase.new
|
db1 = DODB::SpecDataBase(Ship).new
|
||||||
db1 << Ship.kisaragi
|
db1 << Ship.kisaragi
|
||||||
|
|
||||||
db1.to_a.size.should eq(1)
|
db1.to_a.size.should eq(1)
|
||||||
|
|
||||||
db2 = DODB::SpecDataBase.new remove_previous_data: false
|
db2 = DODB::SpecDataBase(Ship).new remove_previous_data: false
|
||||||
db2 << Ship.mutsuki
|
db2 << Ship.mutsuki
|
||||||
|
|
||||||
db1.to_a.size.should eq(2)
|
db1.to_a.size.should eq(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "iterates in normal and reversed order" do
|
it "iterates in normal and reversed order" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
Ship.all_ships.each do |ship|
|
Ship.all_ships.each do |ship|
|
||||||
db << ship
|
db << ship
|
||||||
@ -98,7 +87,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "respects the provided offsets if any" do
|
it "respects the provided offsets if any" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
Ship.all_ships.each do |ship|
|
Ship.all_ships.each do |ship|
|
||||||
db << ship
|
db << ship
|
||||||
@ -116,7 +105,7 @@ describe "DODB::DataBase" do
|
|||||||
|
|
||||||
describe "indices" do
|
describe "indices" do
|
||||||
it "do basic indexing" do
|
it "do basic indexing" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_name = db.new_index "name", &.name
|
db_ships_by_name = db.new_index "name", &.name
|
||||||
|
|
||||||
@ -130,7 +119,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "raise on index overload" do
|
it "raise on index overload" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_name = db.new_index "name", &.name
|
db_ships_by_name = db.new_index "name", &.name
|
||||||
|
|
||||||
@ -144,7 +133,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "properly deindex" do
|
it "properly deindex" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_name = db.new_index "name", &.name
|
db_ships_by_name = db.new_index "name", &.name
|
||||||
|
|
||||||
@ -162,7 +151,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "properly reindex" do
|
it "properly reindex" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_name = db.new_index "name", &.name
|
db_ships_by_name = db.new_index "name", &.name
|
||||||
|
|
||||||
@ -180,7 +169,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "properly updates" do
|
it "properly updates" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_name = db.new_index "name", &.name
|
db_ships_by_name = db.new_index "name", &.name
|
||||||
|
|
||||||
@ -202,7 +191,7 @@ describe "DODB::DataBase" do
|
|||||||
|
|
||||||
describe "partitions" do
|
describe "partitions" do
|
||||||
it "do basic partitioning" do
|
it "do basic partitioning" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_class = db.new_partition "class", &.klass
|
db_ships_by_class = db.new_partition "class", &.klass
|
||||||
|
|
||||||
@ -230,7 +219,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "removes select elements from partitions" do
|
it "removes select elements from partitions" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_class = db.new_partition "class", &.klass
|
db_ships_by_class = db.new_partition "class", &.klass
|
||||||
|
|
||||||
@ -250,7 +239,7 @@ describe "DODB::DataBase" do
|
|||||||
|
|
||||||
describe "tags" do
|
describe "tags" do
|
||||||
it "do basic tagging" do
|
it "do basic tagging" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_tags = db.new_tags "tags", &.tags
|
db_ships_by_tags = db.new_tags "tags", &.tags
|
||||||
|
|
||||||
@ -271,7 +260,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "properly removes tags" do
|
it "properly removes tags" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_tags = db.new_tags "tags", &.tags
|
db_ships_by_tags = db.new_tags "tags", &.tags
|
||||||
|
|
||||||
@ -295,7 +284,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "gets items that have multiple tags" do
|
it "gets items that have multiple tags" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_tags = db.new_tags "tags", &.tags
|
db_ships_by_tags = db.new_tags "tags", &.tags
|
||||||
|
|
||||||
@ -316,7 +305,7 @@ describe "DODB::DataBase" do
|
|||||||
|
|
||||||
describe "atomic operations" do
|
describe "atomic operations" do
|
||||||
it "safe_get and safe_get?" do
|
it "safe_get and safe_get?" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_name = db.new_index "name", &.name
|
db_ships_by_name = db.new_index "name", &.name
|
||||||
|
|
||||||
@ -338,7 +327,7 @@ describe "DODB::DataBase" do
|
|||||||
|
|
||||||
describe "tools" do
|
describe "tools" do
|
||||||
it "rebuilds indexes" do
|
it "rebuilds indexes" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
db_ships_by_name = db.new_index "name", &.name
|
db_ships_by_name = db.new_index "name", &.name
|
||||||
db_ships_by_class = db.new_partition "class", &.klass
|
db_ships_by_class = db.new_partition "class", &.klass
|
||||||
@ -370,7 +359,7 @@ describe "DODB::DataBase" do
|
|||||||
# At this point, the “old” DB is filled. Now we need to convert
|
# At this point, the “old” DB is filled. Now we need to convert
|
||||||
# to the new DB.
|
# to the new DB.
|
||||||
|
|
||||||
new_db = DODB::SpecDataBase.new "-migration-target"
|
new_db = DODB::SpecDataBase(Ship).new "-migration-target"
|
||||||
|
|
||||||
new_ships_by_name = new_db.new_index "name", &.name
|
new_ships_by_name = new_db.new_index "name", &.name
|
||||||
new_ships_by_class = new_db.new_partition "class", &.klass
|
new_ships_by_class = new_db.new_partition "class", &.klass
|
||||||
@ -407,7 +396,7 @@ describe "DODB::DataBase" do
|
|||||||
entries_per_fork = 100
|
entries_per_fork = 100
|
||||||
|
|
||||||
it "works for pushing values" do
|
it "works for pushing values" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
|
|
||||||
processes = [] of Process
|
processes = [] of Process
|
||||||
|
|
||||||
@ -427,7 +416,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "works for updating values" do
|
it "works for updating values" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
db_entries_by_name = db.new_index "name", &.name
|
db_entries_by_name = db.new_index "name", &.name
|
||||||
|
|
||||||
# First pass, creating data.
|
# First pass, creating data.
|
||||||
@ -465,7 +454,7 @@ describe "DODB::DataBase" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "does parallel-safe updates" do
|
it "does parallel-safe updates" do
|
||||||
db = DODB::SpecDataBase.new
|
db = DODB::SpecDataBase(Ship).new
|
||||||
db_entries_by_name = db.new_index "name", &.name
|
db_entries_by_name = db.new_index "name", &.name
|
||||||
|
|
||||||
# We’ll be storing an integer in the "klass" field, and incrementing
|
# We’ll be storing an integer in the "klass" field, and incrementing
|
||||||
|
Loading…
Reference in New Issue
Block a user