Skip to content

Commit e7500e1

Browse files
committed
fixed position optimized implementation's hashing; bumped to 4.1.0
1 parent 2c841da commit e7500e1

24 files changed

+94
-246
lines changed

MultiKeyMap/MultiKeyMap.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
<RepositoryUrl>https://github.com/protobufel/multikeymapcsharp</RepositoryUrl>
1414
<RepositoryType>git</RepositoryType>
1515
<PackageTags>c# library multikey dictionary</PackageTags>
16-
<PackageReleaseNotes>improved benchmarks</PackageReleaseNotes>
16+
<PackageReleaseNotes>fixed the position optimized implementation's hashing</PackageReleaseNotes>
1717
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
1818
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
1919
<SignAssembly>False</SignAssembly>
20-
<AssemblyVersion>4.0.20.0</AssemblyVersion>
21-
<FileVersion>4.0.20.0</FileVersion>
22-
<Version>4.0.20</Version>
20+
<AssemblyVersion>4.1.0.0</AssemblyVersion>
21+
<FileVersion>4.1.0.0</FileVersion>
22+
<Version>4.1.0</Version>
2323
</PropertyGroup>
2424

2525
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

MultiKeyMap/PositionMask/KeyMasks.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ internal interface IKeyMask<T, K> : IEquatable<IKeyMask<T, K>>, IEquatable<K>, I
1212
K Key { get; }
1313
}
1414

15-
internal interface ISubKeyMask<T> : IEquatable<ISubKeyMask<T>>, IEquatable<T>
15+
internal interface ISubKeyMask<T> : IEquatable<ISubKeyMask<T>>
1616
{
1717
T SubKey { get; }
1818
int Position { get; }
@@ -82,6 +82,7 @@ IEnumerator IEnumerable.GetEnumerator()
8282
internal class SubKeyMask<T> : ISubKeyMask<T>
8383
{
8484
public const int NonPositional = -1;
85+
public const int NonPositionalHashCode = int.MaxValue >> 16;
8586

8687
public SubKeyMask(T subKey) : this(subKey, NonPositional)
8788
{
@@ -98,14 +99,16 @@ public SubKeyMask(T subKey, int position)
9899

99100
public int Position { get; }
100101

101-
bool IEquatable<T>.Equals(T other)
102-
{
103-
return (other == null) ? false : SubKey.Equals(other);
104-
}
105-
106102
public override int GetHashCode()
107103
{
108-
return SubKey.GetHashCode();
104+
int hash = 13;
105+
106+
unchecked
107+
{
108+
hash = (hash + ((Position == NonPositional) ? NonPositionalHashCode : Position.GetHashCode())) * 47 + SubKey.GetHashCode();
109+
}
110+
111+
return hash;
109112
}
110113

111114
public bool Equals(ISubKeyMask<T> other)
@@ -125,7 +128,7 @@ public bool Equals(ISubKeyMask<T> other)
125128
return false;
126129
}
127130

128-
return SubKey.Equals(other.SubKey);
131+
return Equals(SubKey, other.SubKey) && (Position == other.Position);
129132
}
130133

131134
public override bool Equals(object obj)
@@ -186,7 +189,7 @@ public override bool Equals(ISubKeyMask<T> x, ISubKeyMask<T> y)
186189

187190
public override int GetHashCode(ISubKeyMask<T> obj)
188191
{
189-
return obj?.SubKey?.GetHashCode() ?? 0;
192+
return obj?.GetHashCode() ?? 0;
190193
}
191194
}
192195

MultiKeyMapBenchmarks/BenchmarkDotNet.Artifacts/results/MultiKeyMapVsDictionaryAddition-report-github.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ dotnet cli version=1.0.4
99

1010

