PersistentMap/PersistentOrderedMap/Readme.org

69 KiB

PersistentMap

A high-performance, persistent (Copy-on-Write) B+ Tree implemented in C#.

It is designed for zero-overhead reads, SIMD-accelerated key routing, and allocation-free range queries. It supports both fully immutable usage and "Transient" mode for high-throughput bulk mutations. The primary use case is for when editing operations are in bulk. Updating single elements many times will fail to distinguish this collection from other more mature collections. Bulk writes are very fast using transient interfaces, random reads are fastish depending on key type and entropy, Sequential reads and min/max queries are very fast.

Features

  • Copy-on-Write Semantics: Thread-safe, immutable tree states. Modifying the tre yields a new version while sharing unmodified nodes.
  • Transient Mode: Perform bulk mutations in-place with standard mutable performance, then freeze it into a PersistentMap in $O(1)$ time.
  • SIMD Prefix Scanning: Uses AVX2/AVX512 to vectorize B+ tree routing and binary searches via long key-prefixes.
  • Linear Time Set Operations: Sort-merge based Intersect, Except, and SymmetricExcept execute in $O(N+M)$ time using lazy evaluation.

When should I use this?

Never, probably. This was just a fun little project. If you want a really fast immutable sorted map you should consider it. Despite this map being faster than LanguageExt.HashMap for some key types, you should definitely use that if you don't need a sorted collection. It is well tested and does have a very nice API, and it also has a performance model that is easy to understand. If you look at the performance characteristics of it below, it scales much more linear with collection size. For example: I don't know why PersistentMap lookups suddenly becomes so much slower when we reach 100000 integer keys. There might be a gazillion things like that, that make PersistentMap much slower for real world usage.

The general version of this, using StandardStrategy<K> does not benefit from the prefix optimization, although might benefit from a usage of binary search in the future.

Quick Start

1. Basic Immutable Usage

By default, the map is immutable. Every write operation returns a new, updated version of the map.

// Create a map with a specific key strategy (e.g., Int, Unicode, Double)
var map1 = BaseOrderedMap<int, string, IntStrategy>.Create(new IntStrategy());

// Set returns a new tree instance. map1 remains empty.
var map2 = map1.Set(1, "Apple")
               .Set(2, "Banana")
               .Set(3, "Cherry");

if (map2.TryGetValue(2, out var value)) 
{
    Console.WriteLine(value); // "Banana"
}

