Skip to content

Commit

Permalink
Update benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
Wsm2110 committed Nov 23, 2024
1 parent 80763cd commit d9b2894
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 71 deletions.
171 changes: 102 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Faster.Map
# Faster.Map

The goal of Faster.Map is to create a more efficient and performant alternative to the Dictionary and ConcurrentDictionary classes provided by .NET.
These standard collections are widely used for key-value pair storage in .NET applications, but they have certain limitations, particularly in high-performance and concurrent scenarios.
Expand Down Expand Up @@ -243,76 +243,109 @@ BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3880/23H2/2023Update/SunValley3

### Get String Benchmark

| Method | Length | Mean (ms) | Error (ms) | StdDev (ms) | Allocated |
|-------------------|---------|-----------------|---------------|---------------|-----------|
| DenseMap_Default | 100 | 0.7877 | 0.00488 | 0.00407 | - |
| DenseMap_Xxhash3 | 100 | 0.5638 | 0.00237 | 0.00210 | - |
| DenseMap_GxHash | 100 | 0.4934 | 0.00495 | 0.00463 | - |
| **DenseMap_FastHash** | **100** | **0.4423** | 0.00184 | 0.00144 | - |
| RobinhoodMap | 100 | 0.6755 | 0.00825 | 0.00771 | - |
| Dictionary | 100 | 0.6573 | 0.01266 | 0.01408 | - |
| DenseMap_Default | 1000 |7.9540 | 0.15528 | 0.13765 | - |
| DenseMap_Xxhash3 | 1000 | 5.9863 | 0.11213 | 0.11013 | - |
| DenseMap_GxHash | 1000 | 5.2577 | 0.03646 | 0.03411 | - |
| **DenseMap_FastHash** | **1000** | **4.5143** | 0.08599 | 0.09558 | - |
| RobinhoodMap | 1000 | 7.8287 | 0.05559 | 0.04928 | - |
| Dictionary | 1000 | 7.4062 | 0.13805 | 0.12914 | - |
| DenseMap_Default | 10000 | 115.7674 | 0.37631 | 0.33359 | - |
| DenseMap_Xxhash3 | 10000 | 89.3335 | 0.30373 | 0.23713 | - |
| DenseMap_GxHash | 10000 | 89.3103 | 0.52041 | 0.46133 | - |
| **DenseMap_FastHash** | **10000** | **81.7969** | 0.61676 | 0.54674 | - |
| RobinhoodMap | 10000 | 111.0056 | 1.03930 | 0.97216 | - |
| Dictionary | 10000 | 142.7456 | 0.56217 | 0.49835 | - |
| DenseMap_Default | 100000 | 1567.0900 | 17.38346 | 14.51598 | 1 B |
| DenseMap_Xxhash3 | 100000 | 1154.3523 | 3.08295 | 2.73296 | 1 B |
| DenseMap_GxHash | 100000 | 1215.4789 | 4.05174 | 3.16333 | 1 B |
| **DenseMap_FastHash** | **100000** | **1032.0671** | 10.77159 | 8.99477 | 1 B |
| RobinhoodMap | 100000 | 1864.2588 | 22.85317 | 19.08343 | 1 B |
| Dictionary | 100000 | 1882.8305 | 35.33849 | 42.06796 | 1 B |
| DenseMap_Default | 200000 | 3627.3379 | 68.77079 | 86.97303 | 3 B |
| DenseMap_Xxhash3 | 200000 | 2558.1723 | 10.47182 | 8.74444 | 3 B |
| DenseMap_GxHash | 200000 | 2661.8776 | 49.53749 | 43.91369 | 3 B |
| **DenseMap_FastHash** | **200000 ** | **2252.3690** | 35.63210 | 33.33029 | 3 B |
| RobinhoodMap | 200000 | 5201.6671 | 55.90280 | 49.55637 | 6 B |
| Dictionary | 200000 | 3900.8612 | 18.59936 | 15.53131 | 3 B |
| DenseMap_Default | 400000 | 8787.455 | 102.67141 | 96.03890 | 12 B |
| DenseMap_Xxhash3 | 400000 | 6620.0023 | 101.26791 | 89.77137 | 12 B |
| DenseMap_GxHash | 400000 | 6252.5252 | 24.02417 | 22.47222 | 6 B |
| **DenseMap_FastHash** | **400000** | **5609.3088** | 28.09836 | 23.46340 | 6 B |
| RobinhoodMap | 400000 | 17440.6204 | 115.65609 | 108.18478 | 23 B |
| Dictionary | 400000 | 8838.5934 | 52.30617 | 46.36806 | 12 B |
| DenseMap_Default | 800000 | 29897.6681 | 183.71964 | 162.86268 | 23 B |
| DenseMap_Xxhash3 | 800000 | 23740.6419 | 461.06354 | 512.47090 | 23 B |
| DenseMap_GxHash | 800000 | 18662.8382 | 163.51705 | 136.54414 | 23 B |
| **DenseMap_FastHash** | **800000** | **17516.7710** | 173.69462 | 145.04287 | 23 B |
| RobinhoodMap | 800000 | 45399.0412 | 752.47203 | 703.86280 | 67 B |
| Dictionary | 800000 | 26328.6341 | 122.59703 | 95.71569 | 23 B |
| DenseMap_Default | 1000000 | 43746.8455 | 255.44660 | 238.94491 | 67 B |
| DenseMap_Xxhash3 | 1000000 | 30988.9967 | 138.94068 | 129.96520 | 46 B |
| DenseMap_GxHash | 1000000 | 23901.5047 | 91.89792 | 81.46511 | 23 B |
| **DenseMap_FastHash** | **1000000** | **22579.2328** | 60.22346 | 50.28931 | 23 B |
| RobinhoodMap | 1000000 | 62235.2917 | 339.28829 | 317.37048 | 92 B |
| Dictionary | 1000000 | 34091.9248 | 387.37558 | 343.39836 | 49 B |
This benchmark compares the performance of different hash map implementations for various input sizes. The **Mean (ms)** column represents the average time taken for each operation. The fastest implementation for each input size is highlighted in bold.

