I have used dashmap, which has sort of like the popular high-performance replacement for RwLock<HashMap<K, V>>. Are there any similar crates for BTreeMap? I was working on implementing a C++ data structure called Masstree in Rust, it would also be something you would use instead of RwLock<BTreeMap>, but I can't find any good crates to study as reference material for rust code patterns.
I know that it is a niche use case, so please don't bother with 'why? it's unnecessary' replies :'D
You could check out crossbeam_skiplist, it isn't btree-based but it's a concurrent sorted map nonetheless.
1 Like
That and the IndexSetBTreeMap from indexset were the only similar things I could find. But in benchmarks they seem to be performing worse than the initial unoptimized masstree for some reason, I was looking for references for highly optimized alternatives, someone suggessted congee but it's also different and has a big constraint on key length (fixed 8-byte)
Timer precision: 30 ns
concurrent_maps fastest โ slowest โ median โ mean โ samples โ iters
โโ 01_single_get โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 100 48.15 ns โ 122.3 ns โ 48.32 ns โ 49.08 ns โ 100 โ 6400
โ โ โฐโ 1000 55.04 ns โ 137.5 ns โ 55.99 ns โ 56.82 ns โ 100 โ 6400
โ โโ masstree โ โ โ โ โ
โ โ โโ 100 20.38 ns โ 46.05 ns โ 20.53 ns โ 20.99 ns โ 100 โ 25600
โ โ โฐโ 1000 26.24 ns โ 26.64 ns โ 26.32 ns โ 26.31 ns โ 100 โ 12800
โ โฐโ skipmap โ โ โ โ โ
โ โโ 100 48.15 ns โ 51.78 ns โ 48.32 ns โ 49.58 ns โ 100 โ 6400
โ โฐโ 1000 100.7 ns โ 174.6 ns โ 101.3 ns โ 102 ns โ 100 โ 3200
โโ 02_single_insert โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 100 453 ns โ 637.1 ns โ 490.6 ns โ 505.7 ns โ 100 โ 800
โ โ โฐโ 1000 529.3 ns โ 1.047 ยตs โ 584.5 ns โ 606.1 ns โ 100 โ 800
โ โโ masstree โ โ โ โ โ
โ โ โโ 100 94.51 ns โ 279.5 ns โ 98.57 ns โ 118.2 ns โ 100 โ 3200
โ โ โฐโ 1000 117 ns โ 305.5 ns โ 120.1 ns โ 125.6 ns โ 100 โ 3200
โ โฐโ skipmap โ โ โ โ โ
โ โโ 100 173.3 ns โ 368.4 ns โ 218 ns โ 214.8 ns โ 100 โ 3200
โ โฐโ 1000 151.1 ns โ 381.6 ns โ 161.8 ns โ 164.3 ns โ 100 โ 800
โโ 03_concurrent_reads โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 1 180.6 ยตs โ 434 ยตs โ 188.8 ยตs โ 202.3 ยตs โ 100 โ 100
โ โ โโ 2 368.4 ยตs โ 884.9 ยตs โ 442.8 ยตs โ 456 ยตs โ 100 โ 100
โ โ โโ 4 926.2 ยตs โ 1.475 ms โ 1.074 ms โ 1.077 ms โ 100 โ 100
โ โ โฐโ 8 2.361 ms โ 3.36 ms โ 2.715 ms โ 2.773 ms โ 100 โ 100
โ โโ masstree โ โ โ โ โ
โ โ โโ 1 76.23 ยตs โ 138 ยตs โ 100.6 ยตs โ 99.19 ยตs โ 100 โ 100
โ โ โโ 2 105.3 ยตs โ 225.6 ยตs โ 152.6 ยตs โ 153 ยตs โ 100 โ 100
โ โ โโ 4 172.5 ยตs โ 347.9 ยตs โ 222.6 ยตs โ 227.7 ยตs โ 100 โ 100
โ โ โฐโ 8 263.1 ยตs โ 566 ยตs โ 306 ยตs โ 320.6 ยตs โ 100 โ 100
โ โฐโ skipmap โ โ โ โ โ
โ โโ 1 150 ยตs โ 293.6 ยตs โ 162.8 ยตs โ 170.9 ยตs โ 100 โ 100
โ โโ 2 197.3 ยตs โ 372.4 ยตs โ 224.5 ยตs โ 236.4 ยตs โ 100 โ 100
โ โโ 4 276.7 ยตs โ 540.3 ยตs โ 332.5 ยตs โ 335 ยตs โ 100 โ 100
โ โฐโ 8 404.8 ยตs โ 583.5 ยตs โ 438 ยตs โ 457.7 ยตs โ 100 โ 100
โโ 04_concurrent_writes โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 1 97.91 ยตs โ 180.9 ยตs โ 102.8 ยตs โ 106.5 ยตs โ 100 โ 100
โ โ โโ 2 166.6 ยตs โ 308.9 ยตs โ 205.6 ยตs โ 208.6 ยตs โ 100 โ 100
โ โ โฐโ 4 266.2 ยตs โ 494.1 ยตs โ 317.1 ยตs โ 320.8 ยตs โ 100 โ 100
โ โโ masstree โ โ โ โ โ
โ โ โโ 1 40.87 ยตs โ 101.5 ยตs โ 53.82 ยตs โ 54.9 ยตs โ 100 โ 100
โ โ โโ 2 63.84 ยตs โ 378.9 ยตs โ 86.93 ยตs โ 91.07 ยตs โ 100 โ 100
โ โ โฐโ 4 108.5 ยตs โ 331.1 ยตs โ 137.5 ยตs โ 142.3 ยตs โ 100 โ 100
โ โฐโ skipmap โ โ โ โ โ
โ โโ 1 62.1 ยตs โ 103.2 ยตs โ 67.4 ยตs โ 69.59 ยตs โ 100 โ 100
โ โโ 2 93.73 ยตs โ 231 ยตs โ 107.3 ยตs โ 113 ยตs โ 100 โ 100
โ โฐโ 4 132.7 ยตs โ 244 ยตs โ 158.6 ยตs โ 159.5 ยตs โ 100 โ 100
I suppose the benchmarks are these, correct?
It seems you're benchmarking the insertion/read of 8 bytes strings, but isn't that exactly the threshold for the optimization that masstree has? All the other maps are forces to pay the cost of a Vec allocation and indirection when comparing, while yours doesn't. Sure, in practice it might help depending on your usecase, but it won't help if you want to compare the underlying algorithm of the map.
The patterns you use while reading/inserting also seem to minimize collisions. You never have threads reading and writing the same key, they mostly read/write sequential non-overlapping ranges of keys. It would be more interesting to see what happens when they read/write the same range of keys, or random keys.
Finally, 4 threads seem very few for benchmarking a concurrent algorithm. A good concurrent data structure should be able to scale to tens of threads at least, though I can see why this might be difficult to benchmark on consumer hardware.
3 Likes
Yes, the implementation is still in very early stages and currently I am working out how to fix some major memory leak issues due to not properly handling memory reclamation. For example, the current code crashes for write heavy workloads with higher number of threads. Which is why I was looking for other references to see how to properly work this out. The original implementation uses an epoch based reclamation model, but I decided to go with a hyaline based reclamation model using a newer crate called seize. This made it harder to follow the original reference but also improved read performance quite a bit, so I am trying to stick to it.
The benchmarks may regress a lot (or improve) after the memory reclamation is implemented properly. So the current benchmarks may not be a fair comparison :'D
My point was that the benchmarks themselves are not very fair or representative of real situations. Fixing issue is the crate will not change this.
1 Like
Of course, I will just add longer length keys that will force masstree through multiple layers, more complex and realistic access patterns and contention cases where threads write to overlapping keys. That should give a more objective view of the current situation, but the real problem from an implementation perspective is that the 'better' benchmarks don't really matter when there are major soundness issues in the implementation. Sorry if you got the impression that 'I have a better thing here' :'D
Yeah, you were right, here's the proper benchmark results. It ironically does better ONLY on single threads (consistently) compared to the other concurrent data structures at its current state. But about the inline 8-byte key optimization, it wasn't really my fault here. The original paper for the algorithm specifically optimizes for this use case . The other implementations have to allocate keys on the heap.
concurrent_maps fastest โ slowest โ median โ mean โ samples โ iters
โโ 01_get_by_key_size โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 8B 186.3 ยตs โ 300.7 ยตs โ 200.2 ยตs โ 229.3 ยตs โ 100 โ 100
โ โ โโ 16B 189.6 ยตs โ 219.8 ยตs โ 191.4 ยตs โ 193.7 ยตs โ 100 โ 100
โ โ โโ 24B 192.8 ยตs โ 451.4 ยตs โ 196.4 ยตs โ 209 ยตs โ 100 โ 100
โ โ โฐโ 32B 181.9 ยตs โ 204.5 ยตs โ 185.5 ยตs โ 186.9 ยตs โ 100 โ 100
โ โโ masstree โ โ โ โ โ
โ โ โโ 8B 80.99 ยตs โ 104.7 ยตs โ 82.78 ยตs โ 83.96 ยตs โ 100 โ 100
โ โ โโ 16B 92.29 ยตs โ 107.5 ยตs โ 94.15 ยตs โ 95.22 ยตs โ 100 โ 100
โ โ โโ 24B 91.86 ยตs โ 110.4 ยตs โ 92.98 ยตs โ 94.24 ยตs โ 100 โ 100
โ โ โฐโ 32B 93.33 ยตs โ 107.2 ยตs โ 94.24 ยตs โ 95.64 ยตs โ 100 โ 100
โ โฐโ skipmap โ โ โ โ โ
โ โโ 8B 268.7 ยตs โ 293.9 ยตs โ 272.9 ยตs โ 273.6 ยตs โ 100 โ 100
โ โโ 16B 269.8 ยตs โ 300.7 ยตs โ 273.1 ยตs โ 274.8 ยตs โ 100 โ 100
โ โโ 24B 271.9 ยตs โ 292.7 ยตs โ 275.4 ยตs โ 276.6 ยตs โ 100 โ 100
โ โฐโ 32B 252.9 ยตs โ 280.4 ยตs โ 256.6 ยตs โ 258.2 ยตs โ 100 โ 100
โโ 02_insert_by_key_size โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 8B 522.8 ยตs โ 545 ยตs โ 530.3 ยตs โ 530.4 ยตs โ 100 โ 100
โ โ โโ 16B 521.3 ยตs โ 548.7 ยตs โ 527.9 ยตs โ 528.1 ยตs โ 100 โ 100
โ โ โโ 24B 519.3 ยตs โ 571.8 ยตs โ 526 ยตs โ 526.8 ยตs โ 100 โ 100
โ โ โฐโ 32B 507.8 ยตs โ 526.1 ยตs โ 514.1 ยตs โ 514.5 ยตs โ 100 โ 100
โ โโ masstree โ โ โ โ โ
โ โ โโ 8B 63.89 ยตs โ 74.37 ยตs โ 64.21 ยตs โ 65.07 ยตs โ 100 โ 100
โ โ โโ 16B 200.3 ยตs โ 218.2 ยตs โ 202.4 ยตs โ 203.4 ยตs โ 100 โ 100
โ โ โโ 24B 209.2 ยตs โ 237.1 ยตs โ 212.1 ยตs โ 213.3 ยตs โ 100 โ 100
โ โ โฐโ 32B 219.1 ยตs โ 241 ยตs โ 222 ยตs โ 223.2 ยตs โ 100 โ 100
โ โฐโ skipmap โ โ โ โ โ
โ โโ 8B 163.4 ยตs โ 187.9 ยตs โ 166.1 ยตs โ 167.2 ยตs โ 100 โ 100
โ โโ 16B 162.6 ยตs โ 185.3 ยตs โ 165.4 ยตs โ 166.3 ยตs โ 100 โ 100
โ โโ 24B 162.8 ยตs โ 180 ยตs โ 165.7 ยตs โ 166.4 ยตs โ 100 โ 100
โ โฐโ 32B 148.8 ยตs โ 179.6 ยตs โ 151.5 ยตs โ 152.6 ยตs โ 100 โ 100
โโ 03_concurrent_reads_scaling โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 1 9.176 ms โ 14.37 ms โ 11.79 ms โ 11.94 ms โ 100 โ 100
โ โ โโ 2 12.43 ms โ 23.12 ms โ 14.95 ms โ 15.56 ms โ 100 โ 100
โ โ โโ 4 15.15 ms โ 33.08 ms โ 26.59 ms โ 26.46 ms โ 100 โ 100
โ โ โโ 8 37.2 ms โ 67.1 ms โ 53 ms โ 53.11 ms โ 100 โ 100
โ โ โโ 16 101.5 ms โ 136.8 ms โ 117.9 ms โ 118.3 ms โ 100 โ 100
โ โ โฐโ 32 216.8 ms โ 269.3 ms โ 249.3 ms โ 248.6 ms โ 100 โ 100
โ โโ masstree โ โ โ โ โ
โ โ โโ 1 7.631 ms โ 11.48 ms โ 9.847 ms โ 9.454 ms โ 100 โ 100
โ โ โโ 2 9.673 ms โ 20.49 ms โ 18.49 ms โ 18.31 ms โ 100 โ 100
โ โ โโ 4 18.56 ms โ 42.79 ms โ 41.85 ms โ 36.72 ms โ 100 โ 100
โ โ โโ 8 51.31 ms โ 97.08 ms โ 92.97 ms โ 82.56 ms โ 100 โ 100
โ โ โโ 16 106.3 ms โ 213.4 ms โ 174.9 ms โ 174.5 ms โ 100 โ 100
โ โ โฐโ 32 248.2 ms โ 457.4 ms โ 337.3 ms โ 348.6 ms โ 100 โ 100
โ โฐโ skipmap โ โ โ โ โ
โ โโ 1 11.14 ms โ 15.18 ms โ 12.96 ms โ 12.97 ms โ 100 โ 100
โ โโ 2 15.04 ms โ 18.8 ms โ 16.78 ms โ 16.83 ms โ 100 โ 100
โ โโ 4 19.08 ms โ 39.03 ms โ 32.73 ms โ 32.42 ms โ 100 โ 100
โ โโ 8 34.58 ms โ 69.68 ms โ 54.76 ms โ 54.17 ms โ 100 โ 100
โ โโ 16 95.51 ms โ 145.6 ms โ 118.7 ms โ 117.8 ms โ 100 โ 100
โ โฐโ 32 202.2 ms โ 279.8 ms โ 246.6 ms โ 244.9 ms โ 100 โ 100
โโ 04_concurrent_reads_long_keys โ โ โ โ โ
โ โโ indexset_32b โ โ โ โ โ
โ โ โโ 1 4.244 ms โ 7.161 ms โ 5.7 ms โ 5.582 ms โ 100 โ 100
โ โ โโ 2 6.093 ms โ 14.03 ms โ 8.055 ms โ 9.284 ms โ 100 โ 100
โ โ โโ 4 10.26 ms โ 20.93 ms โ 15.69 ms โ 15.52 ms โ 100 โ 100
โ โ โโ 8 25.89 ms โ 42.76 ms โ 33.75 ms โ 33.95 ms โ 100 โ 100
โ โ โฐโ 16 63.39 ms โ 85.28 ms โ 73.51 ms โ 73.81 ms โ 100 โ 100
โ โโ masstree_32b โ โ โ โ โ
โ โ โโ 1 3.508 ms โ 6.493 ms โ 5.132 ms โ 5.243 ms โ 100 โ 100
โ โ โโ 2 5.308 ms โ 12.58 ms โ 10.88 ms โ 10.09 ms โ 100 โ 100
โ โ โโ 4 12.05 ms โ 25.92 ms โ 18.81 ms โ 18.41 ms โ 100 โ 100
โ โ โโ 8 27.45 ms โ 58.21 ms โ 43.32 ms โ 44.05 ms โ 100 โ 100
โ โ โฐโ 16 65.8 ms โ 119.5 ms โ 87.25 ms โ 90.71 ms โ 100 โ 100
โ โฐโ skipmap_32b โ โ โ โ โ
โ โโ 1 5.047 ms โ 7.937 ms โ 6.049 ms โ 6.182 ms โ 100 โ 100
โ โโ 2 7.509 ms โ 14.68 ms โ 8.992 ms โ 9.616 ms โ 100 โ 100
โ โโ 4 15.9 ms โ 25.97 ms โ 19.78 ms โ 19.82 ms โ 100 โ 100
โ โโ 8 23.76 ms โ 39.68 ms โ 32.59 ms โ 32.86 ms โ 100 โ 100
โ โฐโ 16 57.95 ms โ 78.34 ms โ 68.41 ms โ 68.82 ms โ 100 โ 100
But there's a twist... the C++ implementation used a custom memory allocator (this is way out of my skill levels to even try). Iif we just change the global memory allocator to mimalloc it becomes the faster implementation in all the same benches. The standard global allocator is simply not optimal for the allocation patterns this data structure uses.
Timer precision: 30 ns
concurrent_maps fastest โ slowest โ median โ mean โ samples โ iters
โโ 01_get_by_key_size โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 8B 174.9 ยตs โ 193.3 ยตs โ 176.5 ยตs โ 177.8 ยตs โ 100 โ 100
โ โ โโ 16B 181.8 ยตs โ 205.2 ยตs โ 183.9 ยตs โ 185.6 ยตs โ 100 โ 100
โ โ โโ 24B 178.2 ยตs โ 196.6 ยตs โ 179.6 ยตs โ 181.3 ยตs โ 100 โ 100
โ โ โฐโ 32B 175.1 ยตs โ 194.5 ยตs โ 177.8 ยตs โ 178.9 ยตs โ 100 โ 100
โ โโ masstree โ โ โ โ โ
โ โ โโ 8B 74.53 ยตs โ 98.02 ยตs โ 75.68 ยตs โ 77.33 ยตs โ 100 โ 100
โ โ โโ 16B 89.61 ยตs โ 106.2 ยตs โ 91.18 ยตs โ 92.05 ยตs โ 100 โ 100
โ โ โโ 24B 90.55 ยตs โ 105 ยตs โ 91.85 ยตs โ 92.86 ยตs โ 100 โ 100
โ โ โฐโ 32B 90.57 ยตs โ 103.5 ยตs โ 91.28 ยตs โ 92.32 ยตs โ 100 โ 100
โ โฐโ skipmap โ โ โ โ โ
โ โโ 8B 256 ยตs โ 278.8 ยตs โ 257.8 ยตs โ 259.9 ยตs โ 100 โ 100
โ โโ 16B 272.3 ยตs โ 292.1 ยตs โ 275.2 ยตs โ 276.9 ยตs โ 100 โ 100
โ โโ 24B 251.7 ยตs โ 278.9 ยตs โ 254.6 ยตs โ 256.6 ยตs โ 100 โ 100
โ โฐโ 32B 248.5 ยตs โ 269.7 ยตs โ 251.6 ยตs โ 253 ยตs โ 100 โ 100
โโ 02_insert_by_key_size โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 8B 463.1 ยตs โ 491.1 ยตs โ 468.4 ยตs โ 468.8 ยตs โ 100 โ 100
โ โ โโ 16B 461.6 ยตs โ 484.5 ยตs โ 466.5 ยตs โ 466.4 ยตs โ 100 โ 100
โ โ โโ 24B 453.4 ยตs โ 503.9 ยตs โ 455.2 ยตs โ 458.3 ยตs โ 100 โ 100
โ โ โฐโ 32B 444.8 ยตs โ 469.1 ยตs โ 447.8 ยตs โ 449.2 ยตs โ 100 โ 100
โ โโ masstree โ โ โ โ โ
โ โ โโ 8B 35.71 ยตs โ 59.89 ยตs โ 35.87 ยตs โ 37.86 ยตs โ 100 โ 100
โ โ โโ 16B 104.4 ยตs โ 130.6 ยตs โ 105.9 ยตs โ 107.4 ยตs โ 100 โ 100
โ โ โโ 24B 109.3 ยตs โ 156 ยตs โ 111.6 ยตs โ 112.7 ยตs โ 100 โ 100
โ โ โฐโ 32B 111.9 ยตs โ 137.7 ยตs โ 114.1 ยตs โ 115.4 ยตs โ 100 โ 100
โ โฐโ skipmap โ โ โ โ โ
โ โโ 8B 145.2 ยตs โ 172.7 ยตs โ 151 ยตs โ 151.6 ยตs โ 100 โ 100
โ โโ 16B 145.4 ยตs โ 165.6 ยตs โ 147.2 ยตs โ 148.3 ยตs โ 100 โ 100
โ โโ 24B 134.4 ยตs โ 185.3 ยตs โ 138.1 ยตs โ 139 ยตs โ 100 โ 100
โ โฐโ 32B 132.1 ยตs โ 163.3 ยตs โ 135.1 ยตs โ 136 ยตs โ 100 โ 100
โโ 03_concurrent_reads_scaling โ โ โ โ โ
โ โโ indexset โ โ โ โ โ
โ โ โโ 1 5.518 ms โ 8.801 ms โ 7.008 ms โ 6.983 ms โ 100 โ 100
โ โ โโ 2 7.033 ms โ 11.95 ms โ 9.189 ms โ 9.18 ms โ 100 โ 100
โ โ โโ 4 9.854 ms โ 16.06 ms โ 13.06 ms โ 13.05 ms โ 100 โ 100
โ โ โโ 8 15.53 ms โ 19.93 ms โ 17.26 ms โ 17.39 ms โ 100 โ 100
โ โ โโ 16 28.25 ms โ 33.93 ms โ 30.72 ms โ 30.72 ms โ 100 โ 100
โ โ โฐโ 32 52.93 ms โ 62.44 ms โ 57.55 ms โ 57.69 ms โ 100 โ 100
โ โโ masstree โ โ โ โ โ
โ โ โโ 1 4.536 ms โ 6.213 ms โ 5.623 ms โ 5.51 ms โ 100 โ 100
โ โ โโ 2 5.712 ms โ 9.303 ms โ 7.342 ms โ 7.341 ms โ 100 โ 100
โ โ โโ 4 8.088 ms โ 13.08 ms โ 10.28 ms โ 10.2 ms โ 100 โ 100
โ โ โโ 8 11.39 ms โ 20.9 ms โ 15.05 ms โ 14.99 ms โ 100 โ 100
โ โ โโ 16 23.39 ms โ 31.51 ms โ 26.93 ms โ 26.98 ms โ 100 โ 100
โ โ โฐโ 32 46.32 ms โ 57.52 ms โ 51.09 ms โ 51.07 ms โ 100 โ 100
โ โฐโ skipmap โ โ โ โ โ
โ โโ 1 6.382 ms โ 9.79 ms โ 8.071 ms โ 8.088 ms โ 100 โ 100
โ โโ 2 8.853 ms โ 13.66 ms โ 9.742 ms โ 9.976 ms โ 100 โ 100
โ โโ 4 10.99 ms โ 16.41 ms โ 13.12 ms โ 13.27 ms โ 100 โ 100
โ โโ 8 16.04 ms โ 27.1 ms โ 17.48 ms โ 17.75 ms โ 100 โ 100
โ โโ 16 28.47 ms โ 35.69 ms โ 30.92 ms โ 30.93 ms โ 100 โ 100
โ โฐโ 32 53.7 ms โ 63.41 ms โ 58.27 ms โ 58.18 ms โ 100 โ 100
โโ 04_concurrent_reads_long_keys โ โ โ โ โ
โ โโ indexset_32b โ โ โ โ โ
โ โ โโ 1 2.796 ms โ 4.567 ms โ 3.624 ms โ 3.552 ms โ 100 โ 100
โ โ โโ 2 4.125 ms โ 6.036 ms โ 5.065 ms โ 5 ms โ 100 โ 100
โ โ โโ 4 5.825 ms โ 11.37 ms โ 7.323 ms โ 7.463 ms โ 100 โ 100
โ โ โโ 8 7.756 ms โ 11.95 ms โ 9.196 ms โ 9.293 ms โ 100 โ 100
โ โ โฐโ 16 14.75 ms โ 18.04 ms โ 16.43 ms โ 16.47 ms โ 100 โ 100
โ โโ masstree_32b โ โ โ โ โ
โ โ โโ 1 2.673 ms โ 4.032 ms โ 3.081 ms โ 3.049 ms โ 100 โ 100
โ โ โโ 2 3.55 ms โ 7.098 ms โ 3.964 ms โ 4.233 ms โ 100 โ 100
โ โ โโ 4 5.237 ms โ 7.709 ms โ 6.256 ms โ 6.32 ms โ 100 โ 100
โ โ โโ 8 6.397 ms โ 10.04 ms โ 8.479 ms โ 8.474 ms โ 100 โ 100
โ โ โฐโ 16 12.91 ms โ 21.11 ms โ 15.57 ms โ 15.67 ms โ 100 โ 100
โ โฐโ skipmap_32b โ โ โ โ โ
โ โโ 1 3.693 ms โ 5.395 ms โ 4.08 ms โ 4.107 ms โ 100 โ 100
โ โโ 2 4.691 ms โ 6.9 ms โ 5.123 ms โ 5.366 ms โ 100 โ 100
โ โโ 4 4.911 ms โ 9.255 ms โ 7.031 ms โ 6.947 ms โ 100 โ 100
โ โโ 8 8.064 ms โ 12.75 ms โ 10.18 ms โ 10.18 ms โ 100 โ 100
โ โฐโ 16 14.81 ms โ 18.8 ms โ 16.64 ms โ 16.68 ms โ 100 โ 100
Hi, sorry to bother again, but since you already had a look at the benchmark methodologies, I was wondering if you could take another look at the source to suggest further fairness issues. I have tried to address your points with fixed-size keys (no per-op heap allocation for any of the impls), multiple key sizes, overlapping/random/Zipfian patterns, and thread sweeps up to 32. I would HIGHLY appreciate it if you could take a look and see whether it's currently fair enough or if I could tighten things up more. Because currently I am getting unusually good results for read ops in comparison to std RwLock, Mutex and against both SkilList and indexset:
This bench was particularly desinged to stress layering and lengthier key variations. The unusually high performance for masstree with mimalloc (even standard global allocator too) doesn't make sense. I think I am doing something that is still giving this impl an unfair advantage, but I can't figure it out :'D
concurrent_maps fastest โ slowest โ median โ mean โ samples โ iters
โฐโ 14_concurrent_reads_long_keys_shared_prefix_deep โ โ โ โ โ
โโ indexset_32b โ โ โ โ โ
โ โโ 1 1.011 ms โ 2.578 ms โ 1.052 ms โ 1.239 ms โ 100 โ 100
โ โโ 2 1.825 ms โ 2.892 ms โ 2.152 ms โ 2.162 ms โ 100 โ 100
โ โโ 4 2.46 ms โ 3.139 ms โ 2.609 ms โ 2.627 ms โ 100 โ 100
โ โโ 8 2.545 ms โ 3.978 ms โ 2.726 ms โ 2.795 ms โ 100 โ 100
โ โฐโ 16 4.308 ms โ 5.697 ms โ 4.701 ms โ 4.755 ms โ 100 โ 100
โโ masstree_32b โ โ โ โ โ
โ โโ 1 486.5 ยตs โ 1.046 ms โ 504.1 ยตs โ 529.2 ยตs โ 100 โ 100
โ โโ 2 716.1 ยตs โ 1.489 ms โ 740.3 ยตs โ 774.9 ยตs โ 100 โ 100
โ โโ 4 739 ยตs โ 1.168 ms โ 786.8 ยตs โ 808.2 ยตs โ 100 โ 100
โ โโ 8 866.8 ยตs โ 1.433 ms โ 1.128 ms โ 1.117 ms โ 100 โ 100
โ โฐโ 16 1.286 ms โ 1.855 ms โ 1.374 ms โ 1.416 ms โ 100 โ 100
โฐโ skipmap_32b โ โ โ โ โ
โโ 1 1.621 ms โ 3.745 ms โ 1.673 ms โ 1.915 ms โ 100 โ 100
โโ 2 2.121 ms โ 3.89 ms โ 2.85 ms โ 2.862 ms โ 100 โ 100
โโ 4 2.69 ms โ 3.792 ms โ 2.889 ms โ 3.037 ms โ 100 โ 100
โโ 8 2.611 ms โ 3.974 ms โ 3.339 ms โ 3.253 ms โ 100 โ 100
โฐโ 16 4.682 ms โ 5.523 ms โ 4.865 ms โ 4.904 ms โ 100 โ 100
concurrent_maps fastest โ slowest โ median โ mean โ samples โ iters
โฐโ 15_mixed_long_keys_zipfian_shared_prefix โ โ โ โ โ
โโ indexset_32b โ โ โ โ โ
โ โโ 1 1.391 ms โ 2.792 ms โ 1.809 ms โ 1.807 ms โ 100 โ 100
โ โโ 2 1.759 ms โ 3.159 ms โ 2.503 ms โ 2.51 ms โ 100 โ 100
โ โโ 4 2.411 ms โ 3.231 ms โ 2.788 ms โ 2.789 ms โ 100 โ 100
โ โโ 8 3.192 ms โ 3.748 ms โ 3.414 ms โ 3.425 ms โ 100 โ 100
โ โฐโ 16 4.438 ms โ 6.314 ms โ 5.046 ms โ 5.057 ms โ 100 โ 100
โโ masstree_32b โ โ โ โ โ
โ โโ 1 974.7 ยตs โ 1.774 ms โ 1.529 ms โ 1.472 ms โ 100 โ 100
โ โโ 2 1.637 ms โ 2.354 ms โ 1.941 ms โ 1.93 ms โ 100 โ 100
โ โโ 4 1.997 ms โ 2.724 ms โ 2.308 ms โ 2.327 ms โ 100 โ 100
โ โโ 8 2.734 ms โ 3.693 ms โ 3.123 ms โ 3.134 ms โ 100 โ 100
โ โฐโ 16 3.258 ms โ 10.35 ms โ 3.909 ms โ 4.425 ms โ 100 โ 100
โฐโ skipmap_32b โ โ โ โ โ
โโ 1 2.379 ms โ 3.976 ms โ 3.372 ms โ 3.209 ms โ 100 โ 100
โโ 2 3.197 ms โ 4.169 ms โ 3.752 ms โ 3.723 ms โ 100 โ 100
โโ 4 3.433 ms โ 4.377 ms โ 3.856 ms โ 3.841 ms โ 100 โ 100
โโ 8 3.861 ms โ 5.108 ms โ 4.624 ms โ 4.666 ms โ 100 โ 100
โฐโ 16 6.243 ms โ 8.001 ms โ 6.653 ms โ 6.7 ms โ 100 โ 100
BTreeMap:
โฐโ 12_concurrent_reads_long_keys_shared_prefix_deep โ โ โ โ โ
โโ masstree_32b โ โ โ โ โ
โ โโ 1 471 ยตs โ 1.344 ms โ 493.1 ยตs โ 551.3 ยตs โ 100 โ 100
โ โโ 2 681.7 ยตs โ 1.347 ms โ 734.8 ยตs โ 745.7 ยตs โ 100 โ 100
โ โโ 4 718.6 ยตs โ 1.139 ms โ 784.7 ยตs โ 802.9 ยตs โ 100 โ 100
โ โโ 8 771.3 ยตs โ 1.51 ms โ 1.101 ms โ 1.064 ms โ 100 โ 100
โ โฐโ 16 1.259 ms โ 1.994 ms โ 1.368 ms โ 1.42 ms โ 100 โ 100
โโ mutex_btreemap_32b โ โ โ โ โ
โ โโ 1 785.7 ยตs โ 1.537 ms โ 827.3 ยตs โ 841.4 ยตs โ 100 โ 100
โ โโ 2 2.521 ms โ 4.294 ms โ 3.745 ms โ 3.681 ms โ 100 โ 100
โ โโ 4 6.341 ms โ 8.777 ms โ 7.442 ms โ 7.382 ms โ 100 โ 100
โ โโ 8 13.83 ms โ 19.51 ms โ 16.79 ms โ 16.91 ms โ 100 โ 100
โ โฐโ 16 32.67 ms โ 34.39 ms โ 33.29 ms โ 33.3 ms โ 100 โ 100
โฐโ rwlock_btreemap_32b โ โ โ โ โ
โโ 1 799 ยตs โ 1.766 ms โ 826.9 ยตs โ 966.5 ยตs โ 100 โ 100
โโ 2 1.192 ms โ 1.978 ms โ 1.422 ms โ 1.454 ms โ 100 โ 100
โโ 4 1.569 ms โ 2.003 ms โ 1.656 ms โ 1.672 ms โ 100 โ 100
โโ 8 2.065 ms โ 2.545 ms โ 2.147 ms โ 2.168 ms โ 100 โ 100
โฐโ 16 3.023 ms โ 3.47 ms โ 3.108 ms โ 3.131 ms โ 100 โ 100