consistent-milk12/masstree

An implementation of the C++ Masstree data structure in Rust.

Rust

225

109 commits

updated Aug 2, 2026

See the code

README

masstree

A high-performance concurrent ordered map for Rust. It stores keys as &[u8] and supports variable-length keys by building a trie of B+trees, based on the Masstree paper

Disclaimer: This is an independent implementation. It is not endorsed by, affiliated with, or connected to the original Masstree authors or their institutions.

Status

Current Version: v0.9.5

Significantly reduced duplicate code through trait based abstractions, while improving performance further. All standard data structure features are implemented and streamlined, on top the specialized features like range scans and prefix queries. From latency analysis, it seems to have a surprisingly strong tail latency profile for a concurrent ordered map. The cache-line aligned layout design and aggressive prefetching seems to have paid off, on top of masstree's original excellent architecture.

The next issues to work on are the memory profile (some progress) and memcomparable mappings for general key types, before 1.0.

NOTE: All benchmarks were run with mimalloc feature.

vs Rust Concurrent Maps (12T SMT)

Source: runs/run208_read_write.txt (masstree), runs/run184_read_write_reworked.txt (competitors) Config: 12 threads on 6 physical cores (SMT/hyperthreading), 200 samples.

Benchmarkmasstree15tree_indexskipmapindexsetMT vs Best
01_uniform53.1614.4910.8014.943.56x
02_zipfian45.5418.8612.923.282.42x
03_shared_prefix31.8414.6111.0814.362.18x
04_high_contention79.8121.6416.901.973.69x
05_large_dataset18.7211.357.509.171.65x
06_single_hot_key15.586.827.462.522.09x
07_mixed_50_5040.418.736.4614.862.72x
08_8byte_keys62.4724.9714.0619.692.50x
09_pure_read56.7724.1214.4017.402.35x
10_remove_heavy26.6911.187.184.262.39x
13_insert_only_fair44.7924.2915.136.301.84x
14_pure_insert15.2811.969.862.301.28x

High-Impact Workloads (12T SMT)

Source: runs/run206_high_impact.txt (masstree), runs/run188_high_impact.txt (competitors) Config: 12 threads on 6 physical cores (SMT), 200 samples

Benchmarks targeting Masstree's architectural advantages: long keys, variable-length keys, hot key patterns, mixed operations, prefix queries, deep trie traversal, and mixed prefix workloads.

Benchmarkmasstree15indexsettree_indexskipmapMT vs Best
01_long_keys_128b44.5314.5813.1911.113.05x
02_multiple_hot_keys43.4714.0213.5813.443.10x
03_mixed_get_insert_remove30.615.9610.248.7672.99x
04_variable_long_keys36.339.438.6447.8423.85x
05_prefix_queries (Kitem/s)1115n/a508.4145.22.19x
06_deep_trie_traversal31.4913.438.1229.5542.34x
07_deep_trie_read_only41.2314.9914.7713.772.75x
08_variable_keys_arc36.3111.7910.609.0473.08x
09_prefix_realistic_mixed6.133n/a3.0291.0512.02x

Range Scans (6T Physical)

Source: runs/run191_range_scan.txt Config: Physical cores only, 200 samples, performance governor

Benchmarkmasstree15_inlinetree_indexMT vs TI
01_sequential_full_scan26.7313.072.04x
02_reverse_scan27.8713.272.10x
03_clustered_scan25.1613.081.92x
04_sparse_scan22.2812.781.74x
05_shared_prefix_scan22.9315.331.50x
06_suffix_differ_scan21.2814.551.46x
07_hierarchical_scan24.4714.601.68x
08_adversarial_splits26.838.8073.05x
09_interleaved_scan22.4112.861.74x
10_blink_stress_scan24.4812.811.91x
11_random_keys_scan26.0212.362.10x
12_long_keys_64b_scan26.0614.241.83x
15_full_scan_aggregate183.184.592.16x
16_insert_heavy23.1817.381.33x
17_hot_spot11.245.3182.11x

Range Scans (12T SMT)

Source: runs/run191_range_scan.txt Config: 12 threads on 6 physical cores (SMT), 200 samples

Benchmarkmasstree15_inlinetree_indexMT vs TI
01_sequential_full_scan31.7714.492.19x
02_reverse_scan29.9614.662.04x
03_clustered_scan31.8514.542.19x
04_sparse_scan30.9514.582.12x
05_shared_prefix_scan24.8818.621.34x
06_suffix_differ_scan23.4118.161.29x
07_hierarchical_scan26.9918.461.46x
08_adversarial_splits29.1011.322.57x
09_interleaved_scan24.8215.341.62x
10_blink_stress_scan30.0515.121.99x
11_random_keys_scan25.6214.701.74x
12_long_keys_64b_scan28.2917.771.59x
15_full_scan_aggregate230.8111.92.06x
16_insert_heavy25.0921.881.15x
17_hot_spot10.616.4581.64x

