Andrew Noyes e5b9c03e77 Restore change that hurt codegen
I don't understand, but this is necessary for good codegen somehow
2024-11-18 14:29:55 -08:00
2024-03-06 21:22:30 -08:00
2024-11-15 15:47:32 -08:00
2024-08-21 14:00:00 -07:00
2024-08-05 12:20:38 -07:00
2024-04-04 16:29:26 -07:00
2024-11-18 14:05:14 -08:00
2024-11-15 16:49:21 -08:00
2024-02-20 13:22:22 -08:00
2024-01-30 10:39:43 -08:00
2024-08-30 16:06:43 -07:00
2024-09-09 20:10:55 -07:00
2024-11-10 21:47:26 -08:00
2024-11-18 14:05:14 -08:00
2024-11-12 17:50:27 -08:00

A data structure for optimistic concurrency control on ranges of bitwise-lexicographically-ordered keys.

Intended as an alternative to FoundationDB's skip list.

Hardware for all benchmarks is an AMD Ryzen 9 7900 with (2x32GB) 5600MT/s CL28-34-34-89 1.35V RAM.

$ clang++ --version

Ubuntu clang version 20.0.0 (++20241118082208+63b926af5ff4-1~exp1~20241118082226.549)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm-20/bin
```

# Microbenchmark

## Skip list

|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|              164.92 |        6,063,693.08 |    0.0% |        3,014.03 |          829.48 |  3.634 |         504.59 |    0.0% |      1.97 | `point reads`
|              162.85 |        6,140,505.89 |    0.0% |        2,954.16 |          819.09 |  3.607 |         490.17 |    0.0% |      1.94 | `prefix reads`
|              243.06 |        4,114,132.65 |    0.0% |        3,592.41 |        1,224.74 |  2.933 |         629.31 |    0.0% |      2.90 | `range reads`
|              455.46 |        2,195,561.38 |    0.0% |        4,450.57 |        2,301.93 |  1.933 |         707.92 |    2.1% |      5.44 | `point writes`
|              454.16 |        2,201,858.08 |    0.0% |        4,410.22 |        2,295.25 |  1.921 |         694.74 |    2.1% |      5.42 | `prefix writes`
|              302.97 |        3,300,699.07 |    0.0% |        2,315.38 |        1,531.20 |  1.512 |         396.69 |    3.3% |      3.64 | `range writes`
|              493.69 |        2,025,564.75 |    0.9% |        6,999.33 |        2,493.53 |  2.807 |       1,251.74 |    1.3% |      0.06 | `monotonic increasing point writes`
|          136,298.50 |            7,336.84 |    0.9% |      807,444.50 |      693,845.50 |  1.164 |     144,584.50 |    0.9% |      0.01 | `worst case for radix tree`
|               47.68 |       20,974,738.11 |    0.7% |          902.00 |          238.47 |  3.783 |         132.00 |    0.0% |      0.01 | `create and destroy`

## Radix tree (this implementation)


|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|               12.73 |       78,578,520.69 |    0.0% |          247.13 |           64.01 |  3.861 |          32.64 |    0.6% |      0.15 | `point reads`
|               14.48 |       69,077,363.01 |    0.1% |          299.99 |           72.83 |  4.119 |          42.50 |    0.4% |      0.17 | `prefix reads`
|               35.33 |       28,307,787.32 |    0.1% |          782.70 |          177.67 |  4.405 |         106.65 |    0.2% |      0.42 | `range reads`
|               20.64 |       48,445,877.80 |    0.0% |          376.04 |          103.84 |  3.621 |          49.97 |    0.7% |      0.25 | `point writes`
|               38.32 |       26,098,688.72 |    0.0% |          665.25 |          192.72 |  3.452 |         101.33 |    0.4% |      0.46 | `prefix writes`
|               39.46 |       25,343,458.68 |    0.0% |          732.48 |          198.44 |  3.691 |         111.75 |    0.1% |      0.48 | `range writes`
|               80.63 |       12,401,923.78 |    2.4% |        1,461.96 |          407.42 |  3.588 |         278.93 |    0.1% |      0.01 | `monotonic increasing point writes`
|          311,077.67 |            3,214.63 |    0.5% |    4,016,995.00 |    1,582,232.00 |  2.539 |     714,572.00 |    0.1% |      0.01 | `worst case for radix tree`
|              106.36 |        9,401,962.15 |    0.9% |        2,046.00 |          538.76 |  3.798 |         329.00 |    0.0% |      0.01 | `create and destroy`

# "Real data" test

Point queries only. Gc ratio is the ratio of time spent doing garbage collection to time spent adding writes or doing garbage collection. Lower is better.

## skip list

```
Check: 4.35798 seconds, 386.919 MB/s, Add: 3.69297 seconds, 155.792 MB/s, Gc ratio: 33.6285%, Peak idle memory: 5.61007e+06
```

## radix tree

```
Check: 1.0184 seconds, 1655.72 MB/s, Add: 1.3866 seconds, 414.924 MB/s, Gc ratio: 34.8706%, Peak idle memory: 2.32922e+06
```

## hash table

(The hash table implementation doesn't work on range queries, and its purpose is to provide an idea of how fast point queries can be)

```
Check: 0.855065 seconds, 1972 MB/s, Add: 0.711856 seconds, 808.219 MB/s, Gc ratio: 34.9436%, Peak idle memory: 0
```

Description
A data structure for optimistic concurrency control on ranges of bitwise-lexicographically-ordered keys.
Readme 25 MiB
v0.0.13 Latest
2024-08-26 21:24:21 +00:00
Languages
C++ 82.9%
TeX 8.1%
CMake 4.8%
Python 2.7%
Shell 0.9%
Other 0.6%