2. Transient Mode (Bulk Mutations

If you need to insert thousands of elements, creating a new persistent tree on every insert is too slow. Use a TransientMap to mutate the tree in-place, then lock it into a persistent snapshot. This does not edit an existing map, but will make bulk operations a lot faster on nodes "owned" by the current map.

var transientMap = BaseOrderedMap<int, string, IntStrategy>.CreateTransient(new IntStrategy());

// Mutates in-place. No allocations for unchanged tree paths.
for (int i = 0; i < 10_000; i++)
{
    transientMap.Set(i, $"Value_{i}");
}

// O(1) freeze. Returns a thread-safe immutable PersistentMap.
var persistentSnapshot = transientMap.ToPersistent();

3. Range Queries and Iteration

Because it is a B+ tree range queries require zero allocations and simply walk the leaves.

var map = GetPopulatedMap();

// Iterate exact bounds
foreach (var kvp in map.Range(min: 10, max: 50))
{
    Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}

// Open-ended queries
var greaterThan100 = map.From(100);
var lessThan50 = map.Until(50);
var allElements = map.AsEnumerable();
#+end_sr

*** 4. Tree Navigation
Find bounds and adjacent elements instantly. Missing keys will correctly resolve to the mathematical lower/upper bound.

#+begin_src csharp
// Get extremes
map.TryGetMin(out int minKey, out string minVal);
map.TryGetMax(out int maxKey, out string maxVal);

// Get the immediate next/previous element (works even if '42' doesn't exist)
if (map.TryGetSuccessor(42, out int nextKey, out string nextVal))
{
    Console.WriteLine($"The key immediately after 42 is {nextKey}");
}

if (map.TryGetPredecessor(42, out int prevKey, out string prevVal))
{
    Console.WriteLine($"The key immediately before 42 is {prevKey}");
}

5. Set Operations

Set operations take advantage of the tree's underlying sorted structure to merge trees in linear $O(N+M)$ time.

var mapA = CreateMap(1, 2, 3, 4);
var mapB = CreateMap(3, 4, 5, 6);

// Returns { 3, 4 }
var common = mapA.Intersect(mapB); 

// Returns { 1, 2 }
var onlyInA = mapA.Except(mapB); 

// Returns { 1, 2, 5, 6 }
var symmetricDiff = mapA.SymmetricExcept(mapB);

Benchmarks

These benchmarks tries a variety of operations. The Int benchmarks (the first ones) use avx for lookups. On a computer without avx this is bound to be slower. In benchmarks where there are many writes to the tree, the transient version is used, since this is the workload this datastructure is optimized for.

Build: builds a map of size N. I did not benchmark the builders used by the built in collections, but they are almost certainly at least as fast as the transients used by this library. For integers, the map was sorted (triggering a small optimization in PersistentMap). For the string benchmark it was random.

The retrieval benchmarks reads a subset of the keys in random order.

The update benchmarks updates a subset of the keys in random order.

The update and set benchmarks updates and sets keys in random order. Half of the keys are new.

The iteration benchmarks iterate from start to finish. The ordered collections are of course in order.

The removal benchmarks removes a subset of the keys in random order.

Integer keys

This is pretty much the best case scenario for everyone. Key comparisons are fast, hashing is minimal. For b+trees this means we can do a lot of key comparisons at once using avx. The machine this is done on is an amd 5900x, which supports some kind of bastardized avx512. It is not really a gain over avx256 in this benchmark though on that processor. With regards to building, the microsoft collections have builders, and they are about as fast as the TransientMap, but a little little slower on my computer. LanguageExt lacks transients, and thus these comparisons are not fair.

ImmDict is System.Collections.Immutable dictionary. ImmSortedDict is it's sorted sibling. ExtMap is the sorted map from LanguageExt. ExtHashMap is the unsorted HashMap from LanguageExt.

| Method                  | N      |             Mean |       Gen0 |      Gen1 |    Gen2 |   Allocated |
|-------------------------|--------|-----------------:|-----------:|----------:|--------:|------------:|
| Build_ImmDict           | 100    |     11,307.04 ns |     4.9744 |    0.0458 |       - |     41688 B |
| Build_ImmSortedDict     | 100    |      8,493.79 ns |     4.4250 |    0.0458 |       - |     37104 B |
| Build_ExtMap            | 100    |      8,519.63 ns |     5.3101 |    0.0458 |       - |     44432 B |
| Build_ExtHashMap        | 100    |      9,855.33 ns |     7.5378 |    0.0458 |       - |     63104 B |
| Build_PersistentMap     | 100    |      8,698.33 ns |    16.3879 |    0.1526 |       - |    137072 B |
| Build_TransientMap      | 100    |      1,665.90 ns |     0.6332 |    0.0038 |       - |      5304 B |
| Retrieve_ImmDict        | 100    |         39.19 ns |          - |         - |       - |           - |
| Retrieve_ImmSortedDict  | 100    |         64.32 ns |          - |         - |       - |           - |
| Retrieve_ExtMap         | 100    |        117.61 ns |          - |         - |       - |           - |
| Retrieve_ExtHashMap     | 100    |         84.19 ns |          - |         - |       - |           - |
| Retrieve_PersistentMap  | 100    |         47.25 ns |          - |         - |       - |           - |
| Update_ImmDict          | 100    |      1,145.75 ns |     0.4616 |    0.0019 |       - |      3872 B |
| Update_PersistentMap    | 100    |         1.107 μs |     1.9398 |    0.0248 |       - |    15.86 KB |
| Update_TransientMap     | 100    |        347.49 ns |     0.3576 |    0.0033 |       - |      2992 B |
| Update_ImmSortedDict    | 100    |        849.39 ns |     0.3958 |    0.0010 |       - |      3312 B |
| Update_ExtMap           | 100    |        642.50 ns |     0.3939 |    0.0010 |       - |      3296 B |
| Update_ExtHashMap       | 100    |        541.84 ns |     0.5283 |    0.0010 |       - |      4424 B |
| UpdateSet_ImmDict       | 100    |      1,236.82 ns |     0.5226 |    0.0019 |       - |      4376 B |
| UpdateSet_PersistentMap | 100    |          1189 ns |     1.9398 |    0.0248 |       - |    15.86 KB |
| UpdateSet_TransientMap  | 100    |        380.70 ns |     0.3576 |    0.0033 |       - |      2992 B |
| UpdateSet_ImmSortedDict | 100    |        887.07 ns |     0.4587 |    0.0010 |       - |      3840 B |
| UpdateSet_ExtMap        | 100    |        856.76 ns |     0.4797 |    0.0010 |       - |      4016 B |
| UpdateSet_ExtHashMap    | 100    |        582.31 ns |     0.5312 |    0.0019 |       - |      4448 B |
| Iterate_ImmDict         | 100    |      1,324.41 ns |          - |         - |       - |           - |
| Iterate_PersistentMap   | 100    |        175.98 ns |          - |         - |       - |           - |
| Iterate_ImmSortedDict   | 100    |        488.69 ns |          - |         - |       - |           - |
| Iterate_ExtMap          | 100    |        337.40 ns |     0.0038 |         - |       - |        32 B |
| Iterate_ExtHashMap      | 100    |      1,209.77 ns |     0.2518 |         - |       - |      2112 B |
| Remove_ImmDict          | 100    |        899.57 ns |     0.4425 |    0.0010 |       - |      3704 B |
| Remove_TransientMap     | 100    |        433.52 ns |     0.3290 |    0.0029 |       - |      2752 B |
| Remove_ImmSortedDict    | 100    |        728.77 ns |     0.3786 |    0.0010 |       - |      3168 B |
| Remove_ExtMap           | 100    |        653.72 ns |     0.3767 |    0.0010 |       - |      3152 B |
| Remove_ExtHashMap       | 100    |        589.03 ns |     0.5178 |         - |       - |      4336 B |
| Build_ImmDict           | 1000   |    168,692.47 ns |    71.5332 |    6.8359 |       - |    598712 B |
| Build_ImmSortedDict     | 1000   |    125,591.01 ns |    62.9883 |    5.1270 |       - |    526896 B |
| Build_ExtMap            | 1000   |    117,763.81 ns |    72.3877 |    6.1035 |       - |    605936 B |
| Build_ExtHashMap        | 1000   |     64,443.19 ns |    67.5049 |    1.5869 |       - |    564864 B |
| Build_PersistentMap     | 1000   |    133,156.05 ns |   192.1387 |    7.8125 |       - |   1607744 B |
| Build_TransientMap      | 1000   |     25,945.72 ns |     4.2725 |    0.1526 |       - |     35976 B |
| Retrieve_ImmDict        | 1000   |        686.48 ns |          - |         - |       - |           - |
| Retrieve_ImmSortedDict  | 1000   |      1,145.83 ns |          - |         - |       - |           - |
| Retrieve_ExtMap         | 1000   |      2,276.07 ns |          - |         - |       - |           - |
| Retrieve_ExtHashMap     | 1000   |        808.53 ns |          - |         - |       - |           - |
| Retrieve_PersistentMap  | 1000   |        680.50 ns |          - |         - |       - |           - |
| Update_ImmDict          | 1000   |     16,863.81 ns |     6.5613 |    0.2136 |       - |     54960 B |
| Update_PersistentMap    | 1000   |     13,617.12 ns |    19.4092 |    1.1597 |       - |   158.59 KB |
| Update_TransientMap     | 1000   |      3,611.03 ns |     2.5406 |    0.1564 |       - |     21280 B |
| Update_ImmSortedDict    | 1000   |     12,428.90 ns |     5.5542 |    0.1526 |       - |     46464 B |
| Update_ExtMap           | 1000   |     10,091.51 ns |     5.6000 |    0.1678 |       - |     46880 B |
| Update_ExtHashMap       | 1000   |      6,758.96 ns |     7.9575 |    0.2136 |       - |     66616 B |
| UpdateSet_ImmDict       | 1000   |     21,489.70 ns |     7.0496 |    0.1831 |       - |     59160 B |
| UpdateSet_PersistentMap | 1000   |     14,890.21 ns |    19.4855 |    1.0529 |       - |   159.23 KB |
| UpdateSet_TransientMap  | 1000   |      5,063.11 ns |     2.4796 |    0.1450 |       - |     20776 B |
| UpdateSet_ImmSortedDict | 1000   |     13,333.61 ns |     6.3782 |    0.1526 |       - |     53472 B |
| UpdateSet_ExtMap        | 1000   |     11,221.39 ns |     6.5918 |    0.1526 |       - |     55184 B |
| UpdateSet_ExtHashMap    | 1000   |     15,967.43 ns |    13.1836 |    0.4578 |       - |    110440 B |
| Iterate_ImmDict         | 1000   |     15,325.93 ns |          - |         - |       - |           - |
| Iterate_PersistentMap   | 1000   |      1,574.20 ns |          - |         - |       - |           - |
| Iterate_ImmSortedDict   | 1000   |      5,110.07 ns |          - |         - |       - |           - |
| Iterate_ExtMap          | 1000   |      3,432.88 ns |     0.0038 |         - |       - |        32 B |
| Iterate_ExtHashMap      | 1000   |      8,207.75 ns |     0.2441 |         - |       - |      2112 B |
| Remove_ImmDict          | 1000   |     15,205.95 ns |     6.4392 |    0.2136 |       - |     54064 B |
| Remove_TransientMap     | 1000   |      4,036.18 ns |     2.2507 |    0.1373 |       - |     18880 B |
| Remove_ImmSortedDict    | 1000   |     10,664.14 ns |     5.7068 |    0.1678 |       - |     47760 B |
| Remove_ExtMap           | 1000   |      9,993.90 ns |     5.5084 |    0.1526 |       - |     46160 B |
| Remove_ExtHashMap       | 1000   |      7,475.24 ns |     7.7209 |    0.1907 |       - |     64608 B |
| Build_ImmDict           | 10000  |  2,571,753.12 ns |    41.4063 |  390.6250 |       - |   7882552 B |
| Build_ImmSortedDict     | 10000  |  1,975,364.14 ns |   820.3125 |  296.8750 |       - |   6893616 B |
| Build_ExtMap            | 10000  |  1,866,221.83 ns |   917.9688 |  320.3125 |       - |   7692272 B |
| Build_ExtHashMap        | 10000  |  1,215,103.58 ns |  1009.7656 |  240.2344 |       - |   8446080 B |
| Build_PersistentMap     | 10000  |  1,930,457.96 ns |  2345.7031 |  494.1406 |       - |  19626728 B |
| Build_TransientMap      | 10000  |    640,413.08 ns |    41.0156 |    8.7891 |       - |    347344 B |
| Retrieve_ImmDict        | 10000  |     14,880.32 ns |          - |         - |       - |           - |
| Retrieve_ImmSortedDict  | 10000  |     15,595.68 ns |          - |         - |       - |           - |
| Retrieve_ExtMap         | 10000  |     36,225.60 ns |          - |         - |       - |           - |
| Retrieve_ExtHashMap     | 10000  |     11,987.70 ns |          - |         - |       - |           - |
| Retrieve_PersistentMap  | 10000  |     10,227.73 ns |          - |         - |       - |           - |
| Update_ImmDict          | 10000  |    318,905.00 ns |    86.9141 |   23.4375 |       - |    730200 B |
| Update_PersistentMap    | 10000  |    202,244.42 ns |   243.6523 |   73.2422 |       - |  1992.19 KB |
| Update_TransientMap     | 10000  |     73,203.50 ns |    24.9023 |    7.3242 |       - |    209056 B |
| Update_ImmSortedDict    | 10000  |    216,638.87 ns |    77.1484 |   16.1133 |       - |    645360 B |
| Update_ExtMap           | 10000  |    176,737.24 ns |    74.4629 |   17.5781 |       - |    623600 B |
| Update_ExtHashMap       | 10000  |    105,445.84 ns |    97.2900 |   17.3340 |       - |    814376 B |
| UpdateSet_ImmDict       | 10000  |    333,260.72 ns |    92.2852 |   19.0430 |       - |    775784 B |
| UpdateSet_PersistentMap | 10000  |    221,958.91 ns |   244.6289 |   71.2891 |       - |  1998.95 KB |
| UpdateSet_TransientMap  | 10000  |     93,484.07 ns |    24.9023 |    7.3242 |       - |    209072 B |
| UpdateSet_ImmSortedDict | 10000  |    224,214.31 ns |    83.2520 |   14.6484 |       - |    697920 B |
| UpdateSet_ExtMap        | 10000  |    186,761.55 ns |    83.7402 |   14.4043 |       - |    700880 B |
| UpdateSet_ExtHashMap    | 10000  |    112,371.27 ns |    97.7783 |   20.2637 |       - |    818240 B |
| Iterate_ImmDict         | 10000  |    152,686.50 ns |          - |         - |       - |           - |
| Iterate_PersistentMap   | 10000  |     14,841.56 ns |          - |         - |       - |           - |
| Iterate_ImmSortedDict   | 10000  |     53,372.05 ns |          - |         - |       - |           - |
| Iterate_ExtMap          | 10000  |     38,673.93 ns |          - |         - |       - |        32 B |
| Iterate_ExtHashMap      | 10000  |    111,676.15 ns |     8.0566 |         - |       - |     67648 B |
| Remove_ImmDict          | 10000  |    303,798.22 ns |    86.4258 |   19.5313 |       - |    726560 B |
| Remove_TransientMap     | 10000  |     58,890.93 ns |    22.0947 |    6.5308 |       - |    185056 B |
| Remove_ImmSortedDict    | 10000  |    219,974.63 ns |    77.8809 |   15.1367 |       - |    653184 B |
| Remove_ExtMap           | 10000  |    188,713.80 ns |    74.2188 |   14.4043 |       - |    621248 B |
| Remove_ExtHashMap       | 10000  |    120,113.97 ns |    95.9473 |   15.9912 |       - |    802944 B |
| Build_ImmDict           | 100000 | 38,394,437.95 ns | 11714.2857 | 1071.4286 | 71.4286 |  97460075 B |
| Build_ImmSortedDict     | 100000 | 30,860,676.12 ns | 10187.5000 |  906.2500 | 62.5000 |  84908636 B |
| Build_ExtMap            | 100000 | 28,415,796.22 ns | 11156.2500 |  937.5000 | 62.5000 |  92907004 B |
| Build_ExtHashMap        | 100000 | 29,149,824.12 ns | 15375.0000 | 2750.0000 | 62.5000 | 128198060 B |
| Build_PersistentMap     | 100000 | 24,745,757.59 ns | 27687.5000 |  375.0000 |       - | 231722008 B |
| Build_TransientMap      | 100000 |  9,137,195.74 ns |   406.2500 |  234.3750 |       - |   3460512 B |
| Retrieve_ImmDict        | 100000 |  1,259,618.31 ns |          - |         - |       - |           - |
| Retrieve_ImmSortedDict  | 100000 |    975,518.14 ns |          - |         - |       - |           - |
| Retrieve_ExtMap         | 100000 |  1,535,487.85 ns |          - |         - |       - |           - |
| Retrieve_ExtHashMap     | 100000 |    284,590.55 ns |          - |         - |       - |           - |
| Retrieve_PersistentMap  | 100000 |    429,001.27 ns |          - |         - |       - |           - |
| Update_ImmDict          | 100000 |  5,705,786.31 ns |  1093.7500 |  906.2500 |       - |   9183488 B |
| Update_PersistentMap    | 100000 |  4,056,612.12 ns |  2945.3125 | 2781.2500 | 15.6250 | 23984.39 KB |
| Update_TransientMap     | 100000 |  1,145,551.13 ns |   248.0469 |  199.2188 |       - |   2081568 B |
| Update_ImmSortedDict    | 100000 |  4,433,611.11 ns |   953.1250 |  796.8750 |       - |   8021136 B |
| Update_ExtMap           | 100000 |  3,901,065.86 ns |   937.5000 |  789.0625 |       - |   7848704 B |
| Update_ExtHashMap       | 100000 |  2,696,228.39 ns |  1289.0625 |  960.9375 |       - |  10805952 B |
| UpdateSet_ImmDict       | 100000 |  5,340,382.88 ns |  1109.3750 |  867.1875 |       - |   9318896 B |
| UpdateSet_PersistentMap | 100000 |  4,629,564.21 ns |  2984.3750 | 1906.2500 | 39.0625 | 24060.44 KB |
| UpdateSet_TransientMap  | 100000 |  1,332,859.76 ns |   250.0000 |  208.9844 |       - |   2099520 B |
| UpdateSet_ImmSortedDict | 100000 |  4,418,076.49 ns |  1000.0000 |  992.1875 |       - |   8396544 B |
| UpdateSet_ExtMap        | 100000 |  3,107,339.72 ns |   996.0938 |  507.8125 |       - |   8349248 B |
| UpdateSet_ExtHashMap    | 100000 |  2,630,473.81 ns |  1292.9688 |  976.5625 |       - |  10845480 B |
| Iterate_ImmDict         | 100000 |  1,550,040.28 ns |          - |         - |       - |           - |
| Iterate_PersistentMap   | 100000 |    149,743.16 ns |          - |         - |       - |           - |
| Iterate_ImmSortedDict   | 100000 |    723,978.27 ns |          - |         - |       - |           - |
| Iterate_ExtMap          | 100000 |    504,204.91 ns |          - |         - |       - |        32 B |
| Iterate_ExtHashMap      | 100000 |  1,936,574.10 ns |   257.8125 |         - |       - |   2164800 B |
| Remove_ImmDict          | 100000 |  5,419,879.00 ns |  1093.7500 |  914.0625 |       - |   9149160 B |
| Remove_TransientMap     | 100000 |    951,332.63 ns |   219.7266 |  155.2734 |       - |   1839264 B |
| Remove_ImmSortedDict    | 100000 |  4,203,794.51 ns |   953.1250 |  781.2500 |       - |   8028144 B |
| Remove_ExtMap           | 100000 |  3,896,109.04 ns |   929.6875 |  789.0625 |       - |   7824560 B |
| Remove_ExtHashMap       | 100000 |  2,816,957.99 ns |  1277.3438 |  914.0625 |       - |  10709360 B |

String keys

These benchmarks act like above, but do not insert keys in a specific order. Sorting them before will yield a speed boost. One uses the standardkeystrategy (does a binary search) and one uses the unicodstrategy which encodes the first 8 bytes as a long and uses avx to search for keys.

#+begin_src

```

Method N StringLength Mean Gen0 Gen1 Gen2 Allocated
Build_TransientMap_Standard 100 8 5,170.76 ns 0.7401 0.0076 - 6200 B
Build_TransientMap_Unicode 100 8 12,251.17 ns 0.8850 0.0153 - 7528 B
Build_ImmDict 100 8 13,926.78 ns 5.3253 0.0610 - 44640 B
Build_ImmSortedDict 100 8 21,789.13 ns 4.2114 0.0305 - 35472 B
Build_ExtMap 100 8 22,791.98 ns 5.6152 0.0610 - 47104 B
Build_ExtHashMap 100 8 9,993.13 ns 4.0894 0.0305 - 34216 B
Retrieve_ImmDict 100 8 78.83 ns - - - -
Retrieve_PersistentMap_Standard 100 8 105.97 ns - - - -
Retrieve_PersistentMap_Unicode 100 8 149.07 ns - - - -
Retrieve_ImmSortedDict 100 8 1,203.47 ns - - - -
Retrieve_ExtMap 100 8 1,297.20 ns - - - -
Retrieve_ExtHashMap 100 8 189.50 ns - - - -
Update_ImmDict 100 8 1,343.93 ns 0.5207 0.0019 - 4368 B
Update_PersistentMap_Standard 100 8 1,593.27 ns 2.3994 0.0401 - 20080 B
Update_PersistentMap_Unicode 100 8 1,913.07 ns 2.7046 0.0496 - 22640 B
Update_TransientMap_Standard 100 8 520.49 ns 0.4339 0.0048 - 3632 B
Update_TransientMap_Unicode 100 8 690.74 ns 0.4644 0.0057 - 3888 B
Update_ImmSortedDict 100 8 1,748.06 ns 0.3662 - - 3072 B
Update_ExtMap 100 8 1,793.32 ns 0.4120 - - 3456 B
Update_ExtHashMap 100 8 754.97 ns 0.5264 0.0010 - 4408 B
UpdateSet_ImmDict 100 8 1,361.32 ns 0.5207 0.0019 - 4368 B
UpdateSet_PersistentMap_Standard 100 8 1,838.15 ns 2.3994 0.0420 - 20080 B
UpdateSet_PersistentMap_Unicode 100 8 2,427.91 ns 2.7046 0.0534 - 22640 B
UpdateSet_TransientMap_Standard 100 8 711.17 ns 0.4339 0.0048 - 3632 B
UpdateSet_TransientMap_Unicode 100 8 1,247.32 ns 0.4635 0.0057 - 3888 B
UpdateSet_ImmSortedDict 100 8 2,399.76 ns 0.4578 - - 3840 B
UpdateSet_ExtMap 100 8 2,202.70 ns 0.4730 - - 3960 B
UpdateSet_ExtHashMap 100 8 773.22 ns 0.5274 0.0019 - 4416 B
Iterate_ImmDict 100 8 1,335.18 ns - - - -
Iterate_PersistentMap_Standard 100 8 189.19 ns - - - -
Iterate_ImmSortedDict 100 8 485.69 ns - - - -
Iterate_ExtMap 100 8 327.67 ns 0.0038 - - 32 B
Iterate_ExtHashMap 100 8 1,089.89 ns 0.2480 - - 2088 B
Iterate_PersistentMap_Unicode 100 8 187.62 ns - - - -
Remove_ImmDict 100 8 1,272.43 ns 0.5131 - - 4304 B
Remove_PersistentMap_Standard 100 8 1,969.67 ns 2.3689 0.0381 - 19840 B
Remove_PersistentMap_Unicode 100 8 2,487.99 ns 2.6779 0.0496 - 22400 B
Remove_TransientMap_Standard 100 8 836.95 ns 0.4101 0.0048 - 3432 B
Remove_TransientMap_Unicode 100 8 1,333.99 ns 0.4406 0.0057 - 3688 B
Remove_ImmSortedDict 100 8 1,946.19 ns 0.3777 - - 3168 B
Remove_ExtMap 100 8 2,221.31 ns 0.5798 - - 4856 B
Remove_ExtHashMap 100 8 770.43 ns 0.4721 0.0019 - 3952 B
Build_TransientMap_Standard 100 50 5,216.44 ns 0.7401 0.0076 - 6200 B
Build_TransientMap_Unicode 100 50 11,944.76 ns 0.8850 0.0153 - 7528 B
Build_ImmDict 100 50 15,771.58 ns 5.3101 0.0610 - 44576 B
Build_ImmSortedDict 100 50 22,171.62 ns 4.2114 0.0305 - 35232 B
Build_ExtMap 100 50 27,705.49 ns 5.6458 0.0610 - 47328 B
Build_ExtHashMap 100 50 15,207.38 ns 4.4861 0.0305 - 37672 B
Retrieve_ImmDict 100 50 286.21 ns - - - -
Retrieve_PersistentMap_Standard 100 50 103.79 ns - - - -
Retrieve_PersistentMap_Unicode 100 50 151.04 ns - - - -
Retrieve_ImmSortedDict 100 50 1,317.60 ns - - - -
Retrieve_ExtMap 100 50 1,162.96 ns - - - -
Retrieve_ExtHashMap 100 50 412.76 ns - - - -
Update_ImmDict 100 50 1,359.95 ns 0.4368 - - 3664 B
Update_PersistentMap_Standard 100 50 1,583.22 ns 2.3994 0.0420 - 20080 B
Update_PersistentMap_Unicode 100 50 1,861.53 ns 2.7065 0.0515 - 22640 B
Update_TransientMap_Standard 100 50 543.81 ns 0.4339 0.0048 - 3632 B
Update_TransientMap_Unicode 100 50 633.60 ns 0.4644 0.0057 - 3888 B
Update_ImmSortedDict 100 50 1,986.02 ns 0.4120 - - 3456 B
Update_ExtMap 100 50 1,892.16 ns 0.4253 - - 3568 B
Update_ExtHashMap 100 50 1,088.83 ns 0.4997 - - 4184 B
UpdateSet_ImmDict 100 50 1,799.24 ns 0.5817 0.0019 - 4880 B
UpdateSet_PersistentMap_Standard 100 50 1,847.71 ns 2.3994 0.0401 - 20080 B
UpdateSet_PersistentMap_Unicode 100 50 2,510.91 ns 2.7046 0.0496 - 22640 B
UpdateSet_TransientMap_Standard 100 50 754.14 ns 0.4339 0.0048 - 3632 B
UpdateSet_TransientMap_Unicode 100 50 1,274.76 ns 0.4635 0.0057 - 3888 B
UpdateSet_ImmSortedDict 100 50 2,463.36 ns 0.4730 - - 3984 B
UpdateSet_ExtMap 100 50 2,364.62 ns 0.5913 - - 4968 B
UpdateSet_ExtHashMap 100 50 1,026.26 ns 0.5074 - - 4248 B
Iterate_ImmDict 100 50 1,223.85 ns - - - -
Iterate_PersistentMap_Standard 100 50 187.31 ns - - - -
Iterate_ImmSortedDict 100 50 484.33 ns - - - -
Iterate_ExtMap 100 50 358.22 ns 0.0038 - - 32 B
Iterate_ExtHashMap 100 50 1,149.01 ns 0.2575 - - 2160 B
Iterate_PersistentMap_Unicode 100 50 187.47 ns - - - -
Remove_ImmDict 100 50 1,589.38 ns 0.5283 0.0019 - 4432 B
Remove_PersistentMap_Standard 100 50 1,976.63 ns 2.3689 0.0381 - 19840 B
Remove_PersistentMap_Unicode 100 50 2,568.69 ns 2.6779 0.0458 - 22400 B
Remove_TransientMap_Standard 100 50 839.46 ns 0.4101 0.0048 - 3432 B
Remove_TransientMap_Unicode 100 50 1,399.50 ns 0.4406 0.0057 - 3688 B
Remove_ImmSortedDict 100 50 2,069.17 ns 0.3891 - - 3264 B
Remove_ExtMap 100 50 2,124.59 ns 0.4387 - - 3680 B
Remove_ExtHashMap 100 50 1,029.42 ns 0.5112 - - 4288 B
Build_TransientMap_Standard 1000 8 102,292.92 ns 5.7373 0.3662 - 48592 B
Build_TransientMap_Unicode 1000 8 172,854.88 ns 7.3242 0.7324 - 62248 B
Build_ImmDict 1000 8 247,732.93 ns 79.1016 8.3008 - 662016 B
Build_ImmSortedDict 1000 8 429,391.31 ns 61.0352 4.8828 - 513312 B
Build_ExtMap 1000 8 416,823.27 ns 79.1016 7.3242 - 662448 B
Build_ExtHashMap 1000 8 154,417.86 ns 70.8008 4.6387 - 592920 B
Retrieve_ImmDict 1000 8 1,043.45 ns - - - -
Retrieve_PersistentMap_Standard 1000 8 1,783.56 ns - - - -
Retrieve_PersistentMap_Unicode 1000 8 2,026.44 ns - - - -
Retrieve_ImmSortedDict 1000 8 21,724.33 ns - - - -
Retrieve_ExtMap 1000 8 24,401.52 ns - - - -
Retrieve_ExtHashMap 1000 8 2,472.28 ns - - - -
Update_ImmDict 1000 8 19,547.84 ns 7.2937 0.2747 - 61024 B
Update_PersistentMap_Standard 1000 8 19,846.20 ns 23.9868 2.2278 - 200800 B
Update_PersistentMap_Unicode 1000 8 27,309.69 ns 27.0386 2.5330 - 226400 B
Update_TransientMap_Standard 1000 8 6,888.79 ns 4.3945 0.4501 - 36768 B
Update_TransientMap_Unicode 1000 8 7,801.38 ns 4.4250 0.4425 - 37024 B
Update_ImmSortedDict 1000 8 32,192.51 ns 5.7373 0.1221 - 48288 B
Update_ExtMap 1000 8 31,972.71 ns 6.4087 0.1831 - 53824 B
Update_ExtHashMap 1000 8 10,476.16 ns 7.2021 0.2289 - 60272 B
UpdateSet_ImmDict 1000 8 22,622.37 ns 8.2703 0.3967 - 69280 B
UpdateSet_PersistentMap_Standard 1000 8 22,274.40 ns 23.9868 2.3499 - 200800 B
UpdateSet_PersistentMap_Unicode 1000 8 32,897.61 ns 27.0386 2.6855 - 226400 B
UpdateSet_TransientMap_Standard 1000 8 8,218.75 ns 4.5624 0.4272 - 38176 B
UpdateSet_TransientMap_Unicode 1000 8 12,847.07 ns 4.5929 0.4883 - 38432 B
UpdateSet_ImmSortedDict 1000 8 37,683.95 ns 6.3477 0.2441 - 53232 B
UpdateSet_ExtMap 1000 8 38,195.16 ns 7.6904 0.3052 - 64576 B
UpdateSet_ExtHashMap 1000 8 14,327.00 ns 7.7057 0.2747 - 64480 B
Iterate_ImmDict 1000 8 12,971.77 ns - - - -
Iterate_PersistentMap_Standard 1000 8 1,615.06 ns - - - -
Iterate_ImmSortedDict 1000 8 4,905.20 ns - - - -
Iterate_ExtMap 1000 8 3,282.20 ns 0.0038 - - 32 B
Iterate_ExtHashMap 1000 8 14,214.03 ns 2.6093 - - 21888 B
Iterate_PersistentMap_Unicode 1000 8 1,644.30 ns - - - -
Remove_ImmDict 1000 8 19,504.24 ns 7.5989 0.3052 - 63648 B
Remove_PersistentMap_Standard 1000 8 24,227.34 ns 23.7122 2.0752 - 198400 B
Remove_PersistentMap_Unicode 1000 8 29,622.70 ns 26.7639 2.4414 - 224000 B
Remove_TransientMap_Standard 1000 8 9,476.68 ns 3.7689 0.3510 - 31592 B
Remove_TransientMap_Unicode 1000 8 14,237.22 ns 3.7994 0.3662 - 31848 B
Remove_ImmSortedDict 1000 8 33,197.78 ns 5.6763 0.1221 - 47616 B
Remove_ExtMap 1000 8 39,241.19 ns 6.8970 0.1831 - 57744 B
Remove_ExtHashMap 1000 8 11,374.77 ns 7.5378 0.2136 - 63056 B
Build_TransientMap_Standard 1000 50 104,538.75 ns 5.4932 0.3662 - 46784 B
Build_TransientMap_Unicode 1000 50 175,661.70 ns 7.0801 0.4883 - 59368 B
Build_ImmDict 1000 50 278,290.76 ns 79.5898 8.7891 - 669696 B
Build_ImmSortedDict 1000 50 417,827.13 ns 61.0352 5.3711 - 511344 B
Build_ExtMap 1000 50 409,994.29 ns 78.1250 7.3242 - 656288 B
Build_ExtHashMap 1000 50 181,354.06 ns 70.3125 4.6387 - 588328 B
Retrieve_ImmDict 1000 50 3,132.97 ns - - - -
Retrieve_PersistentMap_Standard 1000 50 1,794.95 ns - - - -
Retrieve_PersistentMap_Unicode 1000 50 2,065.82 ns - - - -
Retrieve_ImmSortedDict 1000 50 21,834.49 ns - - - -
Retrieve_ExtMap 1000 50 23,236.99 ns - - - -
Retrieve_ExtHashMap 1000 50 4,931.32 ns - - - -
Update_ImmDict 1000 50 22,234.72 ns 7.5073 0.3052 - 62816 B
Update_PersistentMap_Standard 1000 50 20,313.66 ns 23.9868 2.0142 - 200800 B
Update_PersistentMap_Unicode 1000 50 27,829.75 ns 27.0386 2.2888 - 226400 B
Update_TransientMap_Standard 1000 50 6,827.30 ns 4.0588 0.4044 - 33952 B
Update_TransientMap_Unicode 1000 50 7,654.44 ns 4.0894 0.3967 - 34208 B
Update_ImmSortedDict 1000 50 32,637.97 ns 5.6763 0.1221 - 47952 B
Update_ExtMap 1000 50 32,523.61 ns 6.5308 0.1831 - 54720 B
Update_ExtHashMap 1000 50 12,993.79 ns 7.2479 0.2441 - 60720 B
UpdateSet_ImmDict 1000 50 25,835.15 ns 8.3313 0.3967 - 69728 B
UpdateSet_PersistentMap_Standard 1000 50 22,970.95 ns 24.1089 2.2278 - 201704 B
UpdateSet_PersistentMap_Unicode 1000 50 34,226.66 ns 27.2217 2.6245 - 227840 B
UpdateSet_TransientMap_Standard 1000 50 7,701.61 ns 4.3335 0.4578 - 36264 B
UpdateSet_TransientMap_Unicode 1000 50 13,115.82 ns 4.4250 0.4578 - 37056 B
UpdateSet_ImmSortedDict 1000 50 37,636.40 ns 6.2866 0.1831 - 53088 B
UpdateSet_ExtMap 1000 50 38,985.88 ns 7.8735 0.3052 - 66200 B
UpdateSet_ExtHashMap 1000 50 17,008.89 ns 7.6294 0.2441 - 63936 B
Iterate_ImmDict 1000 50 13,396.48 ns - - - -
Iterate_PersistentMap_Standard 1000 50 1,626.01 ns - - - -
Iterate_ImmSortedDict 1000 50 4,912.18 ns - - - -
Iterate_ExtMap 1000 50 3,126.26 ns 0.0038 - - 32 B
Iterate_ExtHashMap 1000 50 14,857.12 ns 2.7924 - - 23472 B
Iterate_PersistentMap_Unicode 1000 50 1,654.97 ns - - - -
Remove_ImmDict 1000 50 22,385.84 ns 7.6904 0.3052 - 64352 B
Remove_PersistentMap_Standard 1000 50 25,269.13 ns 23.7122 1.9531 - 198400 B
Remove_PersistentMap_Unicode 1000 50 30,307.99 ns 26.7639 2.2583 - 224000 B
Remove_TransientMap_Standard 1000 50 9,482.18 ns 3.2654 0.2747 - 27368 B
Remove_TransientMap_Unicode 1000 50 13,754.52 ns 3.2959 0.2899 - 27624 B
Remove_ImmSortedDict 1000 50 32,695.64 ns 5.6763 0.1221 - 47664 B
Remove_ExtMap 1000 50 37,495.23 ns 6.9580 0.2441 - 58640 B
Remove_ExtHashMap 1000 50 14,713.28 ns 7.9193 0.2594 - 66264 B
Build_TransientMap_Standard 10000 8 1,680,964.28 ns 52.7344 15.6250 - 452352 B
Build_TransientMap_Unicode 10000 8 2,275,404.91 ns 66.4063 19.5313 - 576584 B
Build_ImmDict 10000 8 4,364,880.86 ns 1046.8750 507.8125 - 8766016 B
Build_ImmSortedDict 10000 8 6,551,472.85 ns 804.6875 281.2500 - 6767232 B
Build_ExtMap 10000 8 6,411,766.35 ns 1015.6250 437.5000 - 8542480 B
Build_ExtHashMap 10000 8 1,913,707.20 ns 945.3125 320.3125 - 7912992 B
Retrieve_ImmDict 10000 8 23,538.66 ns - - - -
Retrieve_PersistentMap_Standard 10000 8 44,522.29 ns - - - -
Retrieve_PersistentMap_Unicode 10000 8 33,878.51 ns - - - -
Retrieve_ImmSortedDict 10000 8 385,003.57 ns - - - -
Retrieve_ExtMap 10000 8 415,526.12 ns - - - -
Retrieve_ExtHashMap 10000 8 38,484.21 ns - - - -
Update_ImmDict 10000 8 395,683.89 ns 101.5625 26.3672 - 849792 B
Update_PersistentMap_Standard 10000 8 348,111.33 ns 304.6875 131.3477 - 2552000 B
Update_PersistentMap_Unicode 10000 8 415,082.82 ns 366.2109 160.1563 - 3064000 B
Update_TransientMap_Standard 10000 8 138,925.69 ns 40.5273 13.6719 - 339232 B
Update_TransientMap_Unicode 10000 8 155,075.00 ns 40.7715 16.6016 - 341792 B
Update_ImmSortedDict 10000 8 576,796.03 ns 76.1719 15.6250 - 640368 B
Update_ExtMap 10000 8 566,570.69 ns 87.8906 22.4609 - 735640 B
Update_ExtHashMap 10000 8 169,597.22 ns 103.0273 22.7051 - 862144 B
UpdateSet_ImmDict 10000 8 430,876.44 ns 108.3984 28.3203 - 907136 B
UpdateSet_PersistentMap_Standard 10000 8 390,932.56 ns 306.6406 136.7188 - 2566136 B
UpdateSet_PersistentMap_Unicode 10000 8 485,184.77 ns 368.6523 154.2969 - 3086432 B
UpdateSet_TransientMap_Standard 10000 8 183,267.74 ns 42.2363 16.3574 - 354776 B
UpdateSet_TransientMap_Unicode 10000 8 222,767.01 ns 43.7012 16.3574 - 365632 B
UpdateSet_ImmSortedDict 10000 8 648,381.31 ns 82.0313 19.5313 - 687648 B
UpdateSet_ExtMap 10000 8 637,483.97 ns 99.6094 25.3906 - 833752 B
UpdateSet_ExtHashMap 10000 8 189,210.57 ns 104.9805 23.6816 - 878600 B
Iterate_ImmDict 10000 8 176,031.53 ns - - - -
Iterate_PersistentMap_Standard 10000 8 17,218.51 ns - - - -
Iterate_ImmSortedDict 10000 8 56,553.28 ns - - - -
Iterate_ExtMap 10000 8 66,099.89 ns - - - 32 B
Iterate_ExtHashMap 10000 8 175,854.49 ns 20.0195 - - 168696 B
Iterate_PersistentMap_Unicode 10000 8 17,469.24 ns - - - -
Remove_ImmDict 10000 8 395,433.28 ns 102.5391 26.3672 - 858560 B
Remove_PersistentMap_Standard 10000 8 417,267.98 ns 302.2461 112.7930 - 2529408 B
Remove_PersistentMap_Unicode 10000 8 489,859.89 ns 363.2813 180.6641 - 3041408 B
Remove_TransientMap_Standard 10000 8 198,908.02 ns 37.8418 13.6719 - 316680 B
Remove_TransientMap_Unicode 10000 8 223,427.67 ns 38.0859 15.1367 - 319240 B
Remove_ImmSortedDict 10000 8 602,358.94 ns 77.1484 15.6250 - 652944 B
Remove_ExtMap 10000 8 614,493.62 ns 91.7969 20.5078 - 774000 B
Remove_ExtHashMap 10000 8 179,222.20 ns 104.0039 20.2637 - 870432 B
Build_TransientMap_Standard 10000 50 1,799,942.31 ns 52.7344 13.6719 - 446352 B
Build_TransientMap_Unicode 10000 50 2,336,360.10 ns 66.4063 23.4375 - 567112 B
Build_ImmDict 10000 50 4,618,106.24 ns 1046.8750 515.6250 - 8772288 B
Build_ImmSortedDict 10000 50 6,614,766.71 ns 804.6875 265.6250 - 6751584 B
Build_ExtMap 10000 50 6,524,244.50 ns 1015.6250 429.6875 - 8544720 B
Build_ExtHashMap 10000 50 2,195,902.51 ns 945.3125 312.5000 - 7921128 B
Retrieve_ImmDict 10000 50 53,644.62 ns - - - -
Retrieve_PersistentMap_Standard 10000 50 51,772.04 ns - - - -
Retrieve_PersistentMap_Unicode 10000 50 35,183.58 ns - - - -
Retrieve_ImmSortedDict 10000 50 384,954.19 ns - - - -
Retrieve_ExtMap 10000 50 419,295.20 ns - - - -
Retrieve_ExtHashMap 10000 50 68,364.13 ns - - - -
Update_ImmDict 10000 50 416,499.71 ns 100.5859 24.9023 - 842880 B
Update_PersistentMap_Standard 10000 50 352,007.58 ns 304.6875 131.3477 - 2552000 B
Update_PersistentMap_Unicode 10000 50 419,485.01 ns 366.2109 158.2031 - 3064000 B
Update_TransientMap_Standard 10000 50 145,767.49 ns 39.3066 13.6719 - 328832 B
Update_TransientMap_Unicode 10000 50 152,884.18 ns 39.5508 13.9160 - 331136 B
Update_ImmSortedDict 10000 50 581,461.95 ns 76.1719 14.6484 - 641616 B
Update_ExtMap 10000 50 562,336.86 ns 86.9141 20.5078 - 732896 B
Update_ExtHashMap 10000 50 189,986.29 ns 103.0273 22.2168 - 863280 B
UpdateSet_ImmDict 10000 50 457,611.78 ns 108.8867 30.7617 - 912128 B
UpdateSet_PersistentMap_Standard 10000 50 400,214.07 ns 306.6406 129.8828 - 2565560 B
UpdateSet_PersistentMap_Unicode 10000 50 497,552.64 ns 368.1641 152.3438 - 3085600 B
UpdateSet_TransientMap_Standard 10000 50 191,918.16 ns 41.0156 13.6719 - 343800 B
UpdateSet_TransientMap_Unicode 10000 50 222,651.45 ns 42.2363 15.8691 - 354144 B
UpdateSet_ImmSortedDict 10000 50 656,130.18 ns 82.0313 19.5313 - 691728 B
UpdateSet_ExtMap 10000 50 644,220.45 ns 98.6328 23.4375 - 829552 B
UpdateSet_ExtHashMap 10000 50 213,717.48 ns 104.7363 23.6816 - 876664 B
Iterate_ImmDict 10000 50 172,329.11 ns - - - -
Iterate_PersistentMap_Standard 10000 50 17,538.70 ns - - - -
Iterate_ImmSortedDict 10000 50 52,626.12 ns - - - -
Iterate_ExtMap 10000 50 75,440.14 ns - - - 32 B
Iterate_ExtHashMap 10000 50 176,467.34 ns 20.0195 - - 168192 B
Iterate_PersistentMap_Unicode 10000 50 17,931.81 ns - - - -
Remove_ImmDict 10000 50 420,385.25 ns 102.5391 26.3672 - 858432 B
Remove_PersistentMap_Standard 10000 50 417,831.54 ns 302.2461 113.7695 - 2530816 B
Remove_PersistentMap_Unicode 10000 50 488,933.92 ns 363.2813 158.2031 - 3042816 B
Remove_TransientMap_Standard 10000 50 215,079.21 ns 37.1094 13.4277 - 310504 B
Remove_TransientMap_Unicode 10000 50 221,947.80 ns 37.3535 13.1836 - 312808 B
Remove_ImmSortedDict 10000 50 607,856.65 ns 77.1484 15.6250 - 651840 B
Remove_ExtMap 10000 50 628,754.81 ns 91.7969 21.4844 - 771256 B
Remove_ExtHashMap 10000 50 203,488.31 ns 104.2480 21.4844 - 873560 B
Build_TransientMap_Standard 100000 8 27,358,697.21 ns 531.2500 406.2500 - 4540216 B
Build_TransientMap_Unicode 100000 8 30,530,320.71 ns 687.5000 593.7500 - 5798728 B
Build_ImmDict 100000 8 90,877,970.56 ns 13166.6667 4500.0000 166.6667 109369973 B
Build_ImmSortedDict 100000 8 116,689,394.37 ns 10000.0000 3800.0000 - 83946432 B
Build_ExtMap 100000 8 117,813,711.80 ns 12400.0000 5600.0000 - 104660688 B
Build_ExtHashMap 100000 8 44,164,471.41 ns 12000.0000 2583.3333 83.3333 99774201 B
Retrieve_ImmDict 100000 8 1,475,338.26 ns - - - -
Retrieve_PersistentMap_Standard 100000 8 1,774,506.52 ns - - - -
Retrieve_PersistentMap_Unicode 100000 8 1,336,091.68 ns - - - -
Retrieve_ImmSortedDict 100000 8 6,136,773.68 ns - - - -
Retrieve_ExtMap 100000 8 6,552,400.29 ns - - - -
Retrieve_ExtHashMap 100000 8 1,008,726.75 ns - - - -
Update_ImmDict 100000 8 7,725,041.14 ns 1265.6250 1070.3125 - 10622656 B
Update_PersistentMap_Standard 100000 8 9,751,403.12 ns 3734.3750 2984.3750 46.8750 30960042 B
Update_PersistentMap_Unicode 100000 8 11,106,373.87 ns 4671.8750 2468.7500 62.5000 38640073 B
Update_TransientMap_Standard 100000 8 3,072,594.67 ns 410.1563 347.6563 - 3458240 B
Update_TransientMap_Unicode 100000 8 2,678,497.53 ns 414.0625 351.5625 - 3487168 B
Update_ImmSortedDict 100000 8 9,958,696.31 ns 953.1250 781.2500 - 8020080 B
Update_ExtMap 100000 8 10,091,372.46 ns 1093.7500 937.5000 - 9246400 B
Update_ExtHashMap 100000 8 3,713,620.94 ns 1269.5313 996.0938 - 10625016 B
UpdateSet_ImmDict 100000 8 8,447,925.20 ns 1343.7500 1062.5000 - 11239232 B
UpdateSet_PersistentMap_Standard 100000 8 10,256,666.84 ns 3750.0000 2609.3750 46.8750 31066796 B
UpdateSet_PersistentMap_Unicode 100000 8 12,170,123.49 ns 4687.5000 2250.0000 62.5000 38809425 B
UpdateSet_TransientMap_Standard 100000 8 3,437,362.03 ns 421.8750 351.5625 - 3545288 B
UpdateSet_TransientMap_Unicode 100000 8 3,401,903.92 ns 433.5938 386.7188 - 3636832 B
UpdateSet_ImmSortedDict 100000 8 11,287,098.80 ns 1015.6250 875.0000 - 8495856 B
UpdateSet_ExtMap 100000 8 11,577,275.47 ns 1218.7500 1015.6250 - 10287328 B
UpdateSet_ExtHashMap 100000 8 3,795,803.13 ns 1285.1563 996.0938 - 10752160 B
Iterate_ImmDict 100000 8 2,176,936.15 ns - - - 192 B
Iterate_PersistentMap_Standard 100000 8 240,376.55 ns - - - -
Iterate_ImmSortedDict 100000 8 713,292.36 ns - - - -
Iterate_ExtMap 100000 8 1,041,016.32 ns - - - 32 B
Iterate_ExtHashMap 100000 8 2,609,178.31 ns 277.3438 - - 2321200 B
Iterate_PersistentMap_Unicode 100000 8 228,758.17 ns - - - -
Remove_ImmDict 100000 8 7,633,500.34 ns 1281.2500 1070.3125 - 10733056 B
Remove_PersistentMap_Standard 100000 8 10,634,178.02 ns 3718.7500 3093.7500 46.8750 30732714 B
Remove_PersistentMap_Unicode 100000 8 11,815,412.68 ns 4640.6250 2875.0000 62.5000 38412734 B
Remove_TransientMap_Standard 100000 8 3,501,181.09 ns 378.9063 312.5000 - 3197160 B
Remove_TransientMap_Unicode 100000 8 3,113,607.62 ns 382.8125 324.2188 - 3226088 B
Remove_ImmSortedDict 100000 8 10,204,663.55 ns 953.1250 781.2500 - 8031888 B
Remove_ExtMap 100000 8 11,026,369.80 ns 1140.6250 937.5000 - 9630448 B
Remove_ExtHashMap 100000 8 3,801,747.29 ns 1265.6250 937.5000 - 10608872 B
Build_TransientMap_Standard 100000 50 31,414,873.58 ns 500.0000 312.5000 - 4518440 B
Build_TransientMap_Unicode 100000 50 34,272,872.95 ns 666.6667 466.6667 - 5763784 B
Build_ImmDict 100000 50 89,991,315.99 ns 13166.6667 4833.3333 166.6667 109418176 B
Build_ImmSortedDict 100000 50 131,306,574.64 ns 10000.0000 4000.0000 - 83731632 B
Build_ExtMap 100000 50 128,889,148.68 ns 12250.0000 5250.0000 - 104371560 B
Build_ExtHashMap 100000 50 48,924,428.69 ns 11909.0909 2272.7273 - 99798944 B
Retrieve_ImmDict 100000 50 1,789,773.89 ns - - - -
Retrieve_PersistentMap_Standard 100000 50 2,280,540.33 ns - - - -
Retrieve_PersistentMap_Unicode 100000 50 1,447,748.76 ns - - - -
Retrieve_ImmSortedDict 100000 50 7,097,150.11 ns - - - -
Retrieve_ExtMap 100000 50 7,013,962.09 ns - - - -
Retrieve_ExtHashMap 100000 50 1,327,343.45 ns - - - -
Update_ImmDict 100000 50 8,075,323.36 ns 1265.6250 1062.5000 - 10593088 B
Update_PersistentMap_Standard 100000 50 11,441,201.31 ns 3734.3750 3421.8750 46.8750 30960051 B
Update_PersistentMap_Unicode 100000 50 11,646,138.25 ns 4656.2500 2765.6250 46.8750 38640052 B
Update_TransientMap_Standard 100000 50 3,785,331.39 ns 406.2500 347.6563 - 3410592 B
Update_TransientMap_Unicode 100000 50 2,931,528.16 ns 410.1563 343.7500 - 3440288 B
Update_ImmSortedDict 100000 50 11,055,325.40 ns 953.1250 781.2500 - 8012928 B
Update_ExtMap 100000 50 10,703,171.07 ns 1093.7500 906.2500 - 9233632 B
Update_ExtHashMap 100000 50 4,100,682.76 ns 1265.6250 976.5625 - 10623184 B
UpdateSet_ImmDict 100000 50 8,848,378.05 ns 1343.7500 1046.8750 - 11255552 B
UpdateSet_PersistentMap_Standard 100000 50 12,223,495.13 ns 3734.3750 2640.6250 31.2500 31083384 B
UpdateSet_PersistentMap_Unicode 100000 50 12,917,217.90 ns 4687.5000 2437.5000 46.8750 38835954 B
UpdateSet_TransientMap_Standard 100000 50 4,490,436.88 ns 414.0625 343.7500 - 3528320 B
UpdateSet_TransientMap_Unicode 100000 50 3,756,285.03 ns 433.5938 367.1875 - 3630560 B
UpdateSet_ImmSortedDict 100000 50 12,490,770.48 ns 1015.6250 890.6250 - 8501136 B
UpdateSet_ExtMap 100000 50 12,674,840.15 ns 1218.7500 1015.6250 - 10265544 B
UpdateSet_ExtHashMap 100000 50 4,395,939.08 ns 1281.2500 992.1875 - 10756792 B
Iterate_ImmDict 100000 50 2,416,834.88 ns - - - 96 B
Iterate_PersistentMap_Standard 100000 50 214,203.41 ns - - - -
Iterate_ImmSortedDict 100000 50 712,519.08 ns - - - -
Iterate_ExtMap 100000 50 1,091,987.30 ns - - - 32 B
Iterate_ExtHashMap 100000 50 2,669,431.61 ns 273.4375 - - 2314072 B
Iterate_PersistentMap_Unicode 100000 50 211,247.16 ns - - - -
Remove_ImmDict 100000 50 8,089,556.02 ns 1281.2500 1031.2500 - 10743040 B
Remove_PersistentMap_Standard 100000 50 11,874,296.78 ns 3703.1250 2750.0000 31.2500 30722852 B
Remove_PersistentMap_Unicode 100000 50 11,948,106.52 ns 4625.0000 2859.3750 46.8750 38402877 B
Remove_TransientMap_Standard 100000 50 4,337,489.41 ns 375.0000 304.6875 - 3176264 B
Remove_TransientMap_Unicode 100000 50 3,278,674.84 ns 382.8125 312.5000 - 3205960 B
Remove_ImmSortedDict 100000 50 11,338,022.46 ns 953.1250 781.2500 - 8032656 B
Remove_ExtMap 100000 50 11,912,777.70 ns 1140.6250 921.8750 - 9617232 B
Remove_ExtHashMap 100000 50 4,223,945.68 ns 1265.6250 937.5000 - 10621824 B #+end_src

Architecture Notes: Key Strategies

NiceBtree uses IKeyStrategy<K> to map generic keys (like string or double) into sortable long prefixes. This achieves two things:

  1. Enables AVX512/AVX2 vector instructions to search internal nodes simultaneously.
  2. Avoids expensive IComparable<T> interface calls or string.Compare during the initial descent of the tree, only falling back to exact comparisons when refining the search within a leaf.

This means that it will be fast for integers and anything you can pack in 8 bytes. If you use stings with high prefix entropy, this will be very performant. If you don't, it is just another b+tree.