Repository navigation
perfcached 0.5.0
A multithreaded, self-clustering cache for Linux, with its own encrypted protocols and a Redis-compatible door. New here? Start with the README.
A rolling restart. 0.5.0 joins a 0.4.5 or 0.4.6 fleet one node at a time: restart the members first and the master last, and read the fleet between nodes. The storage formats and the wire epoch are unchanged, and libperfd 0.3.0 clients keep working. Use SET ... IFEQ/IFNE and DELEX once every node runs 0.5.0; the Symfony lock scripts are refused until it does.
Alpine Linux
- Alpine (musl) is a supported runtime. On Alpine 3.24 (musl 1.2.6, its own malloc) the daemon serves 0.78-0.95 of the glibc build's rate where the server is the bottleneck, and is ahead of
redis:8-alpineon every measured row -INCR,SET/GETof 256 B and 1 KB values, a 7:1 mix,JSON.SETandJSON.GET, at 4 and 12 workers - by 1.5x to 14.9x. bench/Containerfile.alpinebuilds a 55 MB image. CI builds both editions on Alpine and runs the standalone suites there.- The allocator is a build choice:
make menuconfig, orPC_ALLOC = libc | mimalloc | jemalloc. libc stays the default everywhere (the packages below use it);perfcached -Vnames a non-default allocator, and/statscarriesprocess.allocator.
No heap per request
- The JSON path allocates nothing after warm-up:
JSON.SET,GET,NUMINCRBY,ARRAPPEND,DELand the hash forwards made three to four allocations each. On musl one of them was a 256 KB buffer mapped and unmapped on every command, which heldJSON.SETat 25-30k a second; it now runs at 1.3M at 4 workers. - libperfd 0.4.0 allocates nothing per call on a warm handle. The API and the wire are 0.3.0's, so a rebuild is all an existing client needs;
perfd_getandperfd_jgetstill return a malloc'd result, as documented.
Compare-and-set, and Symfony Lock
SET ... IFEQ <value> | IFNE <value>andDELEX <key> [IFEQ|IFNE <value>], in Redis 8.4's spelling and with its replies.IFDEQ/IFDNEare refused by name: perfcached keeps no value digest. Native methodssetifeq,setifne,delifeq,delifne, and in libperfdperfd_set_ifandperfd_del_if.EVAL,EVALSHAandSCRIPT LOAD | EXISTS | FLUSHfor the lock scripts of Symfony's Lock component (5.4 to 7.4): they are recognised by SHA1 and run natively, as one atomic step on the key's holder. Any other script is refused.
Proxy collections
- A request may ask where its key lives (an opt-in flag), and the reply names the node that holds it. libperfd's
route_hintsoption remembers that per key and sends the next request for the key straight there; a stale entry costs one extra hop, never a wrong answer. Off by default. - A
GET,DELorEXPIREthat a stale locator steered to a node no longer holding the key now asks the fleet once. Before, theGETanswered nil, theDELanswered 0 and left the key alive on its new holder, and theEXPIREleft it without a TTL.
Faster
- A
SETthat rewrites an unchanged value compares the two a word at a time and prefetches the stored one (on musl,SETof 256 B +7%, of 1 KB +15%). - The reply writer's small appends and its numbers no longer go through
memcpy: on musl aGEThit made sevenmemcpycalls, now three.
Known
- No sorted sets, lists or streams yet. Keys hold strings, counters, JSON documents or hashes (a hash is one value, under 58,000 bytes).
discovery = unicast(clouds, Kubernetes) is tested in lab network namespaces that drop IP fragments and block UDP, not yet in a real cloud deployment.spreadmode has not yet carried production traffic.- In
eagermode a delete made on one side of a network partition can be undone when the partition heals.
Packages
Debian 12 and 13, Ubuntu 20.04 and 24.04, amd64, in both editions:
perfcached- the clustered daemon, every cluster mode.perfcached-standalone- the single-node edition, built from the same tree without the cluster code; a[cluster]section in its config is refused rather than ignored.
The two install the same files under the same names and replace each other, so moving between editions is one apt install. Each package was built in a clean container and install-checked in a second one: the version and revision, the edition perfcached -V reports, the shipped config passing perfcached -C, the systemd unit, and for the standalone package that a [cluster] section is refused and that installing perfcached over it swaps the edition.