From b1ce1927022d374198441afafeb27199fc8a052a Mon Sep 17 00:00:00 2001 From: eunhhu Date: Thu, 24 Sep 2026 17:14:54 +0100 Subject: Establish native micro runtime checkpoint --- .../005-storage-edit-latency/sequence.py | 85 ++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 research/experiments/005-storage-edit-latency/sequence.py (limited to 'research/experiments/005-storage-edit-latency/sequence.py') diff --git a/research/experiments/005-storage-edit-latency/sequence.py b/research/experiments/005-storage-edit-latency/sequence.py new file mode 100644 index 0000000..57ff835 --- /dev/null +++ b/research/experiments/005-storage-edit-latency/sequence.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +"""Measure repeated durable edits and page-segment rebuilds on one real document.""" +import argparse +import hashlib +import json +from pathlib import Path +import platform +import statistics +import subprocess +import tempfile + +from measure import INITIAL, PROGRAM, invoke + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--flat', type=Path, required=True) + parser.add_argument('--paged', type=Path, required=True) + parser.add_argument('--scratch-parent', type=Path, required=True) + parser.add_argument('--edits', type=int, default=70) + parser.add_argument('--output', type=Path, required=True) + args = parser.parse_args() + if args.edits < 66 or args.output.exists(): + parser.error('at least 66 edits are needed to observe the current rebuild boundary; output must be new') + binaries = {'flat': args.flat.resolve(), 'paged': args.paged.resolve()} + args.scratch_parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory(prefix='pure-storage-sequence-', + dir=args.scratch_parent.resolve()) as name: + root = Path(name) + filesystem = subprocess.run(['findmnt', '-T', str(root), '-no', 'FSTYPE,SOURCE'], + capture_output=True, text=True, check=True).stdout.strip() + (root / 'initial').write_bytes(INITIAL) + patches = {'Y': root / 'Y', 'Z': root / 'Z'} + for label, file in patches.items(): + file.write_bytes(label.encode()) + bases = {variant: [binary, '--program', PROGRAM, '--store', root / variant] + for variant, binary in binaries.items()} + for base in bases.values(): + result, _ = invoke([*base, 'edit', 'document', 0, 0, 0, root / 'initial']) + assert json.loads(result.stdout)['revision'] == '1' + samples = {variant: [] for variant in binaries} + for edit in range(1, args.edits + 1): + patch = 'Z' if edit % 2 else 'Y' + order = ('flat', 'paged') if edit % 2 else ('paged', 'flat') + for variant in order: + base = bases[variant] + result, elapsed = invoke([*base, 'edit', 'document', edit, + len(INITIAL) - 1, 1, patches[patch]]) + assert json.loads(result.stdout)['revision'] == str(edit + 1) + files = [file for file in (root / variant).iterdir() if file.is_file()] + samples[variant].append({'edit': edit, 'elapsed_ms': round(elapsed, 3), + 'files': len(files), + 'allocated_bytes': sum(file.stat().st_blocks * 512 + for file in files)}) + expected = INITIAL[:-1] + patches[patch].read_bytes() + for base in bases.values(): + shown, _ = invoke([*base, 'show', 'document']) + assert shown.stdout == expected + assert json.loads(shown.stderr)['revision'] == str(args.edits + 1) + result = {'profile': 'repeated-durable-one-mib-document-last-byte-edit', + 'platform': platform.platform(), 'filesystem': filesystem, + 'edits_per_variant': args.edits, + 'final_body_sha256': hashlib.sha256(expected).hexdigest(), + 'scope': ('Same actual source-loaded CLI and editor.pure, two persistent ' + 'stores, alternating operation order. Timings include each ' + 'edit process, parser, store init and fsync; creation and ' + 'final show are not timed. Device state is uncontrolled.'), + 'variants': {variant: { + 'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest(), + 'median_edit_ms': round(statistics.median(row['elapsed_ms'] + for row in samples[variant]), 3), + 'samples': samples[variant]} + for variant, binary in binaries.items()}} + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(result, indent=2) + '\n') + print(json.dumps({variant: {'median_edit_ms': row['median_edit_ms'], + 'max_edit_ms': max(sample['elapsed_ms'] + for sample in row['samples']), + 'max_allocated_bytes': max(sample['allocated_bytes'] + for sample in row['samples'])} + for variant, row in result['variants'].items()}, indent=2)) + + +if __name__ == '__main__': + main() -- cgit v1.2.3