Tail Latency (pbench, Per-Operation)

Source: runs/run213_tail_latency.txt (8T), runs/run207_tail_latency.txt (1T) Config: 200k samples per benchmark, sample_size=1 (unbatched), TSC timer (10 ns precision)

Point Lookups

Benchmarkmasstreetreeindexskipmapindexset
get 1T p50140 ns250 ns350 ns270 ns
get 1T p99.9501 ns411 ns801 ns621 ns
get 8T p50340 ns551 ns621 ns591 ns
get 8T p99.9922 ns1.15 us1.36 us1.34 us
get 1M 1T p50321 ns461 ns691 ns521 ns
get deep 8T p50661 ns741 ns831 ns-
get long 8T p50611 ns581 ns701 ns-

Inserts

Benchmarkmasstreetreeindexskipmapindexset
insert 1T p50110 ns220 ns190 ns571 ns
insert 1T p99.9601 ns1.21 us661 ns2.93 us
insert 8T p50691 ns812 ns1.09 us5.93 us
insert 8T p99.980.3 us21.1 us5.70 us45.8 us

Mixed Read/Write (8T)

Benchmarkmasstreetreeindexskipmapindexset
90/10 p50381 ns601 ns681 ns621 ns
90/10 p99.91.04 us4.18 us5.95 us1.39 us
50/50 p50421 ns1.01 us1.09 us691 ns
50/50 p99.91.04 us6.66 us10.3 us1.57 us

Range Scans (8T, 50-key scan)

Benchmarkmasstreetreeindexskipmap
scan p50972 ns862 ns3.90 us
scan+write p50902 ns1.02 us3.97 us
scan+write p99.92.50 us6.66 us9.99 us

Install

[dependencies]
masstree = { version = "0.9.5", features = ["mimalloc"] }

MSRV is Rust 1.92+ (Edition 2024).

The mimalloc feature sets the global allocator. If your project already uses a custom allocator, omit this feature.

Quick Start

use masstree::{MassTree, RangeBound};

let tree: MassTree<u64> = MassTree::new();
let guard = tree.guard();

// Insert (returns None for new keys, Some(old) for existing)
tree.insert_with_guard(b"hello", 123, &guard);
tree.insert_with_guard(b"world", 456, &guard);

// Point lookup (returns copy for inline storage)
assert_eq!(tree.get_with_guard(b"hello", &guard), Some(123));

// Remove
tree.remove_with_guard(b"hello", &guard).unwrap();
assert_eq!(tree.get_with_guard(b"hello", &guard), None);

// Range scan
tree.scan(
    RangeBound::Included(b"a"),
    RangeBound::Excluded(b"z"),
    |key, value| {
        println!("{:?} -> {}", key, value);
        true // continue scanning
    },
    &guard,
);

// Prefix scan
tree.scan_prefix(b"wor", |key, value| {
    println!("{:?} -> {}", key, value);
    true
}, &guard);

Ergonomic APIs

For simpler use cases, auto-guard versions create guards internally:

use masstree::MassTree;

let tree: MassTree<u64> = MassTree::new();

// Auto-guard versions (simpler but slightly more overhead per call)
tree.insert(b"key1", 100);
tree.insert(b"key2", 200);

assert_eq!(tree.get(b"key1"), Some(100));
assert_eq!(tree.len(), 2);
assert!(!tree.is_empty());

tree.remove(b"key1").unwrap();

Range Iteration

use masstree::{MassTree, RangeBound};

let tree: MassTree<u64> = MassTree::new();
let guard = tree.guard();

// Populate
for i in 0..100u64 {
    tree.insert_with_guard(&i.to_be_bytes(), i, &guard);
}

// Iterator-based range scan
for entry in tree.range(RangeBound::Included(b""), RangeBound::Unbounded, &guard) {
    println!("{:?} -> {:?}", entry.key(), entry.value());
}

// Full iteration
for entry in tree.iter(&guard) {
    println!("{:?}", entry.key());
}

License

MIT. See LICENSE.

References

consistent-milk12/masstree

An implementation of the C++ Masstree data structure in Rust.

Rust

225

109 commits

updated Aug 2, 2026

See the code

README

masstree

