diff options
| author | eunhhu <[email protected]> | 2026-09-30 03:42:36 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-30 03:42:36 +0100 |
| commit | 6b3b1c64328fb6b4932dfb67fd05486182657673 (patch) | |
| tree | d81bd1e3bda734c88965aa0d002cdadbaa6496ab /research/experiments/021-memory/run.py | |
| parent | d9e0b6870201d9200b3c225903b43b850475600b (diff) | |
| download | pure-6b3b1c64328fb6b4932dfb67fd05486182657673.tar.gz pure-6b3b1c64328fb6b4932dfb67fd05486182657673.zip | |
Say what the windows and checkpoints cost (013 steps 2 and 3, 104)
013's second step is in (d9e0b68): each transport holds a window of its
output's sends. 104 measures it with the receivers down: once the window
is full a node grows by the outbox alone, 219 and 218 B a send over the
link and HTTP (399 and 534 B before).
The third step is a measurement. A checkpoint holds one list's snapshot
while it writes the image, so what it adds is what the app changed
meanwhile: nothing visible on tmpfs or for a list that fits the card's
fast writes; on the SD card, a 22.4 MB list written for about 8 s while
1,400 items a second were set left +3.0 and +4.4 MiB. The highest
resident memory was twice the state bytes, inside 013's bound (the state
and one snapshot) and its stop criterion (3x).
021's run.py takes --items, --stores (a directory on the device to
measure) and --label, and reports the peak (VmHWM).
Diffstat (limited to 'research/experiments/021-memory/run.py')
| -rw-r--r-- | research/experiments/021-memory/run.py | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/research/experiments/021-memory/run.py b/research/experiments/021-memory/run.py index 49bb5a9..546bfbc 100644 --- a/research/experiments/021-memory/run.py +++ b/research/experiments/021-memory/run.py @@ -15,7 +15,12 @@ size at the end. unheld the same, no surface python3 research/experiments/021-memory/run.py [--seconds 30] [--cases outbox,budget,held] [--out FILE] - [--label NAME] + [--label NAME] [--items 20000] [--stores DIRECTORY] + +--items sets how many items held and unheld begin with; --stores puts the +stores in a directory of the device to measure (a flash card: checkpoints +then take long, and a snapshot is held that long). Each row gives the peak +resident memory too (VmHWM). PURE_SERVE=PATH runs another build's pure-serve (--label names it in the rows). """ @@ -87,10 +92,10 @@ def start(args): return process, json.loads(line)['port'] -def rss_kib(pid): +def rss_kib(pid, field='VmRSS:'): with open(f'/proc/{pid}/status') as status: for line in status: - if line.startswith('VmRSS:'): + if line.startswith(field): return int(line.split()[1]) return 0 @@ -121,8 +126,8 @@ def post_all(port, bodies, stop, counts, index, refused): connection.close() -def run_case(case, work, seconds, clients=4): - store = work / f'store-{case}' +def run_case(case, work, seconds, clients=4, stores=None): + store = (stores or work) / f'store-{case}-{os.getpid()}' args = [SERVE, '--store', store, '--threads', '2'] note = 'n' * NOTE if case in ('outbox', 'budget', 'link-down', 'wire-down'): @@ -183,31 +188,35 @@ def run_case(case, work, seconds, clients=4): stop.set() for t in threads: t.join() - rss_end = rss_kib(process.pid) + rss_end, rss_peak = rss_kib(process.pid), rss_kib(process.pid, 'VmHWM:') finally: process.send_signal(signal.SIGTERM) _, error = process.communicate(timeout=60) stats = [json.loads(line) for line in error.decode().splitlines() if line.startswith('{"active"')] posted = sum(counts) return {'case': case, 'seconds': seconds, 'posted': posted, 'refused': sum(refused), 'rss_began_kib': rss_began, - 'rss_end_kib': rss_end, + 'rss_end_kib': rss_end, 'rss_peak_kib': rss_peak, 'items': SEEDED, 'rss_per_post_bytes': round((rss_end - rss_began) * 1024 / posted, 1) if posted else None, 'store_bytes': store_bytes(store), 'samples': samples[::4] + [samples[-1]], 'stats': stats[-1] if stats else None} def main(): + global SEEDED parser = argparse.ArgumentParser() parser.add_argument('--seconds', type=int, default=30) parser.add_argument('--cases', default='outbox,budget,link-down,wire-down,unheld,held') parser.add_argument('--out', type=Path, default=None) parser.add_argument('--label', default=None, help='the build, named in each row') + parser.add_argument('--items', type=int, default=SEEDED) + parser.add_argument('--stores', type=Path, default=None) args = parser.parse_args() + SEEDED = args.items with tempfile.TemporaryDirectory(prefix='pure-memory-') as directory: work = Path(directory) build(work) for case in args.cases.split(','): - row = run_case(case, work, args.seconds) + row = run_case(case, work, args.seconds, stores=args.stores) if args.label: row = {'label': args.label, **row} line = json.dumps(row) |