1111
```
12-
| Method | Strategy | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Gen 1 | Allocated |
13-
|---------------- |-------------------------------- |-----------:|----------:|----------:|-------:|---------:|--------:|-------:|----------:|
14-
| **MultiKeyMap_Add** | **OptimizedForNonPositionalSearch** | **213.237 us** | **1.2228 us** | **1.0840 us** | **44.77** | **0.35** | **34.1797** | **0.2441** | **140.52 KB** |
15-
| Dictionary_Add | OptimizedForNonPositionalSearch | 4.764 us | 0.0344 us | 0.0305 us | 1.00 | 0.00 | 2.4872 | - | 10.21 KB |
16-
| **MultiKeyMap_Add** | **OptimizedForPositionalSearch** | **310.649 us** | **0.4653 us** | **0.3364 us** | **64.90** | **0.22** | **50.7813** | **-** | **208.48 KB** |
17-
| Dictionary_Add | OptimizedForPositionalSearch | 4.787 us | 0.0207 us | 0.0162 us | 1.00 | 0.00 | 2.5177 | - | 10.32 KB |
12+
| Method | Strategy | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Gen 1 | Allocated |
13+
|---------------- |-------------------------------- |-----------:|----------:|----------:|-------:|---------:|--------:|--------:|----------:|
14+
| **MultiKeyMap_Add** | **OptimizedForNonPositionalSearch** | **214.843 us** | **1.7234 us** | **1.6121 us** | **44.18** | **0.38** | **34.1797** | **0.2441** | **140.52 KB** |
15+
| Dictionary_Add | OptimizedForNonPositionalSearch | 4.864 us | 0.0273 us | 0.0242 us | 1.00 | 0.00 | 2.4872 | - | 10.21 KB |
16+
| **MultiKeyMap_Add** | **OptimizedForPositionalSearch** | **403.821 us** | **2.1189 us** | **1.8784 us** | **82.24** | **0.58** | **67.2852** | **33.6263** | **388.84 KB** |
17+
| Dictionary_Add | OptimizedForPositionalSearch | 4.911 us | 0.0314 us | 0.0279 us | 1.00 | 0.00 | 2.5177 | - | 10.32 KB |
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,RemoveOutliers,Affinity,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,RetainVm,Server,Clock,EngineFactory,Toolchain,InvocationCount,IterationTime,LaunchCount,RunStrategy,TargetCount,UnrollFactor,WarmupCount,Strategy,Mean,Error,StdDev,Scaled,ScaledSD,Gen 0,Gen 1,Allocated
2-
MultiKeyMap_Add,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForNonPositionalSearch,213.237 us,1.2228 us,1.0840 us,44.77,0.35,34.1797,0.2441,140.52 KB
3-
Dictionary_Add,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForNonPositionalSearch,4.764 us,0.0344 us,0.0305 us,1.00,0.00,2.4872,-,10.21 KB
4-
MultiKeyMap_Add,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForPositionalSearch,310.649 us,0.4653 us,0.3364 us,64.90,0.22,50.7813,-,208.48 KB
5-
Dictionary_Add,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForPositionalSearch,4.787 us,0.0207 us,0.0162 us,1.00,0.00,2.5177,-,10.32 KB
2+
MultiKeyMap_Add,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForNonPositionalSearch,214.843 us,1.7234 us,1.6121 us,44.18,0.38,34.1797,0.2441,140.52 KB
3+
Dictionary_Add,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForNonPositionalSearch,4.864 us,0.0273 us,0.0242 us,1.00,0.00,2.4872,-,10.21 KB
4+
MultiKeyMap_Add,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForPositionalSearch,403.821 us,2.1189 us,1.8784 us,82.24,0.58,67.2852,33.6263,388.84 KB
5+
Dictionary_Add,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForPositionalSearch,4.911 us,0.0314 us,0.0279 us,1.00,0.00,2.5177,-,10.32 KB

MultiKeyMapBenchmarks/BenchmarkDotNet.Artifacts/results/MultiKeyMapVsDictionaryAddition-report.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
<table>
2626
<thead><tr><th> Method</th><th> Strategy</th><th>Mean</th><th>Error</th><th>StdDev</th><th>Scaled</th><th>ScaledSD</th><th>Gen 0</th><th>Gen 1</th><th>Allocated</th>
2727
</tr>
28-
</thead><tbody><tr><td>MultiKeyMap_Add</td><td>OptimizedForNonPositionalSearch</td><td>213.237 us</td><td>1.2228 us</td><td>1.0840 us</td><td>44.77</td><td>0.35</td><td>34.1797</td><td>0.2441</td><td>140.52 KB</td>
29-
</tr><tr><td>Dictionary_Add</td><td>OptimizedForNonPositionalSearch</td><td>4.764 us</td><td>0.0344 us</td><td>0.0305 us</td><td>1.00</td><td>0.00</td><td>2.4872</td><td>-</td><td>10.21 KB</td>
30-
</tr><tr><td>MultiKeyMap_Add</td><td>OptimizedForPositionalSearch</td><td>310.649 us</td><td>0.4653 us</td><td>0.3364 us</td><td>64.90</td><td>0.22</td><td>50.7813</td><td>-</td><td>208.48 KB</td>
31-
</tr><tr><td>Dictionary_Add</td><td>OptimizedForPositionalSearch</td><td>4.787 us</td><td>0.0207 us</td><td>0.0162 us</td><td>1.00</td><td>0.00</td><td>2.5177</td><td>-</td><td>10.32 KB</td>
28+
</thead><tbody><tr><td>MultiKeyMap_Add</td><td>OptimizedForNonPositionalSearch</td><td>214.843 us</td><td>1.7234 us</td><td>1.6121 us</td><td>44.18</td><td>0.38</td><td>34.1797</td><td>0.2441</td><td>140.52 KB</td>
29+
</tr><tr><td>Dictionary_Add</td><td>OptimizedForNonPositionalSearch</td><td>4.864 us</td><td>0.0273 us</td><td>0.0242 us</td><td>1.00</td><td>0.00</td><td>2.4872</td><td>-</td><td>10.21 KB</td>
30+
</tr><tr><td>MultiKeyMap_Add</td><td>OptimizedForPositionalSearch</td><td>403.821 us</td><td>2.1189 us</td><td>1.8784 us</td><td>82.24</td><td>0.58</td><td>67.2852</td><td>33.6263</td><td>388.84 KB</td>
31+
</tr><tr><td>Dictionary_Add</td><td>OptimizedForPositionalSearch</td><td>4.911 us</td><td>0.0314 us</td><td>0.0279 us</td><td>1.00</td><td>0.00</td><td>2.5177</td><td>-</td><td>10.32 KB</td>
3232
</tr></tbody></table>
3333
</body>
3434
</html>

MultiKeyMapBenchmarks/BenchmarkDotNet.Artifacts/results/MultiKeyMapVsDictionaryCreation-report-github.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ dotnet cli version=1.0.4
1111
```
1212
| Method | Strategy | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
1313
|---------------------------- |-------------------------------- |----------:|----------:|----------:|-------:|---------:|-------:|----------:|
14-
| **CreateDictionaryMultiKeyMap** | **OptimizedForNonPositionalSearch** | **161.13 ns** | **0.6697 ns** | **0.5936 ns** | **9.55** | **0.08** | **0.0627** | **264 B** |
15-
| CreateDictionary | OptimizedForNonPositionalSearch | 16.88 ns | 0.1433 ns | 0.1270 ns | 1.00 | 0.00 | 0.0190 | 80 B |
16-
| **CreateDictionaryMultiKeyMap** | **OptimizedForPositionalSearch** | **204.40 ns** | **1.6882 ns** | **1.4965 ns** | **11.88** | **0.13** | **0.0894** | **376 B** |
17-
| CreateDictionary | OptimizedForPositionalSearch | 17.21 ns | 0.1508 ns | 0.1410 ns | 1.00 | 0.00 | 0.0190 | 80 B |
14+
| **CreateDictionaryMultiKeyMap** | **OptimizedForNonPositionalSearch** | **168.54 ns** | **1.1452 ns** | **1.0713 ns** | **9.74** | **0.09** | **0.0627** | **264 B** |
15+
| CreateDictionary | OptimizedForNonPositionalSearch | 17.30 ns | 0.1213 ns | 0.1134 ns | 1.00 | 0.00 | 0.0190 | 80 B |
16+
| **CreateDictionaryMultiKeyMap** | **OptimizedForPositionalSearch** | **210.38 ns** | **0.9357 ns** | **0.7814 ns** | **12.27** | **0.09** | **0.0894** | **376 B** |
17+
| CreateDictionary | OptimizedForPositionalSearch | 17.15 ns | 0.1261 ns | 0.1118 ns | 1.00 | 0.00 | 0.0190 | 80 B |
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,RemoveOutliers,Affinity,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,RetainVm,Server,Clock,EngineFactory,Toolchain,InvocationCount,IterationTime,LaunchCount,RunStrategy,TargetCount,UnrollFactor,WarmupCount,Strategy,Mean,Error,StdDev,Scaled,ScaledSD,Gen 0,Allocated
2-
CreateDictionaryMultiKeyMap,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForNonPositionalSearch,161.13 ns,0.6697 ns,0.5936 ns,9.55,0.08,0.0627,264 B
3-
CreateDictionary,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForNonPositionalSearch,16.88 ns,0.1433 ns,0.1270 ns,1.00,0.00,0.0190,80 B
4-
CreateDictionaryMultiKeyMap,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForPositionalSearch,204.40 ns,1.6882 ns,1.4965 ns,11.88,0.13,0.0894,376 B
5-
CreateDictionary,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForPositionalSearch,17.21 ns,0.1508 ns,0.1410 ns,1.00,0.00,0.0190,80 B
2+
CreateDictionaryMultiKeyMap,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForNonPositionalSearch,168.54 ns,1.1452 ns,1.0713 ns,9.74,0.09,0.0627,264 B
3+
CreateDictionary,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForNonPositionalSearch,17.30 ns,0.1213 ns,0.1134 ns,1.00,0.00,0.0190,80 B
4+
CreateDictionaryMultiKeyMap,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForPositionalSearch,210.38 ns,0.9357 ns,0.7814 ns,12.27,0.09,0.0894,376 B
5+
CreateDictionary,Default,False,Default,Default,Default,Default,Default,Default,255,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,1,Default,Default,Default,Default,16,Default,OptimizedForPositionalSearch,17.15 ns,0.1261 ns,0.1118 ns,1.00,0.00,0.0190,80 B