| Method | Length | Mean (ms) | Error (ms) | StdDev (ms) | Allocated |
|-------------------|----------|----------------|----------------|----------------|-----------|
| DenseMap_Default | 100 | 0.000788 | 0.000005 | 0.000004 | - |
| DenseMap_Xxhash3 | 100 | 0.000564 | 0.000002 | 0.000002 | - |
| DenseMap_GxHash | 100 | 0.000493 | 0.000005 | 0.000005 | - |
| **DenseMap_FastHash** 🏆 | **100** | **0.000442** | **0.000002** | **0.000001** | **-** |
| RobinhoodMap | 100 | 0.000676 | 0.000008 | 0.000008 | - |
| Dictionary | 100 | 0.000657 | 0.000013 | 0.000014 | - |
| DenseMap_Default | 1000 | 0.007954 | 0.000155 | 0.000138 | - |
| DenseMap_Xxhash3 | 1000 | 0.005986 | 0.000112 | 0.000110 | - |
| DenseMap_GxHash | 1000 | 0.005258 | 0.000036 | 0.000034 | - |
| **DenseMap_FastHash** 🏆 | **1000** | **0.004514** | **0.000086** | **0.000096** | **-** |
| RobinhoodMap | 1000 | 0.007829 | 0.000056 | 0.000049 | - |
| Dictionary | 1000 | 0.007406 | 0.000138 | 0.000129 | - |
| DenseMap_Default | 10000 | 0.115767 | 0.000376 | 0.000334 | - |
| DenseMap_Xxhash3 | 10000 | 0.089334 | 0.000304 | 0.000237 | - |
| DenseMap_GxHash | 10000 | 0.089310 | 0.000520 | 0.000461 | - |
| **DenseMap_FastHash** 🏆 | **10000** | **0.081797** | **0.000617** | **0.000547** | **-** |
| RobinhoodMap | 10000 | 0.111006 | 0.001039 | 0.000972 | - |
| Dictionary | 10000 | 0.142746 | 0.000562 | 0.000498 | - |
| DenseMap_Default | 100000 | 1.567090 | 0.017383 | 0.014516 | 1 B |
| DenseMap_Xxhash3 | 100000 | 1.154352 | 0.003083 | 0.002733 | 1 B |
| DenseMap_GxHash | 100000 | 1.215479 | 0.004052 | 0.003163 | 1 B |
| **DenseMap_FastHash** 🏆 | **100000** | **1.032067** | **0.010772** | **0.008995** | **1 B** |
| RobinhoodMap | 100000 | 1.864259 | 0.022853 | 0.019083 | 1 B |
| Dictionary | 100000 | 1.882831 | 0.035338 | 0.042068 | 1 B |
| DenseMap_Default | 200000 | 3.627338 | 0.068771 | 0.086973 | 3 B |
| DenseMap_Xxhash3 | 200000 | 2.558172 | 0.010472 | 0.008744 | 3 B |
| DenseMap_GxHash | 200000 | 2.661878 | 0.049537 | 0.043914 | 3 B |
| **DenseMap_FastHash** 🏆 | **200000** | **2.252369** | **0.035632** | **0.033330** | **3 B** |
| RobinhoodMap | 200000 | 5.201667 | 0.055903 | 0.049556 | 6 B |
| Dictionary | 200000 | 3.900861 | 0.018599 | 0.015531 | 3 B |
| DenseMap_Default | 400000 | 8.787456 | 0.102671 | 0.096039 | 12 B |
| DenseMap_Xxhash3 | 400000 | 6.620002 | 0.101268 | 0.089771 | 12 B |
| DenseMap_GxHash | 400000 | 6.252525 | 0.024024 | 0.022472 | 6 B |
| **DenseMap_FastHash** 🏆 | **400000** | **5.609309** | **0.028098** | **0.023463** | **6 B** |
| RobinhoodMap | 400000 | 17.440620 | 0.115656 | 0.108185 | 23 B |
| Dictionary | 400000 | 8.838593 | 0.052306 | 0.046368 | 12 B |
| DenseMap_Default | 800000 | 29.897668 | 0.183720 | 0.162863 | 23 B |
| DenseMap_Xxhash3 | 800000 | 23.740642 | 0.461064 | 0.512471 | 23 B |
| DenseMap_GxHash | 800000 | 18.662838 | 0.163517 | 0.136544 | 23 B |
| **DenseMap_FastHash** 🏆 | **800000** | **17.516771** | **0.173695** | **0.145043** | **23 B** |
| RobinhoodMap | 800000 | 45.399041 | 0.752472 | 0.703863 | 67 B |
| Dictionary | 800000 | 26.328634 | 0.122597 | 0.095716 | 23 B |
| DenseMap_Default | 1000000 | 43.746846 | 0.255447 | 0.238945 | 67 B |
| DenseMap_Xxhash3 | 1000000 | 30.988997 | 0.138941 | 0.129965 | 46 B |
| DenseMap_GxHash | 1000000 | 23.901505 | 0.091898 | 0.081465 | 23 B |
| **DenseMap_FastHash** 🏆 | **1000000** | **22.579233** | **0.060223** | **0.050289** | **23 B** |
| RobinhoodMap | 1000000 | 62.235292 | 0.339288 | 0.317370 | 92 B |
| Dictionary | 1000000 | 34.091925 | 0.387376 | 0.343398 | 49 B |

