Add cached indexes (index, partition, tag): we are now 500x faster.

paper
Philippe PITTOLI 2024-05-06 13:02:14 +02:00
parent f5c9d1a7f2
commit 061e945384
4 changed files with 139 additions and 0 deletions

View File

@ -108,4 +108,22 @@ class DODB::CachedDataBase(V) < DODB::Storage(V)
super
@data = Hash(Int32, V).new
end
def new_index(name : String, &block : Proc(V, String))
CachedIndex(V).new(self, @directory_name, name, block).tap do |indexer|
@indexers << indexer
end
end
def new_partition(name : String, &block : Proc(V, String))
CachedPartition(V).new(self, @directory_name, name, block).tap do |table|
@indexers << table
end
end
def new_tags(name : String, &block : Proc(V, Array(String)))
CachedTags(V).new(self, @directory_name, name, block).tap do |tags|
@indexers << tags
end
end
end

View File

@ -142,3 +142,43 @@ class DODB::Index(V) < DODB::Indexer(V)
end
end
class DODB::CachedIndex(V) < DODB::Index(V)
# This hash contains the relation between the index key and the data key.
property data = Hash(String, Int32).new
def check!(key, value, old_value)
index_key = key_proc.call value
# FIXME: Check its not pointing to “old_value”, if any, before raising.
if data[index_key]?
if old_value
old_key = key_proc.call old_value
return if index_key == old_key
end
raise IndexOverload.new "index '#{@name}' is overloaded for key '#{key}'"
end
end
def index(key, value)
super(key, value)
index_key = key_proc.call value
return if index_key.is_a? NoIndex
@data[index_key] = key.to_i
end
def deindex(key, value)
super(key, value)
index_key = key_proc.call value
return if index_key.is_a? NoIndex
@data.delete index_key
end
def get(index : String) : V
@storage[@data[index]]
end
end

View File

@ -93,3 +93,41 @@ class DODB::Partition(V) < DODB::Indexer(V)
end
end
class DODB::CachedPartition(V) < DODB::Partition(V)
# This hash contains the relation between the index key and the data keys.
property data = Hash(String, Array(Int32)).new
def index(key, value)
super(key, value)
partition = key_proc.call value
array = if v = @data[partition]?
v
else
Array(Int32).new
end
array << key.to_i
@data[partition] = array
end
def deindex(key, value)
super(key, value)
partition = key_proc.call value
if v = @data[partition]?
v.delete key.to_i
@data[partition] = v
end
end
def get(partition)
r_value = Array(V).new
@data[partition].each do |data_key|
r_value << @storage[data_key]
end
r_value
end
end

View File

@ -107,3 +107,46 @@ class DODB::Tags(V) < DODB::Indexer(V)
"../../../data/#{key}"
end
end
class DODB::CachedTags(V) < DODB::Tags(V)
# This hash contains the relation between the index key and the data keys.
property data = Hash(String, Array(Int32)).new
def index(key, value)
super(key, value)
indices = key_proc.call value
indices.each do |tag|
array = if v = @data[tag]?
v
else
Array(Int32).new
end
array << key.to_i
@data[tag] = array
end
end
def deindex(key, value)
super(key, value)
indices = key_proc.call value
indices.each do |tag|
if v = @data[tag]?
v.delete key.to_i
@data[tag] = v
end
end
end
def get(tag : String)
r_value = Array(V).new
@data[tag].each do |data_key|
r_value << @storage[data_key]
end
r_value
end
end