MultiKeyMapBenchmarks/BenchmarkDotNet.Artifacts/results/MultiKeyMapVsDictionaryCreation-report.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
<table>
2626
<thead><tr><th> Method</th><th> Strategy</th><th>Mean</th><th>Error</th><th>StdDev</th><th>Scaled</th><th>ScaledSD</th><th>Gen 0</th><th>Allocated</th>
2727
</tr>
28-
</thead><tbody><tr><td>CreateDictionaryMultiKeyMap</td><td>OptimizedForNonPositionalSearch</td><td>161.13 ns</td><td>0.6697 ns</td><td>0.5936 ns</td><td>9.55</td><td>0.08</td><td>0.0627</td><td>264 B</td>
29-
</tr><tr><td> CreateDictionary</td><td>OptimizedForNonPositionalSearch</td><td>16.88 ns</td><td>0.1433 ns</td><td>0.1270 ns</td><td>1.00</td><td>0.00</td><td>0.0190</td><td>80 B</td>
30-
</tr><tr><td>CreateDictionaryMultiKeyMap</td><td>OptimizedForPositionalSearch</td><td>204.40 ns</td><td>1.6882 ns</td><td>1.4965 ns</td><td>11.88</td><td>0.13</td><td>0.0894</td><td>376 B</td>
31-
</tr><tr><td> CreateDictionary</td><td>OptimizedForPositionalSearch</td><td>17.21 ns</td><td>0.1508 ns</td><td>0.1410 ns</td><td>1.00</td><td>0.00</td><td>0.0190</td><td>80 B</td>
28+
</thead><tbody><tr><td>CreateDictionaryMultiKeyMap</td><td>OptimizedForNonPositionalSearch</td><td>168.54 ns</td><td>1.1452 ns</td><td>1.0713 ns</td><td>9.74</td><td>0.09</td><td>0.0627</td><td>264 B</td>
29+
</tr><tr><td> CreateDictionary</td><td>OptimizedForNonPositionalSearch</td><td>17.30 ns</td><td>0.1213 ns</td><td>0.1134 ns</td><td>1.00</td><td>0.00</td><td>0.0190</td><td>80 B</td>
30+
</tr><tr><td>CreateDictionaryMultiKeyMap</td><td>OptimizedForPositionalSearch</td><td>210.38 ns</td><td>0.9357 ns</td><td>0.7814 ns</td><td>12.27</td><td>0.09</td><td>0.0894</td><td>376 B</td>
31+
</tr><tr><td> CreateDictionary</td><td>OptimizedForPositionalSearch</td><td>17.15 ns</td><td>0.1261 ns</td><td>0.1118 ns</td><td>1.00</td><td>0.00</td><td>0.0190</td><td>80 B</td>
3232
</tr></tbody></table>
3333
</body>
3434
</html>