🏆 indicates the fastest implementation for each input size.

---

### Add string benchmark

| Method | Length | Mean | Error | StdDev | Allocated |
|--------------|----------|-------------:|-----------:|-----------:|----------:|
| **DenseMap** | **10000** | **0.06328 ms** | **0.00119 ms** | **0.00117 ms** | **-** |
| RobinhoodMap | 10000 | 0.11138 ms | 0.00089 ms | 0.00083 ms | - |
| Dictionary | 10000 | 0.14030 ms | 0.00101 ms | 0.00084 ms | - |
| **DenseMap** | **100000** | **0.89303 ms** | **0.00092 ms** | **0.00081 ms** | **1 B** |
| RobinhoodMap | 100000 | 1.74953 ms | 0.00542 ms | 0.00507 ms | 1 B |
| Dictionary | 100000 | 1.82837 ms | 0.00251 ms | 0.00222 ms | 1 B |
| **DenseMap** | **400000** | **5.69521 ms** | **0.08819 ms** | **0.07364 ms** | **6 B** |
| RobinhoodMap | 400000 | 17.48812 ms | 0.11409 ms | 0.10672 ms | 23 B |
| Dictionary | 400000 | 8.90541 ms | 0.10513 ms | 0.09319 ms | 12 B |
| **DenseMap** | **900000** | **25.03465 ms** | **0.15671 ms** | **0.12235 ms** | **23 B** |
| RobinhoodMap | 900000 | 52.43294 ms | 0.71473 ms | 0.63359 ms | 74 B |
| Dictionary | 900000 | 29.69477 ms | 0.19468 ms | 0.15200 ms | 23 B |
| **DenseMap** | **1000000** | **33.72319 ms** | **0.28449 ms** | **0.25219 ms** | **49 B** |
| RobinhoodMap | 1000000 | 62.24546 ms | 0.39693 ms | 0.37129 ms | 92 B |
| Dictionary | 1000000 | 34.00727 ms | 0.10688 ms | 0.08925 ms | 49 B |

