An ultra-fast, memory-optimized, Redis-compatible in-memory key-value database engineered from scratch in modern C++20.
RunDB Native is the high-performance native C++20 evolution of the RunDB distributed architecture. Designed for extreme speed, minimal memory overhead, and wire-level compatibility with standard Redis clients (redis-cli, Jedis, redis-py, etc.), RunDB Native implements proprietary algorithms and cache-conscious internal data structures rather than copying legacy architectures.
This project was built through original coding and deep systems engineering understanding, developed with interactive assistance and pair-programming from Gemini via Antigravity.
- β‘ Blistering Performance: Achieves 150,000+ QPS on commodity hardware with sub-0.2ms p50 latency.
-
π§ Custom
run_allocEngine: Real-time atomic memory allocation tracking with zero lock contention, bundled directly with productionjemalloc(libjemalloc.so) for zero-fragmentation operation. -
π¦ Bundled Zero-Config jemalloc: Embedded into CMake with automatic RPATH resolutionβno manual
apt-get install libjemalloc-devor environment tweaking required. -
𧬠Proprietary
SDS: Small String Optimization (SSO) storing strings$\le 22$ bytes directly inside the 32-byte struct with zero heap allocation, paired with an 8-byte cache-line aligned dynamic header for longer keys. -
π’ Adaptive
IntSet: Compact contiguous sorted integer array automatically packing 16-bit, 32-bit, or 64-bit integers with branchless binary search, migrating encodings backwards with amortized reallocations and auto-promoting to hash sets on demand. -
π Chunked
QuickList: Cache-conscious unrolled doubly-linked list packing 32-element contiguous chunks per node, providing$O(1)$ push/pop at both ends with hardware cache prefetching. - β° 24-Bit Circular LRU Clock & Eviction Pool: Approximates global LRU through a 16-candidate bounded eviction pool that preserves the longest-idle keys across rounds with zero per-key pointer overhead.
-
π― Probabilistic Active Expiration: Evaluates 20 random keys with TTL per database partition, automatically repeating if
$> 25%$ are expired, with a strict 1ms time-budget cap to maintain sub-millisecond p99 latencies. -
πΎ Append-Only File (AOF) Persistence: Enabled by default (
--aof-enabled yes,--no-aofto disable) with configurable fsync (always,everysec,no), transaction safety, and startup replay. -
πΈ Compressed Point-in-Time Snapshots (RDB): High-compression Zlib DEFLATE dumps with CRC32 integrity checks. Single-threaded memory extraction with asynchronous background compression (
BGSAVE), synchronous saving (SAVE), and automated interval triggers. -
π οΈ Comprehensive Admin & Introspection Suite: Complete implementations of
COMMAND(DOCS,INFO,COUNT),CONFIG(GET,SET,RESETSTAT),CLIENT(LIST,SETNAME,GETNAME,KILL,ID,INFO,PAUSE,UNPAUSE), andLATENCY(LATEST,HISTORY,RESET,DOCTOR,GRAPH). -
π³ Zero-Dependency Container: Self-contained multi-stage Docker build packaging pre-bundled
jemalloc,zlib, andquillvia automatedvcpkgbootstrappingβusers never need to manually download or configure external dependencies. -
π¨ Interactive Terminal Printer: Full ANSI color palette, block-font ASCII art banner, boxed network status, dynamic metric scaling (B
$\to$ KB$\to$ MB$\to$ GB), and an end-of-run "memory calories burnt" summary.
runDB_native/
βββ include/
β βββ core/
β β βββ internals/
β β β βββ run_alloc.hpp # Proprietary memory allocation & tracking engine
β β β βββ sds.hpp # Proprietary Small Dynamic String (SSO <= 22B)
β β β βββ intset.hpp # Adaptive contiguous integer set (16/32/64-bit)
β β β βββ quicklist.hpp # Chunked unrolled deque (32 items per chunk)
β β β βββ hashers.hpp # 64-bit MurmurHash3 & FNV-1a hash functions
β β βββ client_context.hpp # Active DB partition & transaction buffers
β β βββ object.hpp # Bit-packed 32-bit object header (type, enc, LRU)
β β βββ database.hpp # Partition keyspace with passive TTL checking
β β βββ evict_pool.hpp # 16-candidate bounded LRU candidate pool
β β βββ eviction.hpp # Memory threshold checks & eviction dispatch
β β βββ expiration.hpp # Adaptive active key expiration daemon
β β βββ stats.hpp # Telemetry (hits, misses, commands, memory)
β β βββ aof.hpp # AOF persistence logger and startup replayer
β β βββ snapshot.hpp # Compressed RDB snapshot engine (Zlib + CRC32)
β β βββ latency.hpp # Latency monitoring engine (histograms & spike doctor)
β β βββ evaluator.hpp # Command dispatch & evaluation engine
β β βββ store.hpp # Multi-DB Store coordinator (SELECT 0..15)
β βββ server/
β β βββ client.hpp # Non-blocking socket client with sliding buffer
β β βββ shutdown.hpp # Atomic engine states & POSIX signal handling
β β βββ server.hpp # Single-threaded Linux epoll event loop
β βββ protocol/
β β βββ cmd.hpp # Command metadata
β β βββ resp_parser.hpp # Zero-copy RESP processor & parser
β β βββ resp.hpp # RESP serializer and encoder helpers
β βββ util/
β βββ printer.hpp # Terminal ANSI printer & memory calories
βββ src/ # Corresponding C++20 implementations
βββ config/
β βββ rundb.conf # Server configuration file
βββ lib/
β βββ libjemalloc.so # Bundled production jemalloc shared library
βββ tests/ # Native C++20 test and benchmarking suite
β βββ test_framework.hpp # Lightweight header-only test runner & assertions
β βββ benchmark_main.cpp # Native C++ benchmarking engine & network suite
β βββ test_*.cpp # Unit & integration tests for all subsystems (76 tests)
βββ Dockerfile # Multi-stage hermetic production container build
βββ docker-compose.yml # Docker compose deployment with volume persistence
βββ CMakeLists.txt # Modern CMake build system with presets
Standard glibc malloc exhibits memory fragmentation and lacks real-time insight into byte footprints. run_alloc implements:
- Prefix Header (16-byte aligned): Every allocation is prefixed with a 16-byte metadata header
[size_t size][padding], ensuring maximum 16-byte alignment compatibility for AVX/SSE vector instructions. - Lock-Free Telemetry: Tracks active bytes and block allocations via atomic counters with zero lock contention.
- Embedded jemalloc: Routes all allocations through bundled
jemallocwith transparent RPATH resolution.
-
SSO (
$\le 22$ bytes): Standard strings incur 32 bytes of struct overhead plus separate heap allocations for keys like"user:1".SDSstores strings up to 22 bytes in an inline 32-byte struct (24-byte union + 1-byte flag + 7-byte padding) with zero heap allocation. -
Dynamic Header (
$> 22$ bytes): Prefixed with an 8-byte cache-aligned header[uint32_t len, uint32_t alloc]directly adjacent to character data, maximizing L1 cache line prefetching. -
Binary Safe: Length is stored explicitly, permitting null bytes
\0in keys and values.
-
Multi-Width Encodings: Evaluates values to store them in the smallest possible integer width:
-
ENC_INT16(2 bytes/val) for range$[-32768, 32767]$ -
ENC_INT32(4 bytes/val) for range$[-2147483648, 2147483647]$ -
ENC_INT64(8 bytes/val) for 64-bit numbers
-
- Dynamic Upgrading: When an inserted value exceeds current limits, dynamically reallocates for the wider width and shifts elements backwards to preserve index ordering before releasing the old buffer. Auto-promotes to a hash set if string values are inserted or size exceeds 512.
-
Cache-Conscious Chunking: Pure linked lists cause cache thrashing due to pointer chasing.
QuickListgroups elements into contiguous arrays of 32 elements perNode. -
$O(1)$ Boundaries: LPUSH, RPUSH, LPOP, and RPOP operate at chunk boundaries in$O(1)$ without vector shifting. -
Chunk Jumping: Random indexing (
LINDEX) skips full chunks of 32 ($k = \text{index} / 32$ ), minimizing pointer traversals.
- Why a Pool?: Single-round random sampling is volatile. Retaining the 16 longest-idle keys across sampling rounds progressively converges to true global LRU with zero pointer overhead per key (saving 16β24 bytes per entry vs Redis's bidirectional pointers).
-
Active Expiration: Samples 20 random keys with TTL per partition every 50ms. If
$> 25%$ are expired, it resamples immediately, capped to 1ms to keep event loop latency sub-millisecond.
-
Snapshot Extraction vs Redis
fork(): Redis uses OSfork()for copy-on-write snapshots, which requires zero upfront copy time but duplicates page tables and risks memory overcommit spikes on Linux. RunDB Native uses a portable single-threaded memory extraction phase followed by background zlib worker writesβeliminatingfork()at the trade-off of an$O(N)$ extraction step and temporary memory replication during saves. -
Object Ownership & Lifetimes:
RunDBObjectusesstd::make_sharedto fuse object data (72-byte struct) and control blocks into a single contiguous allocation, ensuring safe aliasing for in-flight operations and queries. -
Transactions: Supports atomic blocks via
MULTI,EXEC, andDISCARD. (Optimistic CAS viaWATCHis planned for a future release). -
Memory Tracking:
run_alloctracks direct dynamic buffers (heap SDS strings, IntSet arrays, QuickList chunks), while standard allocator nodes and keys are accounted for in process RSS metrics.
RunDB Native is engineered for extreme throughput, sub-millisecond tail latencies, and minimal resident memory overhead. Under empirical testing via redis-benchmark against Python RunDB and Redis 7.0.15 (C):
- π 68.2x Faster than Python RunDB (~156,000 req/s vs ~2,288 req/s).
- β‘ Performance Parity with Redis 7 (C): Matches Redis throughput neck-and-neck with identical 0.159 ms median latency.
-
πΎ 50% Less Memory than Redis: Operates at just 7.12 MB peak RSS (vs 14.23 MB for Redis and 313 MB for Python RunDB) thanks to zero-heap
SDSstack strings ($\le 22$ bytes) and chunkedQuickListstorage.
π For the complete command-by-command comparison tables, percentile latency breakdowns (p50, p90, p95, p99), memory profiling curves, and reproduction steps, see metrics.md.
Install directly on Linux using the automated one-liner:
curl -fsSL https://raw.githubusercontent.com/DarshanAguru/runDB_native/main/install.sh | bashOr download the pre-compiled standalone tarball from GitHub Releases:
tar -xzf rundb-1.0.1-linux-x86_64.tar.gz
cd rundb-1.0.1-linux-x86_64
sudo ./install.sh(See process.md for full binary packaging and release instructions)
- Linux OS (Ubuntu 22.04+, Debian 12+, Arch, Fedora)
- GCC 13+ or Clang 17+ (with C++20 support)
- CMake 3.25+ and Ninja
# Clone the repository
git clone https://github.com/DarshanAguru/runDB_native.git
cd runDB_native
# Configure and compile in Release mode (-O3, LTO)
cmake --preset release
cmake --build --preset build-releaseThe resulting binary ./build/release/rundb will be created with libjemalloc.so copied alongside it.
./build/release/rundb --port 7379redis-cli -p 7379 PING
# Output: PONG
redis-cli -p 7379 SET user:name "Darshan"
redis-cli -p 7379 GET user:name
# Output: "Darshan"
redis-cli -p 7379 INFO memoryRunDB Native includes a production multi-stage Dockerfile:
# Build and start in background
docker compose up -d
# Check logs
docker compose logs -f
# Stop container
docker compose downdocker build -t rundb-native:latest .
docker run -d -p 7379:7379 --name rundb-native -v rundb_data:/data rundb-native:latest| Command | Category | Description |
|---|---|---|
PING [msg] |
Admin | Ping the server; returns PONG or custom message |
ECHO msg |
Admin | Echo back the provided message |
SELECT index |
Admin | Switch active database partition (0..15) |
INFO [section] |
Admin | Server, memory, persistence, and client analytics |
DBSIZE |
Admin | Count total keys in active partition |
TIME |
Admin | Current Unix server timestamp |
COMMAND [COUNT|DOCS|INFO] |
Admin | Introspection catalog for Redis clients and drivers |
CONFIG GET param |
Admin | Query runtime configuration parameter |
CONFIG SET param val |
Admin | Dynamically update configuration parameter |
CONFIG RESETSTAT |
Admin | Reset operational statistics and telemetry counters |
CLIENT LIST |
Admin | Enumerate connected clients with network metrics |
CLIENT SETNAME name |
Admin | Assign human-readable nickname to current client |
CLIENT GETNAME |
Admin | Query nickname assigned to current client |
CLIENT ID |
Admin | Retrieve unique 64-bit client connection ID |
CLIENT INFO |
Admin | Detailed connection state of active client |
CLIENT KILL [ip:port|ID id] |
Admin | Terminate connected client socket |
CLIENT PAUSE timeout_ms |
Admin | Temporarily suspend command processing |
CLIENT UNPAUSE |
Admin | Resume suspended command processing |
LATENCY LATEST |
Latency | Report highest latency spike for tracked events |
LATENCY HISTORY event |
Latency | Return timestamped spike time-series for event |
LATENCY RESET [event] |
Latency | Reset recorded latency spike records |
LATENCY DOCTOR |
Latency | Automated diagnostic human-readable latency report |
LATENCY GRAPH event |
Latency | Render ASCII sparkline graph of event latencies |
SAVE |
Persistence | Synchronously write compressed snapshot (RDB) to disk |
BGSAVE |
Persistence | Non-blocking asynchronous snapshot dump in background thread |
LASTSAVE |
Persistence | Return UNIX timestamp of last successful snapshot |
BGREWRITEAOF |
Persistence | Background compaction and atomic rewrite of AOF log |
SET key val [EX sec] [PX ms] [NX|XX] |
Strings | Set key with optional TTL and conditions |
GET key |
Strings | Get value (with passive expiration) |
MSET k1 v1 [k2 v2 ...] |
Strings | Atomically set multiple key-value pairs |
MGET k1 [k2 ...] |
Strings | Retrieve multiple values |
INCR key / DECR key
|
Strings | Increment or decrement 64-bit integer values |
INCRBY key delta / DECRBY key delta
|
Strings | Add or subtract delta from integer values |
APPEND key val |
Strings | Append string to existing value |
STRLEN key |
Strings | Length of stored string |
LPUSH key val [val ...] |
Lists | Prepend values to list using chunked QuickList |
RPUSH key val [val ...] |
Lists | Append values to list |
LPOP key / RPOP key
|
Lists | Remove and return elements from boundaries |
LLEN key |
Lists | Length of list |
LINDEX key index |
Lists | Element at index (supports negative offsets) |
LRANGE key start stop |
Lists | Slice of list elements |
SADD key member [member ...] |
Sets | Add members (adaptive IntSet |
SREM key member [member ...] |
Sets | Remove members |
SISMEMBER key member |
Sets | Test set membership |
SCARD key |
Sets | Cardinality of set |
SMEMBERS key |
Sets | Return all members of set |
SRANDMEMBER key |
Sets | Return random member from set |
DEL key [key ...] |
Generic | Delete keys |
EXISTS key [key ...] |
Generic | Check key existence |
TYPE key |
Generic | Return object type (string, list, set) |
KEYS pattern |
Generic | Find all keys matching glob pattern (e.g. *, user:*) |
EXPIRE key sec / PEXPIRE key ms
|
Expiry | Set expiration timeout |
EXPIREAT key epoch_s / PEXPIREAT key epoch_ms
|
Expiry | Set expiration at exact UNIX epoch timestamp |
TTL key / PTTL key
|
Expiry | Check remaining time-to-live |
PERSIST key |
Expiry | Remove expiration timeout |
FLUSHDB |
Generic | Flush active database partition |
FLUSHALL |
Generic | Flush all 16 database partitions |
MULTI |
Transactions | Begin transaction block |
EXEC |
Transactions | Execute all queued commands atomically |
DISCARD |
Transactions | Cancel transaction block |
RunDB Native implements strict 4-tier configuration precedence:
- CLI Flags (e.g.
--port 7400,--memory-limit 104857600) β Highest Priority - Environment Variables (e.g.
RUNDB_PORT=7400,RUNDB_LOG_LEVEL=DEBUG) - Configuration File (
config/rundb.confor--config <path>) - Built-in Production Defaults (Port 7379, 0.0.0.0, 100MB limit, allkeys-lru) β Lowest Priority
Note
RunDB cleanly ingests environment variables at startup without mutating or polluting the host environment (zero setenv side-effects).
Example rundb.conf:
# Network Binding
host 0.0.0.0
port 7379
log_level INFO
# Memory & Eviction (0 = unlimited, or e.g. 100MB)
memory_limit 104857600
eviction_strategy allkeys-lru
# Append-Only File (AOF) Durability
aof_enabled yes
aof_file run_master.aof
aof_fsync everysec
# Point-in-Time Compressed Snapshot (RDB) Persistence
# Configurable intervals: 30S (30s), 1M (1 min), 2H (2 hours), 1D (1 day), 0 to disable
snapshot_interval 1M
snapshot_file dump.rdbStart the server pointing to a configuration file:
./build/release/rundb --config config/rundb.confOr override individual settings on the command line:
# Enable automated 1-minute compressed snapshots with custom output path
./build/release/rundb --snapshot 1M --snapshot-file /data/dump.rdb
# Run pure in-memory without AOF durability
./build/release/rundb --no-aof
# Run with snapshot every 30 seconds and AOF everysec fsync
./build/release/rundb --snapshot 30S --aof-fsync everysecRunDB Native features a comprehensive native C++20 testing framework and high-performance benchmarking suite.
Run the full test suite directly or through CTest:
# Direct test binary (runs all 76 unit and integration tests)
./build/rundb_tests
# Filter tests by subsystem or test name
./build/rundb_tests --filter Snapshot
./build/rundb_tests --filter Evaluator
# Run via CMake CTest
ctest --test-dir build --output-on-failureRun high-resolution benchmarks measuring RPS, latency percentiles (min, avg, p50, p90, p95, p99, max), and memory RSS deltas without Python interpreter overhead:
# Run direct in-memory engine microbenchmarks (2.2M - 3.8M ops/sec)
./build/release/rundb_benchmark --engine -n 100000
# Run high-concurrency TCP network benchmark (170k - 182k req/sec)
./build/release/rundb_benchmark --network -c 20 -n 50000
# Run all benchmarks
./build/release/rundb_benchmark| Command | Throughput (RPS) | Avg Latency | p50 Latency | p99 Latency |
|---|---|---|---|---|
PING |
3,527,215 req/s | < 0.001 ms | < 0.001 ms | < 0.001 ms |
SET |
2,257,463 req/s | < 0.001 ms | < 0.001 ms | 0.002 ms |
GET |
2,788,548 req/s | < 0.001 ms | < 0.001 ms | 0.001 ms |
INCR |
3,881,010 req/s | < 0.001 ms | < 0.001 ms | < 0.001 ms |
LPUSH |
3,500,385 req/s | < 0.001 ms | < 0.001 ms | 0.001 ms |
LPOP |
3,388,018 req/s | < 0.001 ms | < 0.001 ms | 0.001 ms |
SADD |
2,473,666 req/s | < 0.001 ms | < 0.001 ms | 0.001 ms |
SISMEMBER |
2,317,438 req/s | < 0.001 ms | < 0.001 ms | 0.001 ms |
| Command | Throughput (RPS) | Avg Latency | p50 Latency | p99 Latency |
|---|---|---|---|---|
GET |
182,062 req/s | 0.109 ms | 0.110 ms | 0.154 ms |
LPUSH |
178,387 req/s | 0.112 ms | 0.111 ms | 0.164 ms |
SET |
175,581 req/s | 0.113 ms | 0.113 ms | 0.152 ms |
SADD |
175,242 req/s | 0.114 ms | 0.113 ms | 0.206 ms |
PING |
173,705 req/s | 0.115 ms | 0.113 ms | 0.160 ms |
INCR |
170,314 req/s | 0.117 ms | 0.117 ms | 0.156 ms |
LPOP |
169,377 req/s | 0.118 ms | 0.115 ms | 0.156 ms |
Contributions are welcome! Please review CONTRIBUTING.md and CODE_OF_CONDUCT.md before opening a pull request.
Protected under the BSD 3-Clause License.
This project is engineered through personal coding, low-level systems design, and deep architectural understanding of databases and memory systems, developed with interactive pair-programming assistance from Google Gemini through the Antigravity agentic development platform.
Author: Darshan Aguru
- π§ Email: agurudf@gmail.com
- π Website: thisdarshiii.in
- π GitHub: @DarshanAguru