MultiKeyMapBenchmarks/BenchmarkDotNet.Artifacts/results/MultiKeyMapVsDictionaryRemoval-report-github.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ dotnet cli version=1.0.4
99

1010

1111
```
12-
| Method | Strategy | Mean | Error | StdDev | Scaled | Gen 0 | Gen 1 | Allocated |
13-
|------------------- |-------------------------------- |---------:|----------:|----------:|-------:|--------:|-------:|----------:|
14-
| **MultiKeyMap_Remove** | **OptimizedForNonPositionalSearch** | **603.8 us** | **3.5025 us** | **3.1049 us** | **2.75** | **68.3594** | **-** | **283.21 KB** |
15-
| Dictionary_Remove | OptimizedForNonPositionalSearch | 219.7 us | 0.4560 us | 0.3808 us | 1.00 | 36.6211 | - | 150.4 KB |
16-
| **MultiKeyMap_Remove** | **OptimizedForPositionalSearch** | **727.5 us** | **2.3995 us** | **2.0037 us** | **2.31** | **96.6797** | **0.9766** | **398.04 KB** |
17-
| Dictionary_Remove | OptimizedForPositionalSearch | 315.0 us | 2.0312 us | 1.8006 us | 1.00 | 53.2227 | 0.4883 | 218.35 KB |
12+
| Method | Strategy | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Gen 1 | Allocated |
13+
|------------------- |-------------------------------- |---------:|----------:|----------:|-------:|---------:|---------:|--------:|----------:|
14+
| **MultiKeyMap_Remove** | **OptimizedForNonPositionalSearch** | **628.8 us** | **4.9192 us** | **4.3607 us** | **2.80** | **0.02** | **68.3594** | **-** | **283.21 KB** |
15+
| Dictionary_Remove | OptimizedForNonPositionalSearch | 224.7 us | 0.9011 us | 0.7988 us | 1.00 | 0.00 | 36.6211 | - | 150.4 KB |
16+
| **MultiKeyMap_Remove** | **OptimizedForPositionalSearch** | **839.4 us** | **4.4798 us** | **4.1904 us** | **2.10** | **0.01** | **126.6927** | **31.7708** | **578.41 KB** |
17+
| Dictionary_Remove | OptimizedForPositionalSearch | 400.2 us | 2.0390 us | 1.9073 us | 1.00 | 0.00 | 83.0078 | 27.3438 | 398.72 KB |

0 commit comments

Comments
 (0)