From 65386f68fb53e5a9a20a284b06afd872172c30eb Mon Sep 17 00:00:00 2001 From: eunhhu Date: Fri, 25 Sep 2026 09:34:34 +0100 Subject: Let the runtime own working versions as drafts state.h gives any app a runtime-owned working version of a stored value on the tree store. A draft shares unchanged extents with the stored version, edits in memory by path copying, lends ordered extents without copying, and commits only its new nodes when the key is still at its base revision. A failed commit changes neither the draft nor the store; a draft whose file was replaced by compaction copies its stored extents on commit. Unreachable arena nodes are reclaimed once they outweigh max(reachable, 32 KiB). Typing into the middle of a 1 MiB document and saving each character peaked at about 1,660 KiB RSS with a draft against about 4,480 KiB for an app copy compared with storage on save; saves were only 1-2 ms faster. This corrects 073, which had attributed the TUI's remaining 8 ms to that comparison. Drafts are not yet charged to the runtime budget or visible to .pure definitions. --- research/experiments/009-runtime-drafts/run.py | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100755 research/experiments/009-runtime-drafts/run.py (limited to 'research/experiments/009-runtime-drafts/run.py') diff --git a/research/experiments/009-runtime-drafts/run.py b/research/experiments/009-runtime-drafts/run.py new file mode 100755 index 0000000..08ed55d --- /dev/null +++ b/research/experiments/009-runtime-drafts/run.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Run bench.c in copy and draft modes on a real device, alternating order.""" +import argparse +import json +import platform +import shutil +import subprocess +from pathlib import Path + +HERE = Path(__file__).resolve().parent +CONNECTIONS = HERE.parents[2] / 'prototypes' / 'connections' + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--work', type=Path, default=CONNECTIONS / 'build' / 'bench-drafts') + parser.add_argument('--size', type=int, default=1048576) + parser.add_argument('--saves', type=int, default=24) + parser.add_argument('--rounds', type=int, default=3) + parser.add_argument('--output', type=Path) + args = parser.parse_args() + shutil.rmtree(args.work, ignore_errors=True) + args.work.mkdir(parents=True) + device = subprocess.check_output(['findmnt', '-n', '-T', str(args.work), '-o', 'SOURCE,FSTYPE'], text=True).split() + assert device[1] != 'tmpfs', 'fsync is free on tmpfs' + binary = args.work / 'bench' + subprocess.run(['cc', '-std=c17', '-O2', '-Wall', '-Wextra', '-Werror', f'-I{CONNECTIONS}', + str(HERE / 'bench.c'), str(CONNECTIONS / 'store-tree.c'), '-o', str(binary)], check=True) + runs = [] + for round_number in range(args.rounds): + for mode in (('copy', 'draft') if round_number % 2 == 0 else ('draft', 'copy')): + directory = args.work / f'{mode}-{round_number}' + subprocess.run([str(binary), 'create', str(directory), str(args.size), '0'], check=True) + line = subprocess.check_output([str(binary), mode, str(directory), str(args.size), str(args.saves)], text=True) + runs.append(json.loads(line)) + print(line.strip(), flush=True) + shutil.rmtree(directory) + report = {'device': device[0], 'filesystem': device[1], 'machine': platform.machine(), + 'kernel': platform.release(), 'store': 'store-tree.c', 'runs': runs} + if args.output: + args.output.write_text(json.dumps(report, indent=2) + '\n') + + +if __name__ == '__main__': + main() -- cgit v1.2.3