Skip to content

Commit d4c35de

Browse files
committed
Hash now uses an open addressing algorithm
This improves its performance, both in time and memory.
1 parent dc882ea commit d4c35de

File tree

2 files changed

+759
-194
lines changed

2 files changed

+759
-194
lines changed

spec/std/hash_spec.cr

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -892,18 +892,53 @@ describe "Hash" do
892892

893893
it "creates with initial capacity" do
894894
hash = Hash(Int32, Int32).new(initial_capacity: 1234)
895-
hash.@buckets_size.should eq(1234)
895+
hash.@indices_size_pow2.should eq(11)
896896
end
897897

898898
it "creates with initial capacity and default value" do
899899
hash = Hash(Int32, Int32).new(default_value: 3, initial_capacity: 1234)
900900
hash[1].should eq(3)
901-
hash.@buckets_size.should eq(1234)
901+
hash.@indices_size_pow2.should eq(11)
902902
end
903903

904904
it "creates with initial capacity and block" do
905905
hash = Hash(Int32, Int32).new(initial_capacity: 1234) { |h, k| h[k] = 3 }
906906
hash[1].should eq(3)
907-
hash.@buckets_size.should eq(1234)
907+
hash.@indices_size_pow2.should eq(11)
908+
end
909+
910+
describe "some edge cases while changing the implementation to open addressing" do
911+
it "edge case 1" do
912+
h = {1 => 10}
913+
h[1]?.should eq(10)
914+
h.size.should eq(1)
915+
916+
h.delete(1)
917+
h[1]?.should be_nil
918+
h.size.should eq(0)
919+
920+
h[2] = 10
921+
h[2]?.should eq(10)
922+
h.size.should eq(1)
923+
924+
h[2] = 10
925+
h[2]?.should eq(10)
926+
h.size.should eq(1)
927+
end
928+
929+
it "edge case 2" do
930+
hash = Hash(Int32, Int32).new(initial_capacity: 0)
931+
hash.@indices_size_pow2.should eq(0)
932+
hash[1] = 2
933+
hash[1].should eq(2)
934+
end
935+
936+
it "edge case 3" do
937+
h = {} of Int32 => Int32
938+
(1 << 17).times do |i|
939+
h[i] = i
940+
h[i].should eq(i)
941+
end
942+
end
908943
end
909944
end

0 commit comments

Comments
 (0)