Production-ready embedded + networked store: PBKDF2 auth, a checksummed write-ahead journal, real transactions, a single-process select() event loop, EXT ops and ORDER_BY. Benches below are fair, apples-to-apples against SQLite 3.46.1 — matched transport and durability, real runs only, whoever wins.
tachyond --passwd <user>); failed-attempt rate limiting and lockout.off / interval / always); replay on startup; snapshot + journal truncation. Crash-recovery (kill -9 mid-write, restart, verify) is a passing C test.BEGIN / COMMIT / ROLLBACK with atomic per-frame apply via an in-memory undo log.select() event loop serving many clients; all sockets non-blocking; TCP_NODELAY.JOIN, SPLIT, REINDEX, COMPRESS — implemented and tested.ORDER_BY1 / ORDER_BY2, ascending or descending (bit7 of the field byte), filter-aware, with a bounded top-k path under LIMIT and OFFSET./dev/shm, so the data path has no socket and no framing. Volatile — for hot read paths, not the durable system of record.Click tachyondb_status.cgi for a live TCP probe of 127.0.0.1:7447 (override with Apache env TACHYON_HOST/TACHYON_PORT) and the in-process shm arena under /dev/shm.
This static page does not invent a “running” state. If the CGI reports no listener, start tachyond on the host first.
Every row is labelled with transport and durability, and compares like with like.
The networked rows use the identical client, wire framing, loopback and workload against both
tachyond and a minimal single-process select() TCP server that wraps SQLite and speaks the same
protocol — so only the engine differs. The in-process rows compare TacyonMem (engine linked in, arena in
/dev/shm) with SQLite :memory:, both volatile. Keyed KV workload (put/get), 64-bit Linux build.
All numbers are from real runs on one host; treat absolutes as representative, not a production SLA.
| Size | Op | TacyonMem (ops/s) | SQLite :memory: (ops/s) |
|---|---|---|---|
| 16 B | PUT | 4,427,654 | 605,082 |
| 16 B | GET | 5,025,646 | 1,412,442 |
| 64 B | PUT | 2,719,735 | 346,596 |
| 64 B | GET | 4,216,343 | 952,603 |
| 4 KiB | PUT | 243,682 | 139,967 |
| 4 KiB | GET | 948,093 | 589,542 |
| 64 KiB | PUT | 18,040 | 17,522 |
| 64 KiB | GET | 116,064 | 130,233 |
| 1 MiB | PUT | 1,021 | 761 |
| 1 MiB | GET | 6,824 | 8,890 |
Small records favour TacyonMem (~3–7×); 64 KiB–1 MiB are memcpy-bound and roughly even.
Tachyon fsync=always vs SQLite synchronous=FULL + WAL.
| Size | Op | Tachyon fsync=always (ops/s) | SQLite FULL+WAL (ops/s) |
|---|---|---|---|
| 16 B | PUT | 1,528 | 2,471 |
| 16 B | GET | 3,582 | 47,584 |
| 64 B | PUT | 1,401 | 1,189 |
| 64 B | GET | 4,240 | 44,188 |
| 4 KiB | PUT | 1,421 | 1,099 |
| 4 KiB | GET | 3,858 | 25,620 |
| 64 KiB | PUT | 740 | 711 |
| 64 KiB | GET | 5,312 | 13,768 |
| 1 MiB | PUT | 178 | 158 |
| 1 MiB | GET | 1,754 | 1,255 |
Durable writes are close and fsync-bound on both. Durable reads are SQLite's win here: its WAL lets readers proceed, while Tachyon's current single-thread journal/snapshot maintenance stalls the loop (p50 stays ~18–40 µs but the tail drags throughput). Noted as a known limitation.
Tachyon fsync=off vs SQLite :memory:.
| Size | Op | Tachyon fsync=off (ops/s) | SQLite :memory: (ops/s) |
|---|---|---|---|
| 16 B | PUT | 46,428 | 45,912 |
| 16 B | GET | 60,263 | 47,963 |
| 64 B | PUT | 59,534 | 45,877 |
| 64 B | GET | 61,135 | 44,210 |
| 4 KiB | PUT | 48,904 | 31,155 |
| 4 KiB | GET | 51,075 | 43,484 |
| 64 KiB | PUT | 10,547 | 9,189 |
| 64 KiB | GET | 24,515 | 20,433 |
| 1 MiB | PUT | 896 | 643 |
| 1 MiB | GET | 2,484 | 1,971 |
Non-durable over TCP: Tachyon leads at every size tested.
Tachyon fsync=off vs SQLite :memory:, 128 concurrent clients on the one select() loop.
| Size | Op | Tachyon fsync=off (ops/s) | SQLite :memory: (ops/s) |
|---|---|---|---|
| 16 B | PUT | 103,105 | 114,657 |
| 16 B | GET | 153,419 | 127,312 |
| 64 B | PUT | 157,266 | 108,917 |
| 64 B | GET | 172,593 | 142,858 |
| 4 KiB | PUT | 94,090 | 71,231 |
| 4 KiB | GET | 115,834 | 99,049 |
| 64 KiB | PUT | 16,973 | 15,642 |
| 64 KiB | GET | 34,508 | 22,052 |
| 1 MiB | PUT | 507 | 494 |
| 1 MiB | GET | 1,514 | 1,253 |
Tachyon fsync=always vs SQLite synchronous=FULL + WAL, 128 clients.
| Size | Op | Tachyon fsync=always (ops/s) | SQLite FULL+WAL (ops/s) |
|---|---|---|---|
| 16 B | PUT | 1,682 | 2,754 |
| 16 B | GET | 4,769 | 122,724 |
| 64 B | PUT | 1,739 | 1,424 |
| 64 B | GET | 4,087 | 119,256 |
| 4 KiB | PUT | 1,372 | 1,179 |
| 4 KiB | GET | 4,176 | 34,040 |
| 64 KiB | PUT | 927 | 698 |
| 64 KiB | GET | 5,252 | 14,235 |
| 1 MiB | PUT | 172 | 136 |
| 1 MiB | GET | 401 | 1,056 |
fsync=always are a known weak spot (see table 2/5 notes); non-durable and in-process reads are not affected.bench/run_fair.sh) — not estimates.podsticky:<user>/pod/<user>/sticky (Object, magic PSTK)# Build (64-bit Linux, no libc) and run the full C test suite cd /workspace/tachyon && bash build_linux.sh && bash tests/run_all.sh # Fair, labelled benchmarks (networked + in-process, matched durability) # needs the SQLite 3.46.1 amalgamation in SQLITE_DIR SQLITE_DIR=/path/to/sqlite-amalgamation-3460100 bash bench/run_fair.sh
Updated 2026-10-09 · Fair apples-to-apples benches vs SQLite 3.46.1 (matched transport + durability) · No invented numbers