Snapshot of spacejam/sled: 9.1k★, Rust, Data. the champagne of beta embedded databases
Snapshot summary built from the project's own GitHub metadata — there's no written TopGit review yet. The page will update automatically when a full review is published.
WHY NO REVIEW YET
TopGit writes full reviews for the most-starred, most-requested repositories. This page is a snapshot until then — see the READ ME tab for the original README in full.
let tree = sled::open("/tmp/welcome-to-sled")?;
// insert and get, similar to std's BTreeMap
let old_value = tree.insert("key", "value")?;
assert_eq!(
tree.get(&"key")?,
Some(sled::IVec::from("value")),
);
// range queries
for kv_result in tree.range("key_1".."key_9") {}
// deletion
let old_value = tree.remove(&"key")?;
// atomic compare and swap
tree.compare_and_swap(
"key",
Some("current_value"),
Some("new_value"),
)?;
// block until all operations are stable on disk
// (flush_async also available to get a Future)
tree.flush()?;
$${\color{red}This \space README \space is \space out \space of \space sync \space with \space the \space main \space branch \space which \space contains \space a \space large \space in-progress \space rewrite }$$
If you would like to work with structured data without paying expensive deserialization costs, check out the structured example!
features
API similar to a threadsafe BTreeMap<[u8], [u8]>
serializable (ACID) transactions
for atomically reading and writing to multiple keys in multiple keyspaces.
fully atomic single-key operations, including compare and swap
zero-copy reads
write batches
subscribe to changes on key
prefixes
multiple keyspaces
merge operators
forward and reverse iterators over ranges of items
a crash-safe monotonic ID generator
capable of generating 75-125 million unique ID's per second
zstd compression (use the
compression build feature, disabled by default)
cpu-scalable lock-free implementation
flash-optimized log-structured storage
uses modern b-tree techniques such as prefix encoding and suffix
truncation for reducing the storage costs of long keys with shared
prefixes. If keys are the same length and sequential then the
system can avoid storing 99%+ of the key data in most cases,
essentially acting like a learned index
expectations, gotchas, advice
Maybe one of the first things that seems weird is the IVec type.
This is an inlinable Arced slice that makes some things more efficient.
Durability: sled automatically fsyncs every 500ms by default,
which can be configured with the flush_every_ms configurable, or you may
call flush / flush_async manually after operations.
Transactions are optimistic - do not interact with external state
or perform IO from within a transaction closure unless it is
idempotent.
Internal tree node optimizations: sled performs prefix encoding
on long keys with similar prefixes that are grouped together in a range,
as well as suffix truncation to further reduce the indexing costs of
long keys. Nodes will skip potentially expensive length and offset pointers
if keys or values are all the same length (tracked separately, don't worry
about making keys the same length as values), so it may improve space usage
slightly if you use fixed-length keys or values. This also makes it easier
to use structured access as well.
sled does not support multiple open instances for the time being. Please
keep sled open for the duration of your process's lifespan. It's totally
safe and often quite convenient to use a global lazy_static sled instance,
modulo the normal global variable trade-offs. Every operation is threadsafe,
and most are implemented under the hood with lock-free algorithms that avoid
blocking in hot paths.
performance
LSM tree-like write performance
with traditional B+ tree-like read performance
over a billion operations in under a minute at 95% read 5% writes on 16 cores on a small dataset
measure your own workloads rather than relying on some marketing for contrived workloads
a note on lexicographic ordering and endianness
If you want to store numerical keys in a way that will play nicely with sled's iterators and ordered operations, please remember to store your numerical items in big-endian form. Little endian (the default of many things) will often appear to be doing the right thing until you start working with more than 256 items (more than 1 byte), causing lexicographic ordering of the serialized bytes to diverge from the lexicographic ordering of their deserialized numerical form.
Rust integral types have built-in to_be_bytes and from_be_bytes methods.
bincode can be configured to store integral types in big-endian form.
interaction with async
If your dataset resides entirely in cache (achievable at startup by setting the cache
to a large enough value and performing a full iteration) then all reads and writes are
non-blocking and async-friendly, without needing to use Futures or an async runtime.
To asynchronously suspend your async task on the durability of writes, we support the
flush_async method,
which returns a Future that your async tasks can await the completion of if they require
high durability guarantees and you are willing to pay the latency costs of fsync.
Note that sled automatically tries to sync all data to disk several times per second
in the background without blocking user threads.
We support async subscription to events that happen on key prefixes, because the
Subscriber struct implements Future<Output=Option<Event>>:
let sled = sled::open("my_db").unwrap();
let mut sub = sled.watch_prefix("");
sled.insert(b"a", b"a").unwrap();
extreme::run(async move {
while let Some(event) = (&mut sub).await {
println!("got event {:?}", event);
}
});
minimum supported Rust version (MSRV)
We support Rust 1.62 and up.
architecture
lock-free tree on a lock-free pagecache on a lock-free log. the pagecache scatters
partial page fragments across the log, rather than rewriting entire pages at a time
as B+ trees for spinning disks historically have. on page reads, we concurrently
scatter-gather reads across the log to materialize the page from its fragments.
check out the architectural outlook
for a more detailed overview of where we're at and where we see things going!
philosophy
don't make the user think. the interface should be obvious.
don't surprise users with performance traps.
don't wake up operators. bring reliability techniques from academia into real-world practice.
don't use so much electricity. our data structures should play to modern hardware's strengths.
known issues, warnings
if reliability is your primary constraint, use SQLite. sled is beta.
if storage price performance is your primary constraint, use RocksDB. sled uses too much space sometimes.
if you have a multi-process workload that rarely writes, use LMDB. sled is architected for use with long-running, highly-concurrent workloads such as stateful services or higher-level databases.
quite young, should be considered unstable for the time being.
the on-disk format is going to change in ways that require manual migrations before the 1.0.0 release!
priorities
A full rewrite of sled's storage subsystem is happening on a modular basis as part of the komora project, in particular the marble storage engine. This will dramatically lower both the disk space usage (space amplification) and garbage collection overhead (write amplification) of sled.
The memory layout of tree nodes is being completely rewritten to reduce fragmentation and eliminate serialization costs.
The merge operator feature will change into a trigger feature that resembles traditional database triggers, allowing state to be modified as part of the same atomic writebatch that triggered it for retaining serializability with reactive semantics.
fund feature development
Like what we're doing? Help us out via GitHub Sponsors!
No homepage URL was recorded for spacejam/sled in TopGit's last sync. The README tab above frequently contains screenshots and demo links, or check the repository description on GitHub.
How active is development on spacejam/sled?
The most recent commit recorded on spacejam/sled was 4 months ago, based on the GitHub push timestamp. The repository has 427 forks — one of the better signals of community interest.
Is spacejam/sled open source?
Yes — spacejam/sled ships under the Apache-2.0 license, which makes its source code freely readable (and, depending on license terms, forkable and reusable). Source: github.com/spacejam/sled.
What license does spacejam/sled use?
spacejam/sled is released under the Apache-2.0 license. Always verify the LICENSE file directly on GitHub for the authoritative terms — license strings can be edited out of sync with a project's actual stance.
This TopGit page is a snapshot — the READ ME tab shows the project's own README content (links stripped, images preserved). The GitHub repository at github.com/spacejam/sled is the definitive source.
Read full README in the tab above.
Want a second opinion on sled?
Ask an AI that can read this page — one click and you get its take on sled.