| Crates.io | wt-indexset |
| lib.rs | wt-indexset |
| version | 0.12.8 |
| created_at | 2025-07-13 22:23:19.054102+00 |
| updated_at | 2025-09-19 19:37:04.708265+00 |
| description | Fork of original indexset which is used for worktable |
| homepage | |
| repository | https://github.com/Handy-caT/indexset |
| max_upload_size | |
| id | 1750881 |
| size | 312,855 |
A pure-Rust two-level dynamic order-statistic b-tree.
This crate implements a compact set data structure that preserves its elements' sorted order and allows lookups of entries by value or sorted order position.
Under the feature concurrent you can find a version of the BTree that can be fearlessly shared between
threads.
Both the concurrent and single-threaded versions are meant to be drop-in replacements for the stdlib BTree. This is mostly true for the latter but not for the former, yet.
The following table describes the variants of this data structure that are available:
| Variant | tl;dr | Stability |
|---|---|---|
| crate::BTreeSet | A single-threaded ordered set | Stable |
| crate::BTreeMap | A single-threaded ordered map | Stable |
| crate::concurrent::set::BTreeSet | A concurrent ordered set | Beta |
| crate::concurrent::map::BTreeMap | A concurrent ordered map | Beta |
| crate::concurrent::multimap::BTreeMultiMap | A concurrent ordered map where keys need not to be unique | Alpha |
serde: implements serialization and deserialization traits for the single-threaded treesconcurrent: enables the three concurrent variants of BTreeSet referenced in the table abovecdc: provides helper methods to persist all concurrent treesmultimap: enables BTreeMultiMapThis was heavily inspired by indexmap, and
python's sortedcontainers.
It differs from both in that:
indexmap is a hashmap that provides numerical lookups, but does not maintain order in case of removals, while
indexset's core data structure is a b-tree that irrespective of which mutating operation is run, always maintains order.sortecontainers is similar in spirit, but utilizes a different routine for balancing the tree, and relies
on a heap for numerical lookups.indexset provides the following features:
select(lookups by position) and rank operations in near constant time (not yet in the concurrent versions).BTreeSet and BTreeMap derive their performance much from how they are constructed, which is:
A two-level B-Tree with a fenwick tree as a low-cost index for numerical lookups
Each node is a leaf, and each leaf is a vec with a fixed capacity of size B, with 1024 being the default.
The following hold:
n/B nodes and another over B elements: O(log(n/B) + log(B)) = O(log(n)).O(B) in the best case and O(B^2) in the worst. Removals are O(log(n)).The following numbers were obtained on a M3 macbook pro:
Command: cargo bench --bench stdlib --all-features
stdlib::collections::BTreeSet.insert(i): 8.9msindexset::BTreeSet.insert(i): 13.1msindexset::concurrent::set::BTreeSet.insert(i): 14.0msstdlib::collections::BTreeSet.contains(i): 7.02msindexset::BTreeSet.contains(i): 5.22msindexset::concurrent::set::BTreeSet.contains(i): 5.27msstdlib::collections::BTreeSet.iter.nth(i): 13.28s yes, seconds!indexset::BTreeSet.get_index(i): 3.93msVec::from_iter(stdlib::collections::BTreeSet.iter()): 227.28usVec::from_iter(indexset::BTreeSet.iter()): 123.21.usGetting the i-th element is 3400x faster than stdlib's btree, contains is 25% faster, and iterating is twice
as fast, at the cost of insertions being 30% slower.
If your use case of std::collections::BTreeSet and BTreeMap is read-heavy, or if you really need to index by
sorted-order position, it might be worth checking out indexset instead.
Command: cargo bench --bench concurrent --all-features
We benchmark concurrent operations with 40 threads, each conducting 100000 operations at the same time that vary from a ratio of 1% writes/reads to 50% writes/reads.
In this benchmark threads have high locality and tend to focus on specific parts of the data.
indexset::concurrent::set::BTreeSet: 170.5msscc::TreeIndex: 128.7mscrossbeam_skiplist::SkipSet: 161.3msindexset::concurrent::set::BTreeSet: 175.9msscc::TreeIndex: 183.9mscrossbeam_skiplist::SkipSet: 217.4msindexset::concurrent::set::BTreeSet: 190.9msscc::TreeIndex: 313.2mscrossbeam_skiplist::SkipSet: 261.8msindexset::concurrent::set::BTreeSet: 220.75msscc::TreeIndex: 561.70mscrossbeam_skiplist::SkipSet: 334.40msBTreeMap is less polished than BTreeSet. This crate has been optimised for a leaner BTreeSet.Concurrent BtreeSet, BTreeMap and BTreeMultiMap do not support serde serialization and deserialization nor are they order-statistic trees.This library is called indexset because the base data structure is BTreeSet. BTreeMap is a BTreeSet with
a Pair<K, V> item type, and BTreeMultiMap is one with a MultiPair<K, V> item.
See CHANGELOG.md.