aboutsummaryrefslogtreecommitdiffstats
path: root/research/experiments/001-checkpoint-granularity
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-24 17:14:54 +0100
committereunhhu <[email protected]>2026-09-24 17:14:54 +0100
commitb1ce1927022d374198441afafeb27199fc8a052a (patch)
tree6021f175f4c67ed03b44240eaa2f90d846f12f6f /research/experiments/001-checkpoint-granularity
parentd34f9426d5317a1948f12f229439946728bc342a (diff)
downloadpure-b1ce1927022d374198441afafeb27199fc8a052a.tar.gz
pure-b1ce1927022d374198441afafeb27199fc8a052a.zip
Establish native micro runtime checkpoint
Diffstat (limited to 'research/experiments/001-checkpoint-granularity')
-rw-r--r--research/experiments/001-checkpoint-granularity/README.md110
-rw-r--r--research/experiments/001-checkpoint-granularity/benchmark.c276
-rw-r--r--research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/environment.json330
-rw-r--r--research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/raw.csv281
-rw-r--r--research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/summary.csv41
-rw-r--r--research/experiments/001-checkpoint-granularity/run.py148
6 files changed, 1186 insertions, 0 deletions
diff --git a/research/experiments/001-checkpoint-granularity/README.md b/research/experiments/001-checkpoint-granularity/README.md
new file mode 100644
index 0000000..4c04950
--- /dev/null
+++ b/research/experiments/001-checkpoint-granularity/README.md
@@ -0,0 +1,110 @@
+# Experiment 001: checkpoint granularity
+
+This is a native measurement apparatus for one known space/time tradeoff. It is
+not a new algorithm, a general dependency-graph runtime, or the product's language
+choice. The apparatus uses C17 and Python's standard library so it can be run
+with the tools present on the initial Linux host and with a C compiler on macOS.
+
+## Question and pre-measurement expectations
+
+How much does storing intermediate results at different intervals save, once the
+editable program and scheduling state are included? How much extra work does it
+cause when a rule changes?
+
+Expected, not measured at the time of writing this section:
+
+- Uniformly spaced checkpoints shrink the result cache at the cost of starting
+ recomputation before the changed instruction.
+- Root input changes offer no prefix to reuse. Fine checkpoints may only add
+ cache writes and comparisons in this workload.
+- Edits near the end favor fine checkpoints. This deliberately favorable case
+ must not stand in for all edits.
+- The editable model stays resident, so shrinking the cache 16-fold will not
+ shrink total core storage 16-fold.
+
+## Semantics and comparison
+
+The model consists of independent, statically connected chains. Each instruction
+is an 8-byte record with a scalar operator and parameter. Values are uint64_t;
+overflow wraps. Supported operators are add, XOR, multiply, and rotate/XOR.
+Only the final result of each chain is observed.
+
+One update applies a batch of changes, then computes all affected observed
+outputs. Changes alter roots, operators, and parameters, not graph topology.
+There is no renderer, effectful I/O, concurrent execution, or state migration.
+
+- Block 1 stores every intermediate result (fine incremental baseline).
+- Blocks 4, 16, and 64 store results at block ends.
+- A block equal to chain length recomputes the whole affected chain, retaining
+ only its final output (full recomputation baseline).
+
+All variants share program representation, input handling and per-chain dirty
+ranges. Unaffected chains are skipped by every variant. Fine and full variants
+use dedicated loops. Fine/block variants stop at an unchanged cached boundary
+only after passing the last changed instruction in the batch.
+
+The chain structure makes dependency information implicit. No general graph
+edge storage or graph partitioning is needed. This is an optimistic case for
+compact checkpoints; it cannot establish results for arbitrary graphs.
+
+For G chains of length L and checkpoint spacing B, the requested persistent
+storage in this implementation is:
+
+```text
+sizeof(Engine) + 8*G*L + 16*G + 8*G*ceil(L/B)
+ model inputs+ cached values,
+ dirty including outputs
+```
+
+This includes all live core arrays and the engine descriptor, but not allocator
+bookkeeping, stack, executable code, trace storage or OS pages. Trace size is
+recorded separately. It is not RSS, physical footprint, or total application RAM.
+There are no allocations in the timed update path.
+
+## Workloads
+
+The fixed initial matrix uses 16 chains, lengths 256 and 1024, and 256 updates per
+trace. Workload seed: 20260922.
+
+- `roots`: every chain's input changes on every update.
+- `uniform`: one uniformly selected instruction changes per update.
+- `tail`: one instruction in the last eight positions changes per update.
+- `dense`: eight instruction edits per chain per update, with replacement.
+
+Changes are XOR deltas so repeated traces continue changing the model. Two
+warm-up passes precede timing. Even measured replay counts leave identical final
+models across strategies; the runner checks their output checksums. Differential
+tests additionally compare every output after every update against independent
+from-scratch evaluation across multiple seeds, odd sizes and edge cases.
+
+## Reproduce
+
+From this directory, with Python 3 and a C compiler with ASan/UBSan support:
+
+```sh
+python3 run.py --check-only
+python3 run.py --output results/local-run
+```
+
+The runner refuses to overwrite an existing result directory. `CC` can select a
+compiler, such as `CC=clang`. It builds into a temporary directory. On Linux it
+pins itself and child processes to one available CPU and records that choice.
+
+Default measurements use seven trials with randomized strategy order within
+each trial. Pilot timings choose an even replay count per case, targeting 20 ms
+per measurement. All raw samples, memory counts, instruction counts, compiler
+flags, source hashes and host metadata are retained. Timing excludes program
+creation, trace creation, warm-up, and output verification. It includes change
+application, scheduling and recomputation.
+
+`median_ns_per_tick` is the median of batch-average processing times. It is not a
+P50/P99 input-to-display latency measurement. A shared host without controlled
+power or temperature permits preliminary comparisons, not hardware guarantees.
+
+The reported storage reduction is largely predicted by the formula. The useful
+observations are the whole-core reduction, processing cost and losing workloads.
+This experiment cannot establish automatic policy quality, novel research,
+editor usability, M3 performance, or universal memory savings.
+
+The first run and its interpretation are available in the
+[Korean research report](../../../docs/research/002-checkpoint-results.md).
diff --git a/research/experiments/001-checkpoint-granularity/benchmark.c b/research/experiments/001-checkpoint-granularity/benchmark.c
new file mode 100644
index 0000000..1c3f98b
--- /dev/null
+++ b/research/experiments/001-checkpoint-granularity/benchmark.c
@@ -0,0 +1,276 @@
+#define _POSIX_C_SOURCE 200809L
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/* Experimental apparatus, not the Pure runtime. All arithmetic is modulo 2^64. */
+typedef struct { uint32_t salt, control; } Op;
+typedef struct {
+ uint32_t chain, index;
+ uint64_t mask;
+} Change;
+typedef struct {
+ uint32_t chains, length, block, slots;
+ Op *ops;
+ uint64_t *inputs, *cache;
+ uint32_t *first, *last;
+} Engine;
+typedef struct {
+ uint32_t ticks, per_tick;
+ Change *changes;
+} Trace;
+
+static void die(const char *s) { fprintf(stderr, "%s\n", s); exit(1); }
+static void require(int condition, const char *s) { if (!condition) die(s); }
+static void *allocate(size_t count, size_t size) {
+ if (size && count > SIZE_MAX / size) die("allocation size overflow");
+ void *p = calloc(count, size);
+ if (!p) die("allocation failed");
+ return p;
+}
+static uint64_t random64(uint64_t *s) {
+ uint64_t z = (*s += UINT64_C(0x9e3779b97f4a7c15));
+ z = (z ^ (z >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
+ z = (z ^ (z >> 27)) * UINT64_C(0x94d049bb133111eb);
+ return z ^ (z >> 31);
+}
+static uint64_t rotate(uint64_t x, uint32_t n) {
+ return (x << n) | (x >> (64 - n));
+}
+static uint64_t evaluate(Op op, uint64_t x) {
+ switch (op.control & 3u) {
+ case 0: return x + op.salt;
+ case 1: return x ^ ((uint64_t)op.salt << 17);
+ case 2: return x * ((uint64_t)op.salt | 1u);
+ default: return rotate(x, 1u + ((op.control >> 2) % 63u)) ^ op.salt;
+ }
+}
+static uint64_t now_ns(void) {
+ struct timespec t;
+ if (clock_gettime(CLOCK_MONOTONIC, &t)) die("clock_gettime failed");
+ return (uint64_t)t.tv_sec * UINT64_C(1000000000) + (uint64_t)t.tv_nsec;
+}
+static uint64_t output(const Engine *e, uint32_t c) {
+ return e->cache[(size_t)c * e->slots + e->slots - 1];
+}
+static uint64_t reference_output(const Engine *e, uint32_t c) {
+ uint64_t x = e->inputs[c];
+ for (uint32_t n = 0; n < e->length; ++n)
+ x = evaluate(e->ops[(size_t)c * e->length + n], x);
+ return x;
+}
+static Engine create_engine(uint32_t chains, uint32_t length,
+ uint32_t block, uint64_t seed) {
+ Engine e = { .chains = chains, .length = length, .block = block,
+ .slots = (length + block - 1) / block };
+ e.ops = allocate((size_t)chains * length, sizeof(*e.ops));
+ e.inputs = allocate(chains, sizeof(*e.inputs));
+ e.cache = allocate((size_t)chains * e.slots, sizeof(*e.cache));
+ e.first = allocate(chains, sizeof(*e.first));
+ e.last = allocate(chains, sizeof(*e.last));
+ for (uint32_t c = 0; c < chains; ++c) {
+ e.inputs[c] = random64(&seed);
+ uint64_t x = e.inputs[c];
+ for (uint32_t n = 0; n < length; ++n) {
+ Op *op = &e.ops[(size_t)c * length + n];
+ op->salt = (uint32_t)random64(&seed);
+ op->control = (uint32_t)random64(&seed);
+ x = evaluate(*op, x);
+ if ((n + 1) % block == 0 || n + 1 == length)
+ e.cache[(size_t)c * e.slots + n / block] = x;
+ }
+ e.first[c] = length;
+ }
+ return e;
+}
+static void destroy_engine(Engine *e) {
+ free(e->ops); free(e->inputs); free(e->cache);
+ free(e->first); free(e->last);
+}
+static void apply(Engine *e, Change change) {
+ uint32_t c = change.chain, n = change.index;
+ require(c < e->chains && n <= e->length, "invalid change");
+ if (!change.mask) return;
+ if (n == e->length) {
+ e->inputs[c] ^= change.mask;
+ n = 0;
+ } else {
+ Op *op = &e->ops[(size_t)c * e->length + n];
+ op->salt ^= (uint32_t)change.mask;
+ op->control ^= (uint32_t)(change.mask >> 32);
+ }
+ if (n < e->first[c]) e->first[c] = n;
+ if (n > e->last[c]) e->last[c] = n;
+}
+static uint64_t update(Engine *e) {
+ uint64_t work = 0;
+ for (uint32_t c = 0; c < e->chains; ++c) {
+ uint32_t first = e->first[c], last = e->last[c];
+ if (first == e->length) continue;
+ const Op *ops = e->ops + (size_t)c * e->length;
+ uint64_t *cache = e->cache + (size_t)c * e->slots;
+ /* Full and fine have dedicated loops: no block-loop penalty for B=1. */
+ if (e->block == e->length) {
+ uint64_t x = e->inputs[c];
+ for (uint32_t n = 0; n < e->length; ++n) x = evaluate(ops[n], x);
+ cache[0] = x;
+ work += e->length;
+ } else if (e->block == 1) {
+ uint64_t x = first ? cache[first - 1] : e->inputs[c];
+ uint32_t n = first;
+ while (n < e->length) {
+ uint64_t old = cache[n];
+ cache[n] = x = evaluate(ops[n], x);
+ ++n;
+ /* Do not skip a later edit in the same batch. */
+ if (n > last && x == old) break;
+ }
+ work += n - first;
+ } else {
+ uint32_t start = first / e->block;
+ uint64_t x = start ? cache[start - 1] : e->inputs[c];
+ for (uint32_t b = start; b < e->slots; ++b) {
+ uint32_t begin = b * e->block, end = begin + e->block;
+ if (end > e->length) end = e->length;
+ for (uint32_t n = begin; n < end; ++n) x = evaluate(ops[n], x);
+ uint64_t old = cache[b];
+ cache[b] = x;
+ work += end - begin;
+ if (end > last && x == old) break;
+ }
+ }
+ e->first[c] = e->length;
+ e->last[c] = 0;
+ }
+ return work;
+}
+static uint64_t checksum(const Engine *e) {
+ uint64_t h = UINT64_C(0xcbf29ce484222325);
+ for (uint32_t c = 0; c < e->chains; ++c)
+ h = (h ^ output(e, c)) * UINT64_C(0x100000001b3);
+ return h;
+}
+static Trace create_trace(const char *kind, uint32_t chains, uint32_t length,
+ uint32_t ticks, uint64_t seed) {
+ uint32_t per_tick = 1;
+ int roots = !strcmp(kind, "roots");
+ int dense = !strcmp(kind, "dense");
+ int uniform = !strcmp(kind, "uniform");
+ int tail = !strcmp(kind, "tail");
+ require(roots || dense || uniform || tail, "unknown workload");
+ if (roots) per_tick = chains;
+ if (dense) per_tick = chains * 8;
+ Trace t = { .ticks = ticks, .per_tick = per_tick };
+ t.changes = allocate((size_t)ticks * per_tick, sizeof(*t.changes));
+ for (uint32_t i = 0; i < ticks; ++i) {
+ for (uint32_t k = 0; k < per_tick; ++k) {
+ Change *p = &t.changes[(size_t)i * per_tick + k];
+ p->chain = roots ? k : dense ? k / 8 : (uint32_t)(random64(&seed) % chains);
+ p->index = roots ? length : (uint32_t)(random64(&seed) % length);
+ if (tail) {
+ uint32_t width = length < 8 ? length : 8;
+ p->index = length - width + p->index % width;
+ }
+ /* XOR changes keep every replay active; fixed assignments would not. */
+ p->mask = random64(&seed) | 1u;
+ }
+ }
+ return t;
+}
+static uint64_t replay(Engine *e, const Trace *t) {
+ uint64_t work = 0;
+ for (uint32_t i = 0; i < t->ticks; ++i) {
+ for (uint32_t k = 0; k < t->per_tick; ++k)
+ apply(e, t->changes[(size_t)i * t->per_tick + k]);
+ work += update(e);
+ }
+ return work;
+}
+static size_t owned_bytes(const Engine *e) {
+ return sizeof(*e) + (size_t)e->chains * e->length * sizeof(*e->ops)
+ + (size_t)e->chains * (sizeof(*e->inputs) + sizeof(*e->first) + sizeof(*e->last))
+ + (size_t)e->chains * e->slots * sizeof(*e->cache);
+}
+static void check_outputs(const Engine *e) {
+ for (uint32_t c = 0; c < e->chains; ++c)
+ require(output(e, c) == reference_output(e, c), "output disagrees with full reference");
+}
+static void self_test(void) {
+ const uint32_t lengths[] = {1, 2, 7, 17, 65, 257};
+ const uint32_t blocks[] = {1, 2, 4, 16, 64, 256};
+ uint64_t checked_ticks = 0;
+ for (uint64_t seed = 1; seed <= 8; ++seed) {
+ for (size_t l = 0; l < sizeof(lengths) / sizeof(*lengths); ++l) {
+ uint32_t length = lengths[l];
+ for (size_t b = 0; b <= sizeof(blocks) / sizeof(*blocks); ++b) {
+ uint32_t block = b == sizeof(blocks) / sizeof(*blocks) ? length : blocks[b];
+ if (block > length) continue;
+ Engine e = create_engine(3, length, block, seed);
+ check_outputs(&e);
+ uint64_t rng = seed;
+ for (uint32_t tick = 0; tick < 500; ++tick) {
+ uint32_t count = (uint32_t)(random64(&rng) % 9);
+ for (uint32_t k = 0; k < count; ++k) {
+ Change change = {
+ .chain = (uint32_t)(random64(&rng) % e.chains),
+ .index = (uint32_t)(random64(&rng) % (length + 1)),
+ .mask = random64(&rng)
+ };
+ if (tick % 11 == 0) change.mask = 0;
+ apply(&e, change);
+ if (tick % 13 == 0) apply(&e, change); /* cancelling edits */
+ }
+ (void)update(&e);
+ check_outputs(&e);
+ require(update(&e) == 0, "clean update performed work");
+ ++checked_ticks;
+ }
+ destroy_engine(&e);
+ }
+ }
+ }
+ /* An unchanged early checkpoint must not suppress a later dirty operation. */
+ for (uint32_t block = 1; block <= 4; block *= 2) {
+ Engine e = create_engine(1, 8, block, 77);
+ Change cancel = {0, 0, 123}, later = {0, 7, 987};
+ apply(&e, cancel); apply(&e, cancel); apply(&e, later);
+ (void)update(&e); check_outputs(&e); destroy_engine(&e);
+ }
+ printf("{\"checked_ticks\":%" PRIu64 ",\"status\":\"passed\"}\n", checked_ticks);
+}
+static uint32_t number(const char *s, uint32_t max) {
+ char *end;
+ errno = 0;
+ unsigned long n = strtoul(s, &end, 10);
+ if (errno || end == s || *end || !n || n > max) die("invalid positive integer");
+ return (uint32_t)n;
+}
+int main(int argc, char **argv) {
+ if (argc == 2 && !strcmp(argv[1], "--check")) { self_test(); return 0; }
+ if (argc != 8) die("usage: benchmark CHAINS LENGTH BLOCK WORKLOAD TICKS REPLAYS SEED | --check");
+ uint32_t chains = number(argv[1], 1024), length = number(argv[2], 65536);
+ uint32_t block = number(argv[3], length), ticks = number(argv[5], 4096);
+ uint32_t replays = number(argv[6], 4096), seed = number(argv[7], UINT32_MAX);
+ require((uint64_t)chains * length <= UINT64_C(1048576), "model too large for this lab");
+ Engine e = create_engine(chains, length, block, seed);
+ Trace t = create_trace(argv[4], chains, length, ticks, seed + UINT64_C(1234567));
+ (void)replay(&e, &t); (void)replay(&e, &t); /* two warm-up replays */
+ uint64_t work = 0, start = now_ns();
+ for (uint32_t r = 0; r < replays; ++r) work += replay(&e, &t);
+ uint64_t elapsed = now_ns() - start;
+ check_outputs(&e); /* correctness check is outside the measured interval */
+ printf("{\"elapsed_ns\":%" PRIu64 ",\"ticks\":%" PRIu64
+ ",\"node_evaluations\":%" PRIu64 ",\"core_owned_bytes\":%zu"
+ ",\"model_bytes\":%zu,\"cache_bytes\":%zu,\"engine_bytes\":%zu"
+ ",\"trace_bytes\":%zu,\"checksum\":\"%016" PRIx64 "\"}\n",
+ elapsed, (uint64_t)ticks * replays, work, owned_bytes(&e),
+ (size_t)chains * length * sizeof(Op),
+ (size_t)chains * e.slots * sizeof(uint64_t), sizeof(Engine),
+ sizeof(t) + (size_t)t.ticks * t.per_tick * sizeof(Change), checksum(&e));
+ free(t.changes); destroy_engine(&e);
+ return 0;
+}
diff --git a/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/environment.json b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/environment.json
new file mode 100644
index 0000000..1e967ad
--- /dev/null
+++ b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/environment.json
@@ -0,0 +1,330 @@
+{
+ "started_utc": "2026-09-22T09:32:06.820074+00:00",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "compiler": "cc (Debian 14.2.0-19) 14.2.0\nCopyright (C) 2024 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions. There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.",
+ "flags": [
+ "-std=c17",
+ "-O3",
+ "-Wall",
+ "-Wextra",
+ "-Wpedantic",
+ "-Werror"
+ ],
+ "python": "3.14.7",
+ "source_sha256": "9e1b1108f58a8725458531207bd1edf06d9af43ae3255c3b97d4388c2b58c707",
+ "runner_sha256": "4c3e8ae899eb5068813df9529a8c7953d63730ee3ca507a0a7dbe58963b1db01",
+ "trials": 7,
+ "target_ms": 20.0,
+ "seed": 20260922,
+ "timing": "batch elapsed time / update ticks; not input latency",
+ "memory": "sizeof engine + requested live array bytes; excludes allocator, harness, code, OS",
+ "power_control": "not controlled; shared host; preliminary measurements",
+ "original_affinity": [
+ 0,
+ 1,
+ 2,
+ 3
+ ],
+ "measurement_affinity": [
+ 0
+ ],
+ "cpu_description": [
+ "CPU architecture: 8",
+ "CPU implementer\t: 0x41",
+ "CPU part\t: 0xd0b",
+ "Model\t\t: Raspberry Pi 5 Model B Rev 1.1"
+ ],
+ "release_check": {
+ "checked_ticks": 108000,
+ "status": "passed"
+ },
+ "sanitizer_check": {
+ "checked_ticks": 108000,
+ "status": "passed"
+ },
+ "calibration_replays": [
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "roots",
+ "block": 1,
+ "replays": 6
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "roots",
+ "block": 4,
+ "replays": 4
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "roots",
+ "block": 16,
+ "replays": 6
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "roots",
+ "block": 64,
+ "replays": 6
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "roots",
+ "block": 256,
+ "replays": 6
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "uniform",
+ "block": 1,
+ "replays": 130
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "uniform",
+ "block": 4,
+ "replays": 110
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "uniform",
+ "block": 16,
+ "replays": 130
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "uniform",
+ "block": 64,
+ "replays": 124
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "uniform",
+ "block": 256,
+ "replays": 74
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "tail",
+ "block": 1,
+ "replays": 968
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "tail",
+ "block": 4,
+ "replays": 870
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "tail",
+ "block": 16,
+ "replays": 730
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "tail",
+ "block": 64,
+ "replays": 384
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "tail",
+ "block": 256,
+ "replays": 86
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "dense",
+ "block": 1,
+ "replays": 4
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "dense",
+ "block": 4,
+ "replays": 4
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "dense",
+ "block": 16,
+ "replays": 4
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "dense",
+ "block": 64,
+ "replays": 4
+ },
+ {
+ "chains": 16,
+ "length": 256,
+ "workload": "dense",
+ "block": 256,
+ "replays": 4
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "roots",
+ "block": 1,
+ "replays": 2
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "roots",
+ "block": 4,
+ "replays": 2
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "roots",
+ "block": 16,
+ "replays": 2
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "roots",
+ "block": 64,
+ "replays": 2
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "roots",
+ "block": 1024,
+ "replays": 2
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "uniform",
+ "block": 1,
+ "replays": 24
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "uniform",
+ "block": 4,
+ "replays": 22
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "uniform",
+ "block": 16,
+ "replays": 24
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "uniform",
+ "block": 64,
+ "replays": 24
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "uniform",
+ "block": 1024,
+ "replays": 14
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "tail",
+ "block": 1,
+ "replays": 912
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "tail",
+ "block": 4,
+ "replays": 834
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "tail",
+ "block": 16,
+ "replays": 708
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "tail",
+ "block": 64,
+ "replays": 384
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "tail",
+ "block": 1024,
+ "replays": 14
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "dense",
+ "block": 1,
+ "replays": 2
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "dense",
+ "block": 4,
+ "replays": 2
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "dense",
+ "block": 16,
+ "replays": 2
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "dense",
+ "block": 64,
+ "replays": 2
+ },
+ {
+ "chains": 16,
+ "length": 1024,
+ "workload": "dense",
+ "block": 1024,
+ "replays": 2
+ }
+ ],
+ "completed_utc": "2026-09-22T09:32:24.887753+00:00",
+ "binary_bytes": 71208
+}
diff --git a/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/raw.csv b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/raw.csv
new file mode 100644
index 0000000..1ed88ef
--- /dev/null
+++ b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/raw.csv
@@ -0,0 +1,281 @@
+trial,chains,length,workload,block,replays,elapsed_ns,ticks,node_evaluations,core_owned_bytes,model_bytes,cache_bytes,engine_bytes,trace_bytes,checksum,ns_per_tick,evaluations_per_tick
+0,16,256,uniform,256,74,19423930,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1025.3341427364865,256.0
+0,16,256,dense,256,4,27889701,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27236.0361328125,4096.0
+0,16,256,dense,64,4,27252683,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26613.9482421875,3984.5
+0,16,256,tail,16,730,16031339,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,85.78413420376712,16.0
+0,16,1024,roots,1,2,58533196,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,114322.6484375,16384.0
+0,16,1024,uniform,1,24,20859539,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3395.1072591145835,533.7734375
+0,16,256,roots,256,6,23781630,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,15482.83203125,4096.0
+0,16,1024,dense,4,2,63661600,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,124339.0625,14567.8125
+0,16,1024,uniform,1024,14,22677705,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6327.484654017857,1024.0
+0,16,256,tail,1,968,15760618,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,63.60011783316116,4.5546875
+0,16,1024,tail,4,834,14631637,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,68.53097365857315,5.984375
+0,16,1024,tail,1,912,15252766,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,65.33017235471492,4.5546875
+0,16,256,dense,4,4,28737719,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28064.1787109375,3665.4375
+0,16,1024,roots,64,2,54914217,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,107254.330078125,16384.0
+0,16,256,roots,1,6,30769606,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,20032.295572916668,4096.0
+0,16,1024,roots,16,2,57387697,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,112085.345703125,16384.0
+0,16,1024,roots,1024,2,55510329,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,108418.611328125,16384.0
+0,16,1024,uniform,64,24,20219114,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3290.8714192708335,565.25
+0,16,1024,roots,4,2,69964336,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,136649.09375,16384.0
+0,16,1024,uniform,16,24,20636818,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3358.8570963541665,540.9375
+0,16,256,roots,4,4,21918928,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21405.203125,4096.0
+0,16,1024,uniform,4,22,21167687,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3758.4671519886365,535.203125
+0,16,256,uniform,4,110,17970005,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,638.1393821022727,132.203125
+0,16,1024,tail,16,708,15733117,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,86.80436197916667,16.0
+0,16,256,roots,16,6,25329389,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16490.487630208332,4096.0
+0,16,1024,dense,64,2,55407347,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108217.474609375,15004.25
+0,16,1024,tail,64,384,18079579,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,183.91498819986978,64.0
+0,16,1024,dense,16,2,57109105,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,111541.220703125,14661.375
+0,16,256,uniform,1,130,19115671,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,574.3891526442308,130.7734375
+0,16,256,uniform,16,130,18864226,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,566.8337139423077,137.9375
+0,16,256,dense,1,4,26646406,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26021.880859375,3642.171875
+0,16,1024,dense,1024,2,60125695,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,117432.998046875,16384.0
+0,16,256,tail,4,870,15279896,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,68.60585488505747,5.984375
+0,16,256,tail,64,384,18427282,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,187.4520060221354,64.0
+0,16,256,tail,256,86,19077985,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,866.5509175145348,256.0
+0,16,256,uniform,64,124,19114097,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,602.1325919858871,162.25
+0,16,256,dense,16,4,27271257,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26632.0869140625,3752.0
+0,16,1024,dense,1,2,56247180,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,109857.7734375,14544.31640625
+0,16,1024,tail,1024,14,22547316,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6291.103794642857,1024.0
+0,16,256,roots,64,6,24836741,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,16169.753255208334,4096.0
+1,16,256,tail,16,730,15723896,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,84.13899828767123,16.0
+1,16,1024,roots,64,2,53830403,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,105137.505859375,16384.0
+1,16,256,uniform,64,124,19164986,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,603.7356980846774,162.25
+1,16,1024,roots,16,2,57857808,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,113003.53125,16384.0
+1,16,256,tail,256,86,18910930,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,858.9630268895348,256.0
+1,16,256,uniform,1,130,19119244,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,574.496514423077,130.7734375
+1,16,256,uniform,256,74,19320449,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1019.8716744087837,256.0
+1,16,256,dense,64,4,27044701,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26410.8408203125,3984.5
+1,16,1024,tail,4,834,14780378,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,69.22763976318944,5.984375
+1,16,1024,tail,1,912,15955191,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,68.33877724095395,4.5546875
+1,16,256,dense,256,4,27838608,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27186.140625,4096.0
+1,16,256,uniform,4,110,18108468,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,643.0563920454546,132.203125
+1,16,1024,uniform,64,24,20199430,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3287.6676432291665,565.25
+1,16,256,tail,4,870,15577488,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,69.94202586206896,5.984375
+1,16,1024,dense,4,2,63503118,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,124029.52734375,14567.8125
+1,16,1024,roots,1,2,60590399,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,118340.623046875,16384.0
+1,16,1024,dense,16,2,58815196,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,114873.4296875,14661.375
+1,16,1024,uniform,1,24,20999687,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3417.9178059895835,533.7734375
+1,16,1024,dense,64,2,55368532,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108141.6640625,15004.25
+1,16,256,roots,64,6,25027166,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,16293.727864583334,4096.0
+1,16,256,dense,4,4,28726459,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28053.1826171875,3665.4375
+1,16,1024,dense,1024,2,59377529,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,115971.736328125,16384.0
+1,16,1024,uniform,1024,14,22664872,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6323.904017857143,1024.0
+1,16,1024,tail,16,708,16137451,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,89.03519487111582,16.0
+1,16,1024,dense,1,2,59209844,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,115644.2265625,14544.31640625
+1,16,1024,tail,1024,14,28440553,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,7935.422154017857,1024.0
+1,16,1024,uniform,16,24,22939408,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3733.6276041666665,540.9375
+1,16,1024,roots,4,2,68243319,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,133287.732421875,16384.0
+1,16,1024,uniform,4,22,22284502,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3956.7652698863635,535.203125
+1,16,1024,tail,64,384,19017726,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,193.45831298828125,64.0
+1,16,1024,roots,1024,2,54456218,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,106359.80078125,16384.0
+1,16,256,roots,1,6,29430274,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,19160.334635416668,4096.0
+1,16,256,tail,1,968,16229803,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,65.4934586454029,4.5546875
+1,16,256,uniform,16,130,18842745,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,566.1882512019231,137.9375
+1,16,256,roots,256,6,25712943,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,16740.197265625,4096.0
+1,16,256,roots,16,6,24999092,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16275.450520833334,4096.0
+1,16,256,tail,64,384,18145560,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,184.586181640625,64.0
+1,16,256,roots,4,4,21467262,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,20964.123046875,4096.0
+1,16,256,dense,1,4,26614572,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,25990.79296875,3642.171875
+1,16,256,dense,16,4,27211406,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26573.638671875,3752.0
+2,16,1024,dense,64,2,55177792,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,107769.125,15004.25
+2,16,1024,roots,1024,2,56337550,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,110034.27734375,16384.0
+2,16,256,uniform,256,74,19340633,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1020.9371304898649,256.0
+2,16,1024,roots,4,2,70127632,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,136968.03125,16384.0
+2,16,256,uniform,16,130,18852485,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,566.4809194711538,137.9375
+2,16,256,uniform,64,124,19214726,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,605.3026083669355,162.25
+2,16,256,dense,4,4,29007978,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28328.103515625,3665.4375
+2,16,1024,roots,64,2,55147181,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,107709.337890625,16384.0
+2,16,1024,uniform,16,24,20757910,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3378.5660807291665,540.9375
+2,16,256,roots,16,6,24347186,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,15851.032552083334,4096.0
+2,16,1024,uniform,1024,14,23230334,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6481.678013392857,1024.0
+2,16,1024,dense,1024,2,59534306,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,116277.94140625,16384.0
+2,16,1024,uniform,1,24,20842391,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3392.3162434895835,533.7734375
+2,16,256,uniform,1,130,19198967,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,576.8920372596153,130.7734375
+2,16,256,uniform,4,110,17994653,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,639.0146661931818,132.203125
+2,16,256,dense,64,4,27086276,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26451.44140625,3984.5
+2,16,256,roots,4,4,21994113,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21478.6259765625,4096.0
+2,16,1024,roots,16,2,57820049,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,112929.783203125,16384.0
+2,16,256,dense,256,4,27941793,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27286.9072265625,4096.0
+2,16,1024,tail,16,708,16133895,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,89.01557534427967,16.0
+2,16,1024,tail,64,384,18182820,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,184.9652099609375,64.0
+2,16,256,tail,256,86,18779634,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,852.9993640988372,256.0
+2,16,256,roots,256,6,22007890,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,14328.053385416666,4096.0
+2,16,1024,tail,1024,14,22562372,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6295.3046875,1024.0
+2,16,1024,tail,1,912,15219507,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,65.18771844161184,4.5546875
+2,16,256,tail,1,968,16217302,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,65.4430123321281,4.5546875
+2,16,256,tail,16,730,15889117,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,85.02310038527398,16.0
+2,16,256,roots,64,6,24043260,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,15653.1640625,4096.0
+2,16,256,tail,64,384,18128542,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,184.4130655924479,64.0
+2,16,256,roots,1,6,28856219,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,18786.600911458332,4096.0
+2,16,256,dense,1,4,26688073,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26062.5712890625,3642.171875
+2,16,1024,roots,1,2,59012937,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,115259.642578125,16384.0
+2,16,1024,tail,4,834,15146304,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,70.94154676258992,5.984375
+2,16,1024,uniform,4,22,21112966,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3748.751065340909,535.203125
+2,16,1024,uniform,64,24,20180244,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3284.544921875,565.25
+2,16,256,dense,16,4,27251979,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26613.2607421875,3752.0
+2,16,1024,dense,1,2,56115124,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,109599.8515625,14544.31640625
+2,16,256,tail,4,870,15574118,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,69.92689475574713,5.984375
+2,16,1024,dense,4,2,63355452,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,123741.1171875,14567.8125
+2,16,1024,dense,16,2,59015622,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,115264.88671875,14661.375
+3,16,1024,dense,1024,2,59351733,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,115921.353515625,16384.0
+3,16,256,tail,64,384,18358098,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,186.74822998046875,64.0
+3,16,256,tail,256,86,18854430,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,856.3967114825581,256.0
+3,16,1024,tail,4,834,14976119,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,70.14444225869305,5.984375
+3,16,1024,uniform,1024,14,22676798,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6327.231584821428,1024.0
+3,16,1024,tail,1024,14,22703465,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6334.672154017857,1024.0
+3,16,256,dense,64,4,27086110,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26451.279296875,3984.5
+3,16,256,roots,256,6,25762944,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,16772.75,4096.0
+3,16,256,uniform,1,130,19111541,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,574.2650540865385,130.7734375
+3,16,1024,roots,4,2,70026373,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,136770.259765625,16384.0
+3,16,1024,tail,1,912,16096766,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,68.94516687225877,4.5546875
+3,16,256,dense,16,4,27379350,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26737.646484375,3752.0
+3,16,256,roots,16,6,24957185,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16248.167317708334,4096.0
+3,16,256,tail,16,730,15562896,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,83.27748287671233,16.0
+3,16,256,roots,1,6,28879071,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,18801.478515625,4096.0
+3,16,256,dense,256,4,27899146,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27245.259765625,4096.0
+3,16,1024,uniform,16,24,20733021,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3374.51513671875,540.9375
+3,16,1024,roots,16,2,58642974,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,114537.05859375,16384.0
+3,16,256,roots,4,4,21769853,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21259.6220703125,4096.0
+3,16,1024,dense,4,2,63265711,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,123565.841796875,14567.8125
+3,16,256,uniform,4,110,17831783,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,633.2309303977273,132.203125
+3,16,1024,roots,1,2,59387770,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,115991.73828125,16384.0
+3,16,256,dense,1,4,26625294,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26001.263671875,3642.171875
+3,16,256,uniform,64,124,19081356,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,601.1011844758065,162.25
+3,16,1024,roots,64,2,54379514,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,106209.98828125,16384.0
+3,16,256,roots,64,6,23421927,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,15248.650390625,4096.0
+3,16,1024,tail,64,384,18163616,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,184.76985677083334,64.0
+3,16,256,uniform,256,74,19326707,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1020.2020164695946,256.0
+3,16,256,tail,1,968,16443302,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,66.35500871642562,4.5546875
+3,16,256,uniform,16,130,18945597,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,569.2787560096153,137.9375
+3,16,256,tail,4,870,15606951,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,70.07431303879311,5.984375
+3,16,1024,uniform,4,22,21160558,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3757.201349431818,535.203125
+3,16,1024,tail,16,708,16127914,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,88.98257635946328,16.0
+3,16,1024,dense,1,2,56464457,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,110282.142578125,14544.31640625
+3,16,1024,dense,16,2,58168790,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,113610.91796875,14661.375
+3,16,1024,uniform,1,24,21266872,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3461.4049479166665,533.7734375
+3,16,1024,uniform,64,24,20355706,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3313.1031901041665,565.25
+3,16,1024,roots,1024,2,55149236,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,107713.3515625,16384.0
+3,16,256,dense,4,4,28735811,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28062.3154296875,3665.4375
+3,16,1024,dense,64,2,55532161,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108461.251953125,15004.25
+4,16,1024,roots,16,2,58275974,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,113820.26171875,16384.0
+4,16,1024,uniform,1,24,20898336,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3401.421875,533.7734375
+4,16,1024,tail,4,834,14866877,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,69.63277971372902,5.984375
+4,16,1024,tail,16,708,16058932,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,88.60198181497175,16.0
+4,16,1024,roots,64,2,54187366,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,105834.69921875,16384.0
+4,16,256,uniform,4,110,18060098,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,641.3387073863636,132.203125
+4,16,1024,uniform,4,22,21147503,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3754.8833451704545,535.203125
+4,16,256,roots,64,6,24374259,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,15868.658203125,4096.0
+4,16,1024,dense,4,2,63382933,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,123794.791015625,14567.8125
+4,16,256,dense,64,4,27028257,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26394.7822265625,3984.5
+4,16,1024,tail,64,384,18112820,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,184.25313313802084,64.0
+4,16,1024,uniform,1024,14,22717760,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6338.660714285715,1024.0
+4,16,1024,dense,1,2,56368123,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,110093.990234375,14544.31640625
+4,16,256,dense,16,4,27298090,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26658.291015625,3752.0
+4,16,256,tail,256,86,18729560,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,850.7249273255813,256.0
+4,16,256,tail,4,870,15490173,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,69.54998653017242,5.984375
+4,16,1024,dense,1024,2,59373955,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,115964.755859375,16384.0
+4,16,256,uniform,64,124,19073782,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,600.8625882056451,162.25
+4,16,256,roots,16,6,25373629,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16519.289713541668,4096.0
+4,16,1024,uniform,64,24,20210356,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3289.4459635416665,565.25
+4,16,256,uniform,256,74,19265226,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1016.9566089527027,256.0
+4,16,1024,uniform,16,24,20671781,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3364.5476888020835,540.9375
+4,16,1024,roots,1024,2,54991477,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,107405.228515625,16384.0
+4,16,256,dense,1,4,26646128,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26021.609375,3642.171875
+4,16,256,roots,1,6,27778090,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,18084.694010416668,4096.0
+4,16,256,tail,16,730,15578766,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,83.36240368150685,16.0
+4,16,1024,tail,1024,14,22511631,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6281.147042410715,1024.0
+4,16,256,dense,256,4,27817794,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27165.814453125,4096.0
+4,16,256,roots,256,6,23618612,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,15376.700520833334,4096.0
+4,16,1024,tail,1,912,15076693,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,64.57602196408992,4.5546875
+4,16,256,dense,4,4,28763201,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28089.0634765625,3665.4375
+4,16,256,uniform,16,130,18825430,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,565.66796875,137.9375
+4,16,256,uniform,1,130,19054708,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,572.5573317307692,130.7734375
+4,16,256,tail,1,968,16474654,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,66.48152602014463,4.5546875
+4,16,256,roots,4,4,21753002,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21243.166015625,4096.0
+4,16,1024,roots,4,2,65107229,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,127162.556640625,16384.0
+4,16,1024,roots,1,2,59380214,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,115976.98046875,16384.0
+4,16,1024,dense,64,2,55434866,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108271.22265625,15004.25
+4,16,1024,dense,16,2,58074048,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,113425.875,14661.375
+4,16,256,tail,64,384,18460486,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,187.7897745768229,64.0
+5,16,256,uniform,64,124,19329263,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,608.9107547883065,162.25
+5,16,1024,roots,16,2,57375679,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,112061.873046875,16384.0
+5,16,1024,tail,1024,14,22579761,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6300.156529017857,1024.0
+5,16,1024,tail,4,834,14960082,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,70.0693289118705,5.984375
+5,16,256,tail,1,968,16278580,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,65.69029248450413,4.5546875
+5,16,1024,dense,16,2,57445975,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,112199.169921875,14661.375
+5,16,1024,tail,64,384,18213134,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,185.2735799153646,64.0
+5,16,256,roots,1,6,27856293,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,18135.607421875,4096.0
+5,16,256,dense,64,4,27057813,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26423.6455078125,3984.5
+5,16,256,dense,1,4,26671387,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26046.2763671875,3642.171875
+5,16,256,uniform,16,130,18836911,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,566.0129507211539,137.9375
+5,16,1024,uniform,1,24,20823781,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3389.2872721354165,533.7734375
+5,16,256,tail,4,870,15190562,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,68.2047503591954,5.984375
+5,16,1024,tail,1,912,15649600,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,67.02987938596492,4.5546875
+5,16,256,roots,256,6,24620815,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,16029.176432291666,4096.0
+5,16,1024,dense,4,2,63311137,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,123654.564453125,14567.8125
+5,16,1024,uniform,4,22,21326706,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3786.702059659091,535.203125
+5,16,256,tail,256,86,19151578,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,869.8936228197674,256.0
+5,16,256,roots,4,4,22301428,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21778.73828125,4096.0
+5,16,256,dense,4,4,29056293,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28375.2861328125,3665.4375
+5,16,256,uniform,256,74,19565633,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1032.8142419763512,256.0
+5,16,256,uniform,4,110,18057894,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,641.2604403409091,132.203125
+5,16,1024,dense,1024,2,60140195,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,117461.318359375,16384.0
+5,16,1024,tail,16,708,16254099,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,89.67877714512711,16.0
+5,16,1024,dense,1,2,56663290,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,110670.48828125,14544.31640625
+5,16,256,dense,256,4,27836682,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27184.259765625,4096.0
+5,16,256,uniform,1,130,19151874,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,575.476983173077,130.7734375
+5,16,256,dense,16,4,27268739,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26629.6279296875,3752.0
+5,16,1024,roots,1024,2,55194940,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,107802.6171875,16384.0
+5,16,256,roots,64,6,24760574,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,16120.165364583334,4096.0
+5,16,1024,uniform,16,24,20702411,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3369.5330403645835,540.9375
+5,16,256,tail,16,730,15642655,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,83.70427547089041,16.0
+5,16,1024,roots,1,2,58483900,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,114226.3671875,16384.0
+5,16,1024,roots,64,2,54285033,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,106025.455078125,16384.0
+5,16,256,tail,64,384,18131930,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,184.4475301106771,64.0
+5,16,1024,uniform,1024,14,22782001,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6356.585100446428,1024.0
+5,16,1024,roots,4,2,70559817,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,137812.142578125,16384.0
+5,16,1024,uniform,64,24,20210762,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3289.5120442708335,565.25
+5,16,256,roots,16,6,25681295,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16719.593098958332,4096.0
+5,16,1024,dense,64,2,55456236,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108312.9609375,15004.25
+6,16,1024,roots,1024,2,54870791,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,107169.513671875,16384.0
+6,16,1024,uniform,16,24,20742114,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3375.9951171875,540.9375
+6,16,256,tail,16,730,15687340,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,83.94338613013699,16.0
+6,16,1024,dense,1024,2,59332807,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,115884.388671875,16384.0
+6,16,1024,uniform,64,24,20222374,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3291.4020182291665,565.25
+6,16,1024,roots,1,2,58901437,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,115041.869140625,16384.0
+6,16,1024,tail,64,384,18025357,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,183.36341349283853,64.0
+6,16,256,roots,256,6,25008240,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,16281.40625,4096.0
+6,16,1024,dense,4,2,63551748,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,124124.5078125,14567.8125
+6,16,1024,roots,64,2,56267698,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,109897.84765625,16384.0
+6,16,256,tail,256,86,18806949,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,854.2400526889535,256.0
+6,16,1024,roots,4,2,68814522,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,134403.36328125,16384.0
+6,16,256,dense,256,4,27934608,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27279.890625,4096.0
+6,16,256,tail,4,870,15578303,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,69.94568516522989,5.984375
+6,16,256,dense,4,4,28803219,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28128.1435546875,3665.4375
+6,16,1024,uniform,4,22,21089521,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3744.5882457386365,535.203125
+6,16,1024,tail,4,834,14739063,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,69.03413050809353,5.984375
+6,16,1024,uniform,1,24,20910965,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3403.4773763020835,533.7734375
+6,16,256,roots,4,4,22458464,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21932.09375,4096.0
+6,16,1024,dense,1,2,56255976,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,109874.953125,14544.31640625
+6,16,256,tail,64,384,18071820,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,183.8360595703125,64.0
+6,16,256,tail,1,968,15814117,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,63.81600674715909,4.5546875
+6,16,1024,roots,16,2,57245493,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,111807.603515625,16384.0
+6,16,1024,dense,16,2,57808882,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,112907.97265625,14661.375
+6,16,256,roots,64,6,25547351,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,16632.389973958332,4096.0
+6,16,1024,tail,16,708,15922932,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,87.85162870762711,16.0
+6,16,256,dense,64,4,27213979,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26576.1513671875,3984.5
+6,16,256,uniform,256,74,19487226,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1028.6753589527027,256.0
+6,16,1024,tail,1,912,16061655,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,68.79478053042763,4.5546875
+6,16,1024,dense,64,2,55728624,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108844.96875,15004.25
+6,16,256,uniform,4,110,17905042,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,635.8324573863637,132.203125
+6,16,256,dense,16,4,27274238,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26634.998046875,3752.0
+6,16,256,uniform,1,130,18982300,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,570.3816105769231,130.7734375
+6,16,256,uniform,64,124,19114171,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,602.1349231350806,162.25
+6,16,256,roots,1,6,29285699,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,19066.210286458332,4096.0
+6,16,256,dense,1,4,26745535,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26118.6865234375,3642.171875
+6,16,256,uniform,16,130,18815023,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,565.3552584134616,137.9375
+6,16,256,roots,16,6,24256649,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,15792.089192708334,4096.0
+6,16,1024,uniform,1024,14,22782186,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6356.63671875,1024.0
+6,16,1024,tail,1024,14,22543335,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6289.993024553572,1024.0
diff --git a/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/summary.csv b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/summary.csv
new file mode 100644
index 0000000..861c9d1
--- /dev/null
+++ b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/summary.csv
@@ -0,0 +1,41 @@
+chains,length,workload,block,median_ns_per_tick,min_ns_per_tick,max_ns_per_tick,core_owned_bytes,cache_bytes,evaluations_per_tick
+16,256,roots,1,18801.478515625,18084.694010416668,20032.295572916668,65848,32768,4096.0
+16,256,roots,4,21405.203125,20964.123046875,21932.09375,41272,8192,4096.0
+16,256,roots,16,16275.450520833334,15792.089192708334,16719.593098958332,35128,2048,4096.0
+16,256,roots,64,16120.165364583334,15248.650390625,16632.389973958332,33592,512,4096.0
+16,256,roots,256,16029.176432291666,14328.053385416666,16772.75,33208,128,4096.0
+16,256,uniform,1,574.3891526442308,570.3816105769231,576.8920372596153,65848,32768,130.7734375
+16,256,uniform,4,639.0146661931818,633.2309303977273,643.0563920454546,41272,8192,132.203125
+16,256,uniform,16,566.1882512019231,565.3552584134616,569.2787560096153,35128,2048,137.9375
+16,256,uniform,64,602.1349231350806,600.8625882056451,608.9107547883065,33592,512,162.25
+16,256,uniform,256,1020.9371304898649,1016.9566089527027,1032.8142419763512,33208,128,256.0
+16,256,tail,1,65.4934586454029,63.60011783316116,66.48152602014463,65848,32768,4.5546875
+16,256,tail,4,69.92689475574713,68.2047503591954,70.07431303879311,41272,8192,5.984375
+16,256,tail,16,83.94338613013699,83.27748287671233,85.78413420376712,35128,2048,16.0
+16,256,tail,64,184.586181640625,183.8360595703125,187.7897745768229,33592,512,64.0
+16,256,tail,256,856.3967114825581,850.7249273255813,869.8936228197674,33208,128,256.0
+16,256,dense,1,26021.880859375,25990.79296875,26118.6865234375,65848,32768,3642.171875
+16,256,dense,4,28089.0634765625,28053.1826171875,28375.2861328125,41272,8192,3665.4375
+16,256,dense,16,26632.0869140625,26573.638671875,26737.646484375,35128,2048,3752.0
+16,256,dense,64,26451.279296875,26394.7822265625,26613.9482421875,33592,512,3984.5
+16,256,dense,256,27236.0361328125,27165.814453125,27286.9072265625,33208,128,4096.0
+16,1024,roots,1,115259.642578125,114226.3671875,118340.623046875,262456,131072,16384.0
+16,1024,roots,4,136649.09375,127162.556640625,137812.142578125,164152,32768,16384.0
+16,1024,roots,16,112929.783203125,111807.603515625,114537.05859375,139576,8192,16384.0
+16,1024,roots,64,106209.98828125,105137.505859375,109897.84765625,133432,2048,16384.0
+16,1024,roots,1024,107713.3515625,106359.80078125,110034.27734375,131512,128,16384.0
+16,1024,uniform,1,3401.421875,3389.2872721354165,3461.4049479166665,262456,131072,533.7734375
+16,1024,uniform,4,3757.201349431818,3744.5882457386365,3956.7652698863635,164152,32768,535.203125
+16,1024,uniform,16,3374.51513671875,3358.8570963541665,3733.6276041666665,139576,8192,540.9375
+16,1024,uniform,64,3289.5120442708335,3284.544921875,3313.1031901041665,133432,2048,565.25
+16,1024,uniform,1024,6338.660714285715,6323.904017857143,6481.678013392857,131512,128,1024.0
+16,1024,tail,1,67.02987938596492,64.57602196408992,68.94516687225877,262456,131072,4.5546875
+16,1024,tail,4,69.63277971372902,68.53097365857315,70.94154676258992,164152,32768,5.984375
+16,1024,tail,16,88.98257635946328,86.80436197916667,89.67877714512711,139576,8192,16.0
+16,1024,tail,64,184.76985677083334,183.36341349283853,193.45831298828125,133432,2048,64.0
+16,1024,tail,1024,6295.3046875,6281.147042410715,7935.422154017857,131512,128,1024.0
+16,1024,dense,1,110093.990234375,109599.8515625,115644.2265625,262456,131072,14544.31640625
+16,1024,dense,4,123794.791015625,123565.841796875,124339.0625,164152,32768,14567.8125
+16,1024,dense,16,113425.875,111541.220703125,115264.88671875,139576,8192,14661.375
+16,1024,dense,64,108271.22265625,107769.125,108844.96875,133432,2048,15004.25
+16,1024,dense,1024,115971.736328125,115884.388671875,117461.318359375,131512,128,16384.0
diff --git a/research/experiments/001-checkpoint-granularity/run.py b/research/experiments/001-checkpoint-granularity/run.py
new file mode 100644
index 0000000..b2d66f2
--- /dev/null
+++ b/research/experiments/001-checkpoint-granularity/run.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python3
+"""Build, check, measure, and preserve raw data using only the Python stdlib."""
+import argparse
+import csv
+import hashlib
+import json
+import math
+import os
+from pathlib import Path
+import platform
+import random
+import shlex
+import statistics
+import subprocess
+import tempfile
+from datetime import datetime, timezone
+
+
+ROOT = Path(__file__).resolve().parent
+SOURCE = ROOT / "benchmark.c"
+FLAGS = ["-std=c17", "-O3", "-Wall", "-Wextra", "-Wpedantic", "-Werror"]
+
+
+def command(args):
+ return subprocess.check_output(args, text=True).strip()
+
+
+def write_csv(path, rows):
+ with path.open("w", newline="") as f:
+ writer = csv.DictWriter(f, fieldnames=list(rows[0]))
+ writer.writeheader()
+ writer.writerows(rows)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--output", type=Path)
+ parser.add_argument("--trials", type=int, default=7)
+ parser.add_argument("--target-ms", type=float, default=20.0)
+ parser.add_argument("--check-only", action="store_true")
+ args = parser.parse_args()
+ if args.trials < 3 or not 1 <= args.target_ms <= 1000:
+ parser.error("use at least 3 trials and a target from 1 to 1000 ms")
+ if not args.check_only and args.output is None:
+ parser.error("--output is required for measurements")
+ cc = shlex.split(os.environ.get("CC", "cc"))
+ environment = {
+ "started_utc": datetime.now(timezone.utc).isoformat(),
+ "platform": platform.platform(), "machine": platform.machine(),
+ "compiler": command(cc + ["--version"]), "flags": FLAGS,
+ "python": platform.python_version(),
+ "source_sha256": hashlib.sha256(SOURCE.read_bytes()).hexdigest(),
+ "runner_sha256": hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
+ "trials": args.trials, "target_ms": args.target_ms,
+ "seed": 20260922, "timing": "batch elapsed time / update ticks; not input latency",
+ "memory": "sizeof engine + requested live array bytes; excludes allocator, harness, code, OS",
+ "power_control": "not controlled; shared host; preliminary measurements",
+ }
+ # One CPU reduces migration noise. This is recorded, not assumed to remove noise.
+ if hasattr(os, "sched_getaffinity"):
+ affinity = sorted(os.sched_getaffinity(0))
+ environment["original_affinity"] = affinity
+ os.sched_setaffinity(0, {affinity[0]})
+ environment["measurement_affinity"] = sorted(os.sched_getaffinity(0))
+ cpuinfo = Path("/proc/cpuinfo")
+ if cpuinfo.exists():
+ allowed = ("model name", "CPU implementer", "CPU architecture", "CPU part", "Model")
+ environment["cpu_description"] = sorted({
+ line for line in cpuinfo.read_text().splitlines()
+ if line.split(":", 1)[0].strip() in allowed
+ })
+ with tempfile.TemporaryDirectory(prefix="pure-checkpoints-") as tmp:
+ binary = Path(tmp) / "benchmark"
+ subprocess.run(cc + FLAGS + [str(SOURCE), "-o", str(binary)], check=True)
+ environment["release_check"] = json.loads(command([str(binary), "--check"]))
+ checked = Path(tmp) / "benchmark-checked"
+ check_flags = ["-std=c17", "-O1", "-g", "-Wall", "-Wextra", "-Wpedantic", "-Werror",
+ "-fsanitize=address,undefined", "-fno-omit-frame-pointer"]
+ subprocess.run(cc + check_flags + [str(SOURCE), "-o", str(checked)], check=True)
+ environment["sanitizer_check"] = json.loads(command([str(checked), "--check"]))
+ print("Differential checks passed in release and ASan/UBSan builds.", flush=True)
+ if args.check_only:
+ print(json.dumps(environment, indent=2))
+ return
+ # Fail before measurements if a previous run would be overwritten.
+ args.output.mkdir(parents=True, exist_ok=False)
+
+ cases = []
+ for chains, length in [(16, 256), (16, 1024)]:
+ for workload in ["roots", "uniform", "tail", "dense"]:
+ for block in [1, 4, 16, 64, length]:
+ cases.append((chains, length, workload, block))
+
+ def sample(case, replays):
+ chains, length, workload, block = case
+ return json.loads(command([str(binary), str(chains), str(length), str(block),
+ workload, "256", str(replays), str(environment["seed"])]))
+
+ calibration = {}
+ for case in cases:
+ pilot = sample(case, 2)
+ wanted = math.ceil(2 * args.target_ms * 1e6 / max(1, pilot["elapsed_ns"]))
+ # Even replay counts leave the same final model in every strategy.
+ calibration[case] = min(2048, max(2, wanted + wanted % 2))
+ environment["calibration_replays"] = [
+ {"chains": c[0], "length": c[1], "workload": c[2], "block": c[3], "replays": r}
+ for c, r in calibration.items()
+ ]
+ rows = []
+ checksums = {}
+ rng = random.Random(81173)
+ for trial in range(args.trials):
+ order = cases.copy()
+ rng.shuffle(order)
+ for case in order:
+ result = sample(case, calibration[case])
+ chains, length, workload, block = case
+ key = (chains, length, workload)
+ if checksums.setdefault(key, result["checksum"]) != result["checksum"]:
+ raise RuntimeError(f"cross-strategy output mismatch: {case}")
+ row = {"trial": trial, "chains": chains, "length": length,
+ "workload": workload, "block": block, "replays": calibration[case],
+ **result}
+ row["ns_per_tick"] = result["elapsed_ns"] / result["ticks"]
+ row["evaluations_per_tick"] = result["node_evaluations"] / result["ticks"]
+ rows.append(row)
+ write_csv(args.output / "raw.csv", rows)
+ print(f"Completed trial {trial + 1}/{args.trials}.", flush=True)
+ summary = []
+ for case in cases:
+ chains, length, workload, block = case
+ group = [r for r in rows if (r["chains"], r["length"], r["workload"], r["block"]) == case]
+ times = [r["ns_per_tick"] for r in group]
+ summary.append({"chains": chains, "length": length, "workload": workload, "block": block,
+ "median_ns_per_tick": statistics.median(times),
+ "min_ns_per_tick": min(times), "max_ns_per_tick": max(times),
+ "core_owned_bytes": group[0]["core_owned_bytes"],
+ "cache_bytes": group[0]["cache_bytes"],
+ "evaluations_per_tick": group[0]["evaluations_per_tick"]})
+ write_csv(args.output / "summary.csv", summary)
+ environment["completed_utc"] = datetime.now(timezone.utc).isoformat()
+ environment["binary_bytes"] = binary.stat().st_size
+ (args.output / "environment.json").write_text(json.dumps(environment, indent=2) + "\n")
+ print(f"Saved raw data, summary, and environment to {args.output}")
+
+
+if __name__ == "__main__":
+ main()