From 7d0ac4ab25fdbe0c8acb1f216aa7c5391469238c Mon Sep 17 00:00:00 2001 From: Ray Walker Date: Sun, 6 Sep 2026 16:35:04 +1000 Subject: [PATCH 1/2] LAB-3037: record measured free-threaded performance in docs/free-threading.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 'Measured performance' section to free-threading.md with benchmark results from Dylan G's verification (commit bda770bce, CPython 3.14.3t, 8 physical cores). Table shows no-GIL vs GIL throughput across 1-8 threads. Measurements confirm: - Threaded scaling: 2.57x (1→4 threads, 64.2% efficiency) and 2.63x faster at 4 threads - Single-thread cost: 12.6% slower median, overlapping ranges Link measurement conditions, both findings (no 'negligible' claim), evidence comment, and parked cross-library work (LAB-3038). Update README link to point to new section. --- README.md | 3 ++- docs/free-threading.md | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b55493e..eb2c85b 100644 --- a/README.md +++ b/README.md @@ -363,7 +363,8 @@ free-threaded 3.14 with the GIL verified disabled (CI job `test-freethreaded`), and the Rust extension declares free-threaded safety (`gil_used = false`). Free-threaded wheels are **not yet published** and free-threaded builds are not officially supported — blocked on upstream -wheels (orjson, hiredis; numpy/pandas/pyarrow for `[data]`). Details and the +wheels (orjson, hiredis; numpy/pandas/pyarrow for `[data]`). See +[measured performance results](docs/free-threading.md#measured-performance) and the full concurrency audit: [docs/free-threading.md](docs/free-threading.md). **Per-Function Statistics:** diff --git a/docs/free-threading.md b/docs/free-threading.md index 0778cf5..1de4d13 100644 --- a/docs/free-threading.md +++ b/docs/free-threading.md @@ -88,6 +88,25 @@ hiredis is excluded because it does not declare free-threaded support (no `Py_mod_gil` slot); redis-py transparently falls back to its pure-Python parser. On a GIL build nothing changes — hiredis remains the default parser. +## Measured performance + +A post-merge benchmark run (commit `bda770bce822d9a6eff98e555c5f6fd92e509a9c`, CPython 3.14.3 free-threaded build, eight physical cores, pinned with `taskset -c 0-7` on a Ryzen 9 5950X) compared no-GIL and GIL cache throughput: + +| threads | no-GIL median s (min–max) | GIL median s (min–max) | GIL / no-GIL | +| --: | --: | --: | --: | +| 1 | 3.4422 (2.7822–4.4336) | 3.0566 (2.7979–3.3807) | 0.89x | +| 2 | 1.9956 (1.8117–2.2210) | 3.6367 (3.2625–3.8376) | 1.82x | +| 4 | 1.3402 (1.1175–1.9018) | 3.5293 (3.4629–4.8231) | 2.63x | +| 8 | 1.1550 (0.8962–1.4837) | 3.6749 (3.5853–4.7236) | 3.18x | + +**Measurement conditions:** Five isolated repetitions each; 16,000-operation workload; harness built-in warmup; GIL state asserted via `sys._is_gil_enabled()` at runtime. See [verification comment](https://github.com/cachekit-io/cachekit-py/pull/188#issuecomment-5557418229) for full details. + +**Key findings:** +- **Threaded throughput confirmed.** no-GIL reaches 2.57x one→four-thread scaling (64.2% efficiency) and is 2.63x faster than the GIL arm at four threads. +- **Single-thread cost confirmed.** no-GIL is 12.6% slower at the single-thread median; however, the ranges overlap (GIL max 3.3807 vs no-GIL min 2.7822). + +**Cross-library comparison:** The benchmark measures cachekit operations only. Cross-library throughput (orjson, numpy, pandas, pyarrow) was not run — these packages do not publish free-threaded (`cp314t`) wheels as of 2026-08. When upstream wheels ship, see [LAB-3038](mention://issue/01a07568-c0fc-778d-bfdb-e1d8aaaa4725) for cross-stack performance. + ## Deferred: declared support + free-threaded wheels Publishing `cp314t` wheels and declaring official free-threaded support is From 38ef029a7bc823be3dc89f10a0832ff33edb61c1 Mon Sep 17 00:00:00 2001 From: Mark S Date: Mon, 7 Sep 2026 02:16:07 +1000 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20address=20coderabbit=20review=20?= =?UTF-8?q?=E2=80=94=20CPU=20topology=20wording=20+=20resolvable=20ref?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit taskset -c 0-7 selects eight logical CPUs, not necessarily eight physical cores; state what was actually pinned for reproducibility. Replace the non-resolving mention:// URI for LAB-3038 with a plain-text internal-tracker reference so public readers hit no dead link. CodeRabbit-Resolved: docs/free-threading.md:93:Correct or qualify the CPU-top CodeRabbit-Resolved: docs/free-threading.md:108:Use a resolvable public link --- docs/free-threading.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/free-threading.md b/docs/free-threading.md index 1de4d13..acce4a8 100644 --- a/docs/free-threading.md +++ b/docs/free-threading.md @@ -90,7 +90,7 @@ parser. On a GIL build nothing changes — hiredis remains the default parser. ## Measured performance -A post-merge benchmark run (commit `bda770bce822d9a6eff98e555c5f6fd92e509a9c`, CPython 3.14.3 free-threaded build, eight physical cores, pinned with `taskset -c 0-7` on a Ryzen 9 5950X) compared no-GIL and GIL cache throughput: +A post-merge benchmark run (commit `bda770bce822d9a6eff98e555c5f6fd92e509a9c`, CPython 3.14.3 free-threaded build, eight logical CPUs, pinned with `taskset -c 0-7` on a Ryzen 9 5950X) compared no-GIL and GIL cache throughput: | threads | no-GIL median s (min–max) | GIL median s (min–max) | GIL / no-GIL | | --: | --: | --: | --: | @@ -105,7 +105,7 @@ A post-merge benchmark run (commit `bda770bce822d9a6eff98e555c5f6fd92e509a9c`, C - **Threaded throughput confirmed.** no-GIL reaches 2.57x one→four-thread scaling (64.2% efficiency) and is 2.63x faster than the GIL arm at four threads. - **Single-thread cost confirmed.** no-GIL is 12.6% slower at the single-thread median; however, the ranges overlap (GIL max 3.3807 vs no-GIL min 2.7822). -**Cross-library comparison:** The benchmark measures cachekit operations only. Cross-library throughput (orjson, numpy, pandas, pyarrow) was not run — these packages do not publish free-threaded (`cp314t`) wheels as of 2026-08. When upstream wheels ship, see [LAB-3038](mention://issue/01a07568-c0fc-778d-bfdb-e1d8aaaa4725) for cross-stack performance. +**Cross-library comparison:** The benchmark measures cachekit operations only. Cross-library throughput (orjson, numpy, pandas, pyarrow) was not run — these packages do not publish free-threaded (`cp314t`) wheels as of 2026-08. When upstream wheels ship, cross-stack performance will be measured then (tracked internally as LAB-3038). ## Deferred: declared support + free-threaded wheels