| Method | Length | Mean (ms) | Error (ms) | StdDev (ms) | Median (ms) | Allocated |
|-------------------|----------|----------------|----------------|----------------|---------------|------------|
| DenseMap | 100 | 0.009141 | 0.000963 | 0.002808 | 0.009450 | 2368 B |
| DenseMap_Xxhash3 | 100 | 0.004088 | 0.000222 | 0.000640 | 0.004100 | 64 B |
| DenseMap_GxHash | 100 | 0.008854 | 0.000223 | 0.000641 | 0.008750 | 64 B |
| DenseMap_FastHash | 100 | 0.007225 | 0.000270 | 0.000780 | 0.007150 | 64 B |
| RobinhoodMap | 100 | 0.004639 | 0.000712 | 0.002053 | 0.003900 | 64 B |
| **Dictionary** 🏆 | **100** | **0.002654** | **0.000250** | **0.000722** | **0.002600** | **64 B** |
| DenseMap | 1000 | 0.038267 | 0.004567 | 0.013322 | 0.041000 | 35488 B |
| DenseMap_Xxhash3 | 1000 | 0.024968 | 0.000657 | 0.001741 | 0.024400 | 35200 B |
| DenseMap_GxHash | 1000 | 0.025384 | 0.001586 | 0.004314 | 0.023550 | 35200 B |
| DenseMap_FastHash | 1000 | 0.022692 | 0.001391 | 0.003736 | 0.021400 | 35200 B |
| RobinhoodMap | 1000 | 0.019667 | 0.000397 | 0.000424 | 0.019550 | 64 B |
| **Dictionary** 🏆 | **1000** | **0.015185** | **0.000311** | **0.000726** | **0.015100** | **64 B** |
| DenseMap | 10000 | 0.107737 | 0.002145 | 0.004429 | 0.108150 | 2656 B |
| DenseMap_Xxhash3 | 10000 | 0.103542 | 0.001024 | 0.000799 | 0.103300 | 3040 B |
| DenseMap_GxHash | 10000 | 0.106641 | 0.002131 | 0.003731 | 0.104900 | 3040 B |
| **DenseMap_FastHash** 🏆 | **10000** | **0.095307** | **0.001898** | **0.004003** | **0.094000** | **3040 B** |
| RobinhoodMap | 10000 | 0.166072 | 0.003311 | 0.007740 | 0.164200 | 3040 B |
| Dictionary | 10000 | 0.164537 | 0.003246 | 0.006176 | 0.164250 | 3040 B |
| DenseMap | 100000 | 1.300044 | 0.025983 | 0.046853 | 1.290900 | 3040 B |
| DenseMap_Xxhash3 | 100000 | 1.299239 | 0.025501 | 0.032250 | 1.293900 | 3040 B |
| DenseMap_GxHash | 100000 | 1.366111 | 0.027331 | 0.069069 | 1.347800 | 3040 B |
| **DenseMap_FastHash** 🏆 | **100000** | **1.140335** | **0.021935** | **0.025261** | **1.131150** | **3040 B** |
| RobinhoodMap | 100000 | 2.208244 | 0.043742 | 0.042960 | 2.211900 | 3040 B |
| Dictionary | 100000 | 2.046059 | 0.040840 | 0.069349 | 2.032900 | 3040 B |
| DenseMap | 200000 | 3.099234 | 0.061630 | 0.115755 | 3.084000 | 3040 B |
| DenseMap_Xxhash3 | 200000 | 2.987612 | 0.059547 | 0.079493 | 2.977100 | 3040 B |
| DenseMap_GxHash | 200000 | 3.052873 | 0.059889 | 0.104891 | 3.020350 | 3040 B |
| **DenseMap_FastHash** 🏆 | **200000** | **2.696498** | **0.053552** | **0.097922** | **2.690650** | **3040 B** |
| RobinhoodMap | 200000 | 5.625506 | 0.128638 | 0.369088 | 5.483200 | 3040 B |
| Dictionary | 200000 | 4.749739 | 0.093001 | 0.268328 | 4.677800 | 3040 B |
| DenseMap | 400000 | 8.393189 | 0.263742 | 0.769349 | 8.089750 | 3040 B |
| DenseMap_Xxhash3 | 400000 | 7.750054 | 0.151604 | 0.207517 | 7.750400 | 3040 B |
| DenseMap_GxHash | 400000 | 7.584241 | 0.144610 | 0.148504 | 7.546400 | 3040 B |
| **DenseMap_FastHash** 🏆 | **400000** | **7.059086** | **0.137344** | **0.196975** | **7.066150** | **3040 B** |
| RobinhoodMap | 400000 | 15.510240 | 0.308929 | 0.637992 | 15.405350 | 3040 B |
| Dictionary | 400000 | 11.463663 | 0.262649 | 0.766160 | 11.352950 | 3040 B |
| DenseMap | 800000 | 18.639193 | 0.361017 | 0.517760 | 18.480550 | 3040 B |
| DenseMap_Xxhash3 | 800000 | 19.099343 | 0.363598 | 0.322320 | 19.057950 | 3040 B |
| DenseMap_GxHash | 800000 | 18.050536 | 0.212600 | 0.188464 | 18.033900 | 3040 B |
| **DenseMap_FastHash** 🏆 | **800000** | **18.712627** | **0.512323** | **1.510596** | **19.412700** | **3040 B** |
| RobinhoodMap | 800000 | 37.518002 | 0.738743 | 1.350833 | 36.844850 | 3040 B |
| Dictionary | 800000 | 29.891827 | 0.595388 | 1.526206 | 29.250100 | 3040 B |