A high-performance concurrent ordered map for Rust. It stores keys as &[u8] and supports variable-length keys by building a trie of B+trees, based on the Masstree paper

Disclaimer: This is an independent implementation. It is not endorsed by, affiliated with, or connected to the original Masstree authors or their institutions.

Status

Current Version: v0.9.5

Significantly reduced duplicate code through trait based abstractions, while improving performance further. All standard data structure features are implemented and streamlined, on top the specialized features like range scans and prefix queries. From latency analysis, it seems to have a surprisingly strong tail latency profile for a concurrent ordered map. The cache-line aligned layout design and aggressive prefetching seems to have paid off, on top of masstree's original excellent architecture.

The next issues to work on are the memory profile (some progress) and memcomparable mappings for general key types, before 1.0.

NOTE: All benchmarks were run with mimalloc feature.

vs Rust Concurrent Maps (12T SMT)

Source: runs/run208_read_write.txt (masstree), runs/run184_read_write_reworked.txt (competitors) Config: 12 threads on 6 physical cores (SMT/hyperthreading), 200 samples.

Benchmarkmasstree15tree_indexskipmapindexsetMT vs Best
01_uniform53.1614.4910.8014.943.56x
02_zipfian45.5418.8612.923.282.42x
03_shared_prefix31.8414.6111.0814.362.18x
04_high_contention79.8121.6416.901.973.69x
05_large_dataset18.7211.357.509.171.65x
06_single_hot_key15.586.827.462.522.09x
07_mixed_50_5040.418.736.4614.862.72x
08_8byte_keys62.4724.9714.0619.692.50x
09_pure_read56.7724.1214.4017.402.35x
10_remove_heavy26.6911.187.184.262.39x
13_insert_only_fair44.7924.2915.136.301.84x
14_pure_insert15.2811.969.862.301.28x

High-Impact Workloads (12T SMT)

Source: runs/run206_high_impact.txt (masstree), runs/run188_high_impact.txt (competitors) Config: 12 threads on 6 physical cores (SMT), 200 samples

Benchmarks targeting Masstree's architectural advantages: long keys, variable-length keys, hot key patterns, mixed operations, prefix queries, deep trie traversal, and mixed prefix workloads.

Benchmarkmasstree15indexsettree_indexskipmapMT vs Best
01_long_keys_128b44.5314.5813.1911.113.05x
02_multiple_hot_keys43.4714.0213.5813.443.10x
03_mixed_get_insert_remove30.615.9610.248.7672.99x
04_variable_long_keys36.339.438.6447.8423.85x
05_prefix_queries (Kitem/s)1115n/a508.4145.22.19x
06_deep_trie_traversal31.4913.438.1229.5542.34x
07_deep_trie_read_only41.2314.9914.7713.772.75x
08_variable_keys_arc36.3111.7910.609.0473.08x
09_prefix_realistic_mixed6.133n/a3.0291.0512.02x

Range Scans (6T Physical)

Source: runs/run191_range_scan.txt Config: Physical cores only, 200 samples, performance governor

Benchmarkmasstree15_inlinetree_indexMT vs TI
01_sequential_full_scan26.7313.072.04x
02_reverse_scan27.8713.272.10x
03_clustered_scan25.1613.081.92x
04_sparse_scan22.2812.781.74x
05_shared_prefix_scan22.9315.331.50x
06_suffix_differ_scan21.2814.551.46x
07_hierarchical_scan24.4714.601.68x
08_adversarial_splits26.838.8073.05x
09_interleaved_scan22.4112.861.74x
10_blink_stress_scan24.4812.811.91x
11_random_keys_scan26.0212.362.10x
12_long_keys_64b_scan26.0614.241.83x
15_full_scan_aggregate183.184.592.16x
16_insert_heavy23.1817.381.33x
17_hot_spot11.245.3182.11x

Range Scans (12T SMT)

Source: runs/run191_range_scan.txt Config: 12 threads on 6 physical cores (SMT), 200 samples

Benchmarkmasstree15_inlinetree_indexMT vs TI
01_sequential_full_scan31.7714.492.19x
02_reverse_scan29.9614.662.04x
03_clustered_scan31.8514.542.19x
04_sparse_scan30.9514.582.12x
05_shared_prefix_scan24.8818.621.34x
06_suffix_differ_scan23.4118.161.29x
07_hierarchical_scan26.9918.461.46x
08_adversarial_splits29.1011.322.57x
09_interleaved_scan24.8215.341.62x
10_blink_stress_scan30.0515.121.99x
11_random_keys_scan25.6214.701.74x
12_long_keys_64b_scan28.2917.771.59x
15_full_scan_aggregate230.8111.92.06x
16_insert_heavy25.0921.881.15x
17_hot_spot10.616.4581.64x

Tail Latency (pbench, Per-Operation)

Source: runs/run213_tail_latency.txt (8T), runs/run207_tail_latency.txt (1T) Config: 200k samples per benchmark, sample_size=1 (unbatched), TSC timer (10 ns precision)

Point Lookups

Benchmarkmasstreetreeindexskipmapindexset
get 1T p50140 ns250 ns350 ns270 ns
get 1T p99.9501 ns411 ns801 ns621 ns
get 8T p50340 ns551 ns621 ns591 ns
get 8T p99.9922 ns1.15 us1.36 us1.34 us
get 1M 1T p50321 ns461 ns691 ns521 ns
get deep 8T p50661 ns741 ns831 ns-
get long 8T p50611 ns581 ns701 ns-

Inserts

Benchmarkmasstreetreeindexskipmapindexset
insert 1T p50110 ns220 ns190 ns571 ns
insert 1T p99.9601 ns1.21 us661 ns2.93 us
insert 8T p50691 ns812 ns1.09 us5.93 us
insert 8T p99.980.3 us21.1 us5.70 us45.8 us

Mixed Read/Write (8T)

Benchmarkmasstreetreeindexskipmapindexset
90/10 p50381 ns601 ns681 ns621 ns
90/10 p99.91.04 us4.18 us5.95 us1.39 us
50/50 p50421 ns1.01 us1.09 us691 ns
50/50 p99.91.04 us6.66 us10.3 us1.57 us

Range Scans (8T, 50-key scan)

Benchmarkmasstreetreeindexskipmap
scan p50972 ns862 ns3.90 us
scan+write p50902 ns1.02 us3.97 us
scan+write p99.92.50 us6.66 us9.99 us

Install

[dependencies]
masstree = { version = "0.9.5", features = ["mimalloc"] }

MSRV is Rust 1.92+ (Edition 2024).

The mimalloc feature sets the global allocator. If your project already uses a custom allocator, omit this feature.

Quick Start

use masstree::{MassTree, RangeBound};

let tree: MassTree<u64> = MassTree::new();
let guard = tree.guard();

// Insert (returns None for new keys, Some(old) for existing)
tree.insert_with_guard(b"hello", 123, &guard);
tree.insert_with_guard(b"world", 456, &guard);

// Point lookup (returns copy for inline storage)
assert_eq!(tree.get_with_guard(b"hello", &guard), Some(123));

// Remove
tree.remove_with_guard(b"hello", &guard).unwrap();
assert_eq!(tree.get_with_guard(b"hello", &guard), None);

// Range scan
tree.scan(
    RangeBound::Included(b"a"),
    RangeBound::Excluded(b"z"),
    |key, value| {
        println!("{:?} -> {}", key, value);
        true // continue scanning
    },
    &guard,
);

// Prefix scan
tree.scan_prefix(b"wor", |key, value| {
    println!("{:?} -> {}", key, value);
    true
}, &guard);

Ergonomic APIs

For simpler use cases, auto-guard versions create guards internally:

use masstree::MassTree;

let tree: MassTree<u64> = MassTree::new();

// Auto-guard versions (simpler but slightly more overhead per call)
tree.insert(b"key1", 100);
tree.insert(b"key2", 200);

assert_eq!(tree.get(b"key1"), Some(100));
assert_eq!(tree.len(), 2);
assert!(!tree.is_empty());

tree.remove(b"key1").unwrap();

Range Iteration

use masstree::{MassTree, RangeBound};

let tree: MassTree<u64> = MassTree::new();
let guard = tree.guard();

// Populate
for i in 0..100u64 {
    tree.insert_with_guard(&i.to_be_bytes(), i, &guard);
}

// Iterator-based range scan
for entry in tree.range(RangeBound::Included(b""), RangeBound::Unbounded, &guard) {
    println!("{:?} -> {:?}", entry.key(), entry.value());
}

// Full iteration
for entry in tree.iter(&guard) {
    println!("{:?}", entry.key());
}

License

MIT. See LICENSE.

References

Project health

crates.io

Latest release

0.9.5 · Mar 17, 2026

Releases this year

59

Significant stargazers

Paolo Barbolini

185 followers · starred Jan 2026

Sebastian Thiel

1,431 followers · starred Jan 2026

bluss

631 followers · starred Jan 2026

Vlad Frolov

506 followers · starred Jan 2026