Initial commit
This commit is contained in:
93
vendor/github.com/cockroachdb/pebble/internal/arenaskl/README.md
generated
vendored
Normal file
93
vendor/github.com/cockroachdb/pebble/internal/arenaskl/README.md
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
# arenaskl
|
||||
|
||||
Fast, lock-free, arena-based Skiplist implementation in Go that supports iteration
|
||||
in both directions.
|
||||
|
||||
## Advantages
|
||||
|
||||
Arenaskl offers several advantages over other skiplist implementations:
|
||||
|
||||
* High performance that linearly scales with the number of cores. This is
|
||||
achieved by allocating from a fixed-size arena and by avoiding locks.
|
||||
* Iterators that can be allocated on the stack and easily cloned by value.
|
||||
* Simple-to-use and low overhead model for detecting and handling race conditions
|
||||
with other threads.
|
||||
* Support for iterating in reverse (i.e. previous links).
|
||||
|
||||
## Limitations
|
||||
|
||||
The advantages come at a cost that prevents arenaskl from being a general-purpose
|
||||
skiplist implementation:
|
||||
|
||||
* The size of the arena sets a hard upper bound on the combined size of skiplist
|
||||
nodes, keys, and values. This limit includes even the size of deleted nodes,
|
||||
keys, and values.
|
||||
* Deletion is not supported. Instead, higher-level code is expected to
|
||||
add deletion tombstones and needs to process those tombstones
|
||||
appropriately.
|
||||
|
||||
## Pedigree
|
||||
|
||||
This code is based on Andy Kimball's arenaskl code:
|
||||
|
||||
https://github.com/andy-kimball/arenaskl
|
||||
|
||||
The arenaskl code is based on the skiplist found in Badger, a Go-based
|
||||
KV store:
|
||||
|
||||
https://github.com/dgraph-io/badger/tree/master/skl
|
||||
|
||||
The skiplist in Badger is itself based on a C++ skiplist built for
|
||||
Facebook's RocksDB:
|
||||
|
||||
https://github.com/facebook/rocksdb/tree/master/memtable
|
||||
|
||||
## Benchmarks
|
||||
|
||||
The benchmarks consist of a mix of reads and writes executed in parallel. The
|
||||
fraction of reads is indicated in the run name: "frac_X" indicates a run where
|
||||
X percent of the operations are reads.
|
||||
|
||||
The results are much better than `skiplist` and `slist`.
|
||||
|
||||
```
|
||||
name time/op
|
||||
ReadWrite/frac_0-8 470ns ±11%
|
||||
ReadWrite/frac_10-8 462ns ± 3%
|
||||
ReadWrite/frac_20-8 436ns ± 2%
|
||||
ReadWrite/frac_30-8 410ns ± 2%
|
||||
ReadWrite/frac_40-8 385ns ± 2%
|
||||
ReadWrite/frac_50-8 360ns ± 4%
|
||||
ReadWrite/frac_60-8 386ns ± 1%
|
||||
ReadWrite/frac_70-8 352ns ± 2%
|
||||
ReadWrite/frac_80-8 306ns ± 3%
|
||||
ReadWrite/frac_90-8 253ns ± 4%
|
||||
ReadWrite/frac_100-8 28.1ns ± 2%
|
||||
```
|
||||
|
||||
Note that the above numbers are for concurrent operations using 8x
|
||||
parallelism. The same benchmarks without concurrency (use these
|
||||
numbers when comparing vs batchskl):
|
||||
|
||||
```
|
||||
name time/op
|
||||
ReadWrite/frac_0 1.53µs ± 1%
|
||||
ReadWrite/frac_10 1.46µs ± 2%
|
||||
ReadWrite/frac_20 1.39µs ± 3%
|
||||
ReadWrite/frac_30 1.28µs ± 3%
|
||||
ReadWrite/frac_40 1.21µs ± 2%
|
||||
ReadWrite/frac_50 1.11µs ± 3%
|
||||
ReadWrite/frac_60 1.23µs ±17%
|
||||
ReadWrite/frac_70 1.16µs ± 4%
|
||||
ReadWrite/frac_80 959ns ± 3%
|
||||
ReadWrite/frac_90 738ns ± 5%
|
||||
ReadWrite/frac_100 81.9ns ± 2%
|
||||
```
|
||||
|
||||
Forward and backward iteration are also fast:
|
||||
|
||||
```
|
||||
name time/op
|
||||
IterNext 3.97ns ± 5%
|
||||
IterPrev 3.88ns ± 3%
|
||||
```
|
||||
Reference in New Issue
Block a user