Compare commits
2 Commits
279f4379e8
...
f29fbfb850
Author | SHA1 | Date | |
---|---|---|---|
f29fbfb850 | |||
c105b7fa33 |
@ -197,7 +197,7 @@ end
|
|||||||
Let's create a DODB database for our cars.
|
Let's create a DODB database for our cars.
|
||||||
.SOURCE Ruby ps=9 vs=10
|
.SOURCE Ruby ps=9 vs=10
|
||||||
# Database creation
|
# Database creation
|
||||||
database = DODB::Storage::Basic(Car).new "path/to/db-cars"
|
database = DODB::Storage::Uncached(Car).new "path/to/db-cars"
|
||||||
|
|
||||||
# Adding an element to the db
|
# Adding an element to the db
|
||||||
database << Car.new "Corvet", "red", ["elegant", "fast"]
|
database << Car.new "Corvet", "red", ["elegant", "fast"]
|
||||||
@ -485,7 +485,7 @@ A cached database has the same API as the other DODB databases and keeps a copy
|
|||||||
database = DODB::Storage::Cached(Car).new "path/to/db-cars"
|
database = DODB::Storage::Cached(Car).new "path/to/db-cars"
|
||||||
.SOURCE
|
.SOURCE
|
||||||
All operations of the
|
All operations of the
|
||||||
.CLASS Storage::Basic
|
.CLASS Storage::Uncached
|
||||||
class are available for
|
class are available for
|
||||||
.CLASS Storage::Cached .
|
.CLASS Storage::Cached .
|
||||||
.QE
|
.QE
|
||||||
@ -532,7 +532,7 @@ along with its related data from the cache.
|
|||||||
|
|
||||||
.B "Implementation details" .
|
.B "Implementation details" .
|
||||||
The implementation is time-efficient;
|
The implementation is time-efficient;
|
||||||
the duration of adding a value is constant, it doesn't change with the number of entries.
|
the duration of adding a value is almost constant, it doesn't change much with the number of entries.
|
||||||
This efficiency is a memory tradeoff.
|
This efficiency is a memory tradeoff.
|
||||||
All the entries are added to a
|
All the entries are added to a
|
||||||
.B "double-linked list"
|
.B "double-linked list"
|
||||||
@ -549,6 +549,15 @@ Moreover,
|
|||||||
.I "common database"
|
.I "common database"
|
||||||
enables to adjust the number of stored entries.
|
enables to adjust the number of stored entries.
|
||||||
.
|
.
|
||||||
|
.QP
|
||||||
|
.SOURCE Ruby ps=9 vs=10
|
||||||
|
# Create a database with a data cache limited to 100.000 entries
|
||||||
|
database = DODB::Storage::Common(Car).new "path/to/db-cars", 100000
|
||||||
|
.SOURCE
|
||||||
|
The
|
||||||
|
.CLASS Storage::Common
|
||||||
|
class has the same API as the other database classes.
|
||||||
|
.QE
|
||||||
.
|
.
|
||||||
.SECTION RAM-only database for short-lived data
|
.SECTION RAM-only database for short-lived data
|
||||||
Databases are built around the objective to actually
|
Databases are built around the objective to actually
|
||||||
@ -610,23 +619,26 @@ This way, one can opt for a cached index and, after some time not using the file
|
|||||||
.
|
.
|
||||||
.
|
.
|
||||||
.SECTION DODB and memory constraint
|
.SECTION DODB and memory constraint
|
||||||
In contrast with the previous section, some environments have a memory constraint.
|
Some environments may have very peculiar constraints, where caching data would cause problems or would be inefficient anyway\*[*].
|
||||||
For example, in case the database is larger than the available memory, it won't be possible to use a data cache\*[*].
|
|
||||||
.FOOTNOTE1
|
.FOOTNOTE1
|
||||||
Keep in mind that for the moment "cached database" means "all data in memory".
|
Caching would be inefficient for databases where the distribution of requests is homogeneous between the different entries, for example.
|
||||||
It is perfectly reasonable to have a cached database with a policy of keeping just a certain amount of values in memory, in order to limit the memory required by selecting the relevant values to keep in cache (the most recently used, for example).
|
If the requests are random, without a small portion of the data receiving most requests (such as a Pareto distribution), caching becomes mostly irrelevant.
|
||||||
But for now, the cached version keeps everything.
|
|
||||||
See the "Future work" section.
|
|
||||||
.FOOTNOTE2
|
.FOOTNOTE2
|
||||||
|
In these cases, the
|
||||||
.B "Uncached database" .
|
|
||||||
The
|
|
||||||
.CLASS "DODB::Storage::Uncached"
|
.CLASS "DODB::Storage::Uncached"
|
||||||
database has no data cache at all and can be used in very constrained environments.
|
can be used\*[*].
|
||||||
|
.FOOTNOTE1
|
||||||
However, the
|
However, the
|
||||||
.CLASS DODB::Storage::Common
|
.CLASS DODB::Storage::Common
|
||||||
should (probably) be considered instead, even if the configured number of entries is low.
|
should be considered instead for most applications, even if the configured number of entries is low due to low RAM.
|
||||||
A small data cache is still better than no cache.
|
.FOOTNOTE2
|
||||||
|
.
|
||||||
|
.QP
|
||||||
|
.SOURCE Ruby ps=9 vs=10
|
||||||
|
# Uncached database creation
|
||||||
|
database = DODB::Storage::Uncached(Car).new "path/to/db-cars"
|
||||||
|
.SOURCE
|
||||||
|
.QE
|
||||||
|
|
||||||
.B "Uncached indexes" .
|
.B "Uncached indexes" .
|
||||||
Cached indexes do not require a large amount of memory since the only stored data is an integer (the
|
Cached indexes do not require a large amount of memory since the only stored data is an integer (the
|
||||||
@ -664,10 +676,11 @@ command enables to browse the full documentation with a web browser.
|
|||||||
.SS Database creation
|
.SS Database creation
|
||||||
.QP
|
.QP
|
||||||
.SOURCE Ruby ps=9 vs=10
|
.SOURCE Ruby ps=9 vs=10
|
||||||
# Uncached, cached and RAM-only database creation.
|
# Uncached, cached, common and RAM-only database creation.
|
||||||
database = DODB::Storage::Basic(Car).new "path/to/db-cars"
|
database = DODB::Storage::Uncached(Car).new "path/to/db"
|
||||||
database = DODB::Storage::Cached(Car).new "path/to/db-cars"
|
database = DODB::Storage::Cached(Car).new "path/to/db"
|
||||||
database = DODB::Storage::RAMOnly(Car).new "path/to/db-cars"
|
database = DODB::Storage::Common(Car).new "path/to/db", 50000 # nb cache entries
|
||||||
|
database = DODB::Storage::RAMOnly(Car).new "path/to/db"
|
||||||
.SOURCE
|
.SOURCE
|
||||||
.QE
|
.QE
|
||||||
.
|
.
|
||||||
@ -712,7 +725,7 @@ function.
|
|||||||
.KE
|
.KE
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
.SS Triggers creation
|
.SS Trigger creation
|
||||||
.QP
|
.QP
|
||||||
.SOURCE Ruby ps=9 vs=10
|
.SOURCE Ruby ps=9 vs=10
|
||||||
# Uncached, cached and RAM-only basic indexes.
|
# Uncached, cached and RAM-only basic indexes.
|
||||||
|
@ -171,16 +171,19 @@ def bench_50_shades_of_fifo()
|
|||||||
cars_fifo1 = SPECDB::Common(Car).new "-1k", 1_000
|
cars_fifo1 = SPECDB::Common(Car).new "-1k", 1_000
|
||||||
cars_fifo5 = SPECDB::Common(Car).new "-5k", 5_000
|
cars_fifo5 = SPECDB::Common(Car).new "-5k", 5_000
|
||||||
cars_fifo10 = SPECDB::Common(Car).new "-10k", 10_000
|
cars_fifo10 = SPECDB::Common(Car).new "-10k", 10_000
|
||||||
|
cars_fifo20 = SPECDB::Common(Car).new "-20k", 20_000
|
||||||
|
|
||||||
fifo_Sby_name1, fifo_Sby_color1, fifo_Sby_keywords1 = cached_indexes cars_fifo1
|
fifo_Sby_name1, fifo_Sby_color1, fifo_Sby_keywords1 = cached_indexes cars_fifo1
|
||||||
fifo_Sby_name5, fifo_Sby_color5, fifo_Sby_keywords5 = cached_indexes cars_fifo5
|
fifo_Sby_name5, fifo_Sby_color5, fifo_Sby_keywords5 = cached_indexes cars_fifo5
|
||||||
fifo_Sby_name10, fifo_Sby_color10, fifo_Sby_keywords10 = cached_indexes cars_fifo10
|
fifo_Sby_name10, fifo_Sby_color10, fifo_Sby_keywords10 = cached_indexes cars_fifo10
|
||||||
|
fifo_Sby_name20, fifo_Sby_color20, fifo_Sby_keywords20 = cached_indexes cars_fifo20
|
||||||
|
|
||||||
fn = ->search_benchmark(DODB::Storage(Car), Int32, String, DODB::Trigger::Index(Car), DODB::Trigger::Partition(Car), DODB::Trigger::Tags(Car))
|
fn = ->search_benchmark(DODB::Storage(Car), Int32, String, DODB::Trigger::Index(Car), DODB::Trigger::Partition(Car), DODB::Trigger::Tags(Car))
|
||||||
|
|
||||||
prepare_env cars_fifo1, "fifo1", fifo_Sby_name1, fifo_Sby_color1, fifo_Sby_keywords1, &fn
|
prepare_env cars_fifo1, "fifo1", fifo_Sby_name1, fifo_Sby_color1, fifo_Sby_keywords1, &fn
|
||||||
prepare_env cars_fifo5, "fifo5", fifo_Sby_name5, fifo_Sby_color5, fifo_Sby_keywords5, &fn
|
prepare_env cars_fifo5, "fifo5", fifo_Sby_name5, fifo_Sby_color5, fifo_Sby_keywords5, &fn
|
||||||
prepare_env cars_fifo10, "fifo10", fifo_Sby_name10, fifo_Sby_color10, fifo_Sby_keywords10, &fn
|
prepare_env cars_fifo10, "fifo10", fifo_Sby_name10, fifo_Sby_color10, fifo_Sby_keywords10, &fn
|
||||||
|
prepare_env cars_fifo20, "fifo20", fifo_Sby_name20, fifo_Sby_color20, fifo_Sby_keywords20, &fn
|
||||||
end
|
end
|
||||||
|
|
||||||
ENV["REPORT_DIR"]?.try { |report_dir| Context.report_dir = report_dir }
|
ENV["REPORT_DIR"]?.try { |report_dir| Context.report_dir = report_dir }
|
||||||
@ -193,11 +196,13 @@ ENV["DBSIZE_START"]?.try { |it| Context.from = it.to_i }
|
|||||||
ENV["DBSIZE_INCREMENT"]?.try { |it| Context.incr = it.to_i }
|
ENV["DBSIZE_INCREMENT"]?.try { |it| Context.incr = it.to_i }
|
||||||
ENV["FIFO_SIZE"]?.try { |it| Context.fifo_size = it.to_u32 }
|
ENV["FIFO_SIZE"]?.try { |it| Context.fifo_size = it.to_u32 }
|
||||||
|
|
||||||
pp! Context.nb_run
|
puts "REPORT_DIR: #{Context.report_dir}"
|
||||||
pp! Context.from
|
puts "MAXINDEXES: #{Context.max_indexes}"
|
||||||
pp! Context.to
|
puts "NBRUN: #{Context.nb_run}"
|
||||||
pp! Context.incr
|
puts "DBSIZE: #{Context.to}"
|
||||||
pp! Context.max_indexes
|
puts "DBSIZE_START: #{Context.from}"
|
||||||
|
puts "DBSIZE_INCREMENT: #{Context.incr}"
|
||||||
|
puts "FIFO_SIZE: #{Context.fifo_size}"
|
||||||
|
|
||||||
if ARGV.size == 0
|
if ARGV.size == 0
|
||||||
puts "Usage: benchmark-cars (fifo|search|add)"
|
puts "Usage: benchmark-cars (fifo|search|add)"
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#
|
#
|
||||||
# NOTE: fast for frequently requested data and requires a stable (and configurable) amount of memory.
|
# NOTE: fast for frequently requested data and requires a stable (and configurable) amount of memory.
|
||||||
class DODB::Storage::Common(V) < DODB::Storage::Cached(V)
|
class DODB::Storage::Common(V) < DODB::Storage::Cached(V)
|
||||||
# The *fifo* an `EfficientFIFO` instance where the key of the requested data is pushed.
|
# The *fifo* is an instance of `EfficientFIFO` where the key of the requested data is pushed.
|
||||||
# In case the number of stored entries exceeds what is allowed, the least recently used entry is removed.
|
# In case the number of stored entries exceeds what is allowed, the least recently used entry is removed.
|
||||||
property fifo : EfficientFIFO(Int32)
|
property fifo : EfficientFIFO(Int32)
|
||||||
|
|
||||||
@ -50,8 +50,15 @@ class DODB::Storage::Common(V) < DODB::Storage::Cached(V)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Verifies that the value is in cache, or read it on disk.
|
||||||
|
# Pushes the key in the fifo.
|
||||||
def [](key : Int32) : V
|
def [](key : Int32) : V
|
||||||
val = @data[key] rescue raise MissingEntry.new(key)
|
val = @data[key]?
|
||||||
|
if val.nil?
|
||||||
|
raise MissingEntry.new(key) unless ::File.exists? file_path key
|
||||||
|
val = read file_path key
|
||||||
|
@data[key] = val
|
||||||
|
end
|
||||||
push_fifo key
|
push_fifo key
|
||||||
val
|
val
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user