🏆 indicates the fastest implementation for each input size.

41 changes: 40 additions & 1 deletion benchmarks/Faster.Map.Benchmark/AddStringBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ public class AddStringBenchmark
private DenseMap<string, string> _dense;
private Dictionary<string, string> dic;
private RobinhoodMap<string, string> _robinhoodMap;
private DenseMap<string, string> _denseMapxxHash;
private DenseMap<string, string> _denseMapGxHash;
private DenseMap<string, string> _denseMapFastHash;

private string[] keys;

#endregion

#region Properties

[Params(10000, 100000, 400000, 800000, 900000)]
[Params(100, 1000, 10000, 100000, 200000, 400000, 800000)]

public uint Length { get; set; }

#endregion
Expand Down Expand Up @@ -57,6 +61,10 @@ public void Setup()
int dicLength = HashHelpers.GetPrime((int)Length);

_dense = new DenseMap<string, string>(length, 0.875, new XxHash3StringHasher());
_denseMapxxHash = new DenseMap<string, string>(length, 0.875, new XxHash3StringHasher());
_denseMapGxHash = new DenseMap<string, string>(length, 0.875, new GxHasher());
_denseMapFastHash = new DenseMap<string, string>(length, 0.875, new FastHasher());

dic = new Dictionary<string, string>(dicLength);
_robinhoodMap = new RobinhoodMap<string, string>(length * 2);
}
Expand All @@ -73,6 +81,37 @@ public void DenseMap()
}
}


[Benchmark]
public void DenseMap_Xxhash3()
{
for (int i = 0; i < Length; i++)
{
var key = keys[i];
_denseMapxxHash.Emplace(key, key);
}
}

[Benchmark]
public void DenseMap_GxHash()
{
for (int i = 0; i < Length; i++)
{
var key = keys[i];
_denseMapGxHash.Emplace(key, key);
}
}

[Benchmark]
public void DenseMap_FastHash()
{
for (int i = 0; i < Length; i++)
{
var key = keys[i];
_denseMapFastHash.Emplace(key, key);
}
}

[Benchmark]
public void RobinhoodMap()
{
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/Faster.Map.Benchmark/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<StringBenchmark>();
BenchmarkRunner.Run<AddStringBenchmark>(new DebugInProcessConfig());
//BenchmarkRunner.Run<AddAndResizeBenchmark>();
//BenchmarkRunner.Run<UpdateBenchmark>();
//BenchmarkRunner.Run<RemoveBenchmark>();
Expand Down

0 comments on commit d9b2894

Please sign in to comment.