Skip to content

Releases: LASTRADA-Software/fastcached

fastcached v0.3.0

Choose a tag to compare

@github-actions github-actions released this 22 Sep 13:57
6eaea2c

What's Changed

⚠️ Breaking changes

Features

  • feat(cli): fastcache-cli, an operator's client for the cache by @christianparpart in #1198
  • feat(cli): the memcached-text verbs, and the wire column that makes room for them by @christianparpart in #1232
  • Stack six batches onto one branch: 17 tickets, one CI cycle by @christianparpart in #1249
  • Name the toolchain on a dispatched compile, and measure the /fleet render instead of caching it by @christianparpart in #1263
  • feat(node): a reset peer and one that said goodbye are counted apart by @christianparpart in #1262
  • The upstream row is not replicated, the stream decoder reserves within a cap, and a setting must say what reads it by @christianparpart in #1273
  • feat(cli): reach a pure-0xFC node, and let it say what it is by @christianparpart in #1275
  • The cluster verbs in fastcache-cli, and one predicate for following a NotLeader by @christianparpart in #1312
  • A worker that is never chosen says so by @christianparpart in #1316
  • NodeStatus says what a node is DOING, so a default node is observable by @christianparpart in #1315
  • feat(node): the worker's cache tiers take the daemon's six compression settings by @christianparpart in #1324
  • The fleet tables answer a terminal, not only a browser by @christianparpart in #1326
  • cluster admit echoes the endpoint it recorded, so a typo is visible by @christianparpart in #1336
  • Group COMMANDS by wire, derive the fleet-column coverage, and ship the KPI strip computed by @christianparpart in #1341
  • A runtime enrollment window, and the --raft-join trap it makes sharper by @christianparpart in #1333
  • The live-stats dashboard is a fold over one event stream (#134 stage 3) by @christianparpart in #1386
  • fastcache-cli live-stats: a live terminal view of a cache, a compile node or the fleet by @christianparpart in #1392
  • A Counter becomes an index in one place, and a scan says so by @christianparpart in #1409
  • CacheDrop: an operator removes one key from the cache tier that answers by @christianparpart in #1411
  • compile-node: a worker can be cordoned, drains, and says when stopping it abandons nothing by @christianparpart in #1412
  • compile-node: --scheduler is a list, and a dead first entry falls back in the same round by @christianparpart in #1419
  • A unit compiled against a different Counter enum fails to link by @christianparpart in #1414
  • compile-node: NodeMetrics answers the reading /metrics renders, so a node's cache tier shows without an admin surface by @christianparpart in #1435
  • cli: fleet reads the leader's tables over 0xFC, follows a follower to them, and prints the history as a table by @christianparpart in #1436
  • compile-node: print the consensus address peers dial, apart from the one the node binds by @christianparpart in #1425
  • compile-node: --slots=0 runs no worker, and the worker is a tier by @christianparpart in #1459
  • live-stats: a consensus node's panel says where its peers dial it by @christianparpart in #1463
  • One duration grammar for every length of time the tools read and print by @christianparpart in #1458
  • build: every shipping configure runs the instruction-set check, in its job and before its build by @christianparpart in #1493
  • fleet: an admission names every route that admitted it, through one door by @christianparpart in #1498
  • fleet: a node says how many client tombstones it has APPLIED, and absent is not zero by @christianparpart in #1502
  • node: a machine that holds the cluster key is admitted on 0xFC by proving it, not by its address by @christianparpart in #1513
  • node: a live subscription is gated on the cluster-key proof at its door and on every tick, not on an address by @christianparpart in #1516
  • node: a machine with no worker announces itself, so the fleet can see it by @christianparpart in #1517
  • node: an operator can ask WHICH routes admit or refuse a host, not only whether by @christianparpart in #1522
  • node: the fleet surfaces report WHICH clients the cluster has forgotten, not how many by @christianparpart in #1523
  • board 3: thirteen changes integrated on one branch -- learners, identity keys, conditions, arm64 and the CI guards by @christianparpart in #1551
  • board 3, final: per-node identity replaces the cluster key (#178 PRs 3-6), a follower refuses what it cannot read, and a refusal survives its close by @christianparpart in #1558

Bug fixes

Read more

fastcached v0.2.0

Choose a tag to compare

@github-actions github-actions released this 09 Sep 12:12
8693aeb

What's Changed

⚠️ Breaking changes

Features

Bug fixes

Read more

fastcached v0.1.1

Choose a tag to compare

@Yaraslaut Yaraslaut released this 24 Aug 15:19
a454459

What's Changed

  • Use fastcache-cc for our own build when a daemon is running by @christianparpart in #46
  • Color the fastcache-cc stats report and add an HTML dashboard by @Yaraslaut in #50
  • Fix stale direct-mode cache hits when a source file's own body changes by @Yaraslaut in #52
  • Add opt-in auto-install of fastcache-cc when no compiler cache is present by @christianparpart in #54
  • Streamline compile-cache naming: CMake-style dirs and prefetch groups by @christianparpart in #55
  • Fix a cache hit replaying a depfile that names a moved header's old path by @christianparpart in #61
  • Key a compile on the headers it resolved, and make MSVC keys carry the source by @christianparpart in #62
  • Fix the compile-cache key having 32 bits of strength, not 128 by @christianparpart in #67
  • fastcache-cc: relativize the fused MSVC object-output flag, off one path-flag table by @christianparpart in #71
  • Classify a path's anchor in three states so a Windows drive-relative path is not called absolute by @christianparpart in #75
  • Fix fastcache-cc dying of SIGPIPE when an object is too large to cache by @christianparpart in #73
  • fastcache-cc: classify a dependency path's anchor before asking if it is toolchain by @christianparpart in #72
  • Fix lost cache sharing with relative include paths by @christianparpart in #74
  • Reconcile root spellings so a moved header can re-key on any host by @christianparpart in #76
  • Require a credential on the compile-cache protocol by @christianparpart in #77
  • Add distributed compilation: dispatch cache misses to worker nodes by @christianparpart in #78
  • Add a Raft consensus library with a deterministic cluster simulation by @christianparpart in #82
  • consensus: Raft over the network — the peer wire, transport, pre-vote, membership and snapshots by @christianparpart in #83
  • node: worker metrics, an endpoint to serve them, and the facts a scheduler weighs by @christianparpart in #86
  • node: a daemon shell for the compile worker by @christianparpart in #88
  • cluster: find peers on a LAN, and prove who holds the key before admitting them by @christianparpart in #91
  • distributed: the scheduler moves to the node, and --listen-dispatch is deleted by @christianparpart in #93
  • node: a cache of its own, so a local rebuild never reaches the wire by @christianparpart in #94
  • cmake: FASTCACHE_AUTO_START stages and starts a daemon by @Yaraslaut in #95
  • Resource-aware scheduling, and a node closed to who it is not by @christianparpart in #96
  • Runtime cluster configuration, and a cluster that actually forms by @christianparpart in #98
  • One TCP client, in Net/, coroutine-aware — and a test client that builds on POSIX by @christianparpart in #99
  • ci: a documentation check queues per ref, not behind every Pages deploy by @christianparpart in #101

Full Changelog: v0.1.0...v0.1.1

fastcached v0.1.0

Choose a tag to compare

@github-actions github-actions released this 16 Aug 11:23
087f9dd

This is the first release of fastcached, so rather than a list of changes, here is what the project is and what it can do today.

What it is

Two things ship from this repository:

fastcached — an in-memory cache daemon that speaks the memcached text, memcached binary, memcached meta and Redis RESP2 protocols on a single port. It works out which one a client is using from the first bytes of the connection, so the port selects no protocol; every client reaches the same daemon on the same one.

fastcache-cc — a compiler launcher in the style of ccache and sccache, backed by that daemon. Its distinguishing property is that cache entries are portable across checkout paths: paths under your source root and build tree are rewritten to tokens before hashing, so the same source compiled at /home/alice/proj and at /ci/runner/w/1/s/proj produces the same cache key. CI runners and developer machines can therefore share one cache even when their trees live at different depths — which is the reason the launcher exists, since sccache keys on absolute paths and cannot.

They are useful together as a shared compile cache, and fastcached is useful on its own as a memcached/Redis-compatible cache, including as a plain sccache backend.

What is in this release

The daemon

  • Four wire protocols on one port, detected per connection — memcached text, binary and meta (mg/ms/md/ma/me/mn), and Redis RESP2. The default port is 6674, unassigned by IANA, unprivileged, and below the ephemeral range. Additional listeners are repeatable via --listen, so a client you cannot re-point keeps working on its own port, and that port speaks every protocol too.
  • Optional persistence with --storage: a copy-on-write B+tree where every commit is crash-consistent. The file always matches either the previous transaction or the new one, so a kill -9 at any instant leaves no half-written state, and a restart picks the cache back up with no warm-up. Storage is composed as an in-memory LRU over the on-disk tree, sharded by key hash so writes to different shards do not block each other.
  • --threads=N runs N single-threaded reactors (epoll, kqueue or IOCP), each pinned to a core, with every connection pinned to one reactor for its lifetime. Concurrent clients are bounded by memory rather than by a worker count.
  • Authentication with --requirepass (Redis AUTH, memcached SASL PLAIN), TLS on an OpenSSL build, and Prometheus /metrics plus /healthz on a separate admin port with --metrics.
  • YAML configuration with CLI flags taking precedence, re-read on SIGHUP or the Windows service manager's PARAMCHANGE. Started without --config, the daemon finds its own file from a per-platform list of locations — and which locations apply depends on whether the process could actually be the machine-wide service.
  • Packaged for Linux (.deb, .rpm), macOS (.pkg, .dmg) and Windows (.msi), each installing both executables and registering the daemon to start automatically, plus a Dockerfile for containers.

The launcher

  • Drop-in via CMAKE_<LANG>_COMPILER_LAUNCHER, or as a plain prefix for a single compile. Supports gcc/g++, clang/clang++ including versioned names, and MSVC cl and clang-cl.
  • If anything goes wrong — daemon unreachable, network gone, cache corrupt — it silently runs the real compiler. A broken cache can slow a build down; it should not be able to break one.
  • --show-stats reports hit rate, latency distributions and, importantly, a separate unavailable count, so "the cache did not help" and "the cache was never reached" do not look alike.

Performance

On in-memory GET throughput, measured on one AMD Ryzen 9 9950X3D against redis 8.10.0 and memcached 1.6.40 built and run as native binaries on the same host:

Concurrency fastcached vs redis vs memcached
1 ~125k ops/s ~1.05× (tie) ~1.0× (tie)
16 ~1.06M ops/s 3.0× ~1.07× (tie)
64 ~1.45M ops/s 4.5× 1.6×
256 ~1.32M ops/s 4.4× 1.6×

These are honest but narrow numbers, and worth reading with their limits attached: one fast desktop CPU, a single machine, and a Python load generator sharing that CPU with the server. At one connection there is no parallelism to exploit and all three tie. The redis baseline runs at its default io-threads 1, so a redis tuned for several I/O threads would narrow the network gap — what stands is the multi-core architecture, not a claim about redis at its best. The suite is in bench/ and reproduces with python bench/fastcached_bench.py --vs redis,memcached.

Scope, honestly

fastcached is not a general-purpose replacement for memcached or Redis. It implements only the slice of each protocol a cache backend actually uses, and the coverage matrix in the documentation says exactly which commands that is. If you need the rest of Redis, you need Redis.

It is, however, in production use as a shared compile cache for a large C++ codebase, backing both CI runners and developer machines.

Getting started

fastcached --storage=$HOME/.cache/fastcached/cache.cow

Then point clients at it, or wire the launcher into a build — the README walks through both, and the full documentation lives at https://lastrada-software.github.io/fastcached/.

This being a first release, there will be rough edges we have not found yet. Issue reports and feedback are genuinely welcome.

Licensed under the Apache License, Version 2.0. Memcached and Redis are registered trademarks of their respective owners.