diff options
| author | eunhhu <[email protected]> | 2026-10-04 11:07:55 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-04 11:07:55 +0100 |
| commit | 52e51e4231f2e119c97826ae6d6e2f2af0da0c58 (patch) | |
| tree | 0f17ced79a1881bd2b67fbaa9e7ffb823f54b984 /research/experiments/030-app-lifecycle/isolation.py | |
| parent | 420b749742badd26daf2474e9f157af17be2907f (diff) | |
| download | pure-52e51e4231f2e119c97826ae6d6e2f2af0da0c58.tar.gz pure-52e51e4231f2e119c97826ae6d6e2f2af0da0c58.zip | |
Say what apps that change on a running host showed (017 stage 3, research 115)
Changing an app in place keeps a million items' app answering but for
1.12 ms (a host restart: 150 ms; stopping and starting it again from its
store, as first built, 150.4 ms), 171.5 ms when its records change shape
(332 ms). Another app's p99 stays 0.97 times as it was while one changes
every 0.2 s; a host of one app is as it was (TPC-C +0.7%, instructions
at most +0.02%); each module change leaves 19 KB. 030 holds the windows
of both builds, the isolation, the pairs, the counts and the memory.
Diffstat (limited to 'research/experiments/030-app-lifecycle/isolation.py')
| -rw-r--r-- | research/experiments/030-app-lifecycle/isolation.py | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/research/experiments/030-app-lifecycle/isolation.py b/research/experiments/030-app-lifecycle/isolation.py new file mode 100644 index 0000000..43259f4 --- /dev/null +++ b/research/experiments/030-app-lifecycle/isolation.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""Another app's latency while one app changes again and again on a running +host (docs/design/017's stage 3, research 115). + +A host of apps (two connection threads, two workers, stores in RAM, cores +0-2) holds A, an app of items.aup with ITEMS items, and B, the scoreboard +(benchmarks/http/scores.aup). B takes one connection's scores +(benchmarks/http/load on core 3) for SECONDS, while A is left be (quiet) +or changes every EVERY seconds (changing: SIGHUP, its line naming in turn +items.pmod and NEXT). The two take turns, their order turned each round. + +isolation.py PURE_SERVE ITEMS NEXT EVERY SECONDS ROUNDS a JSON line per run, + then one with medians +""" +import json +import select +import shutil +import signal +import statistics +import subprocess +import sys +import tempfile +import threading +import time +from pathlib import Path + +from window import AUP, HERE, grow + +ROOT = HERE.parents[2] +LOAD = ROOT / 'benchmarks' / 'http' / 'load' + + +def main(): + serve, items, after = Path(sys.argv[1]).resolve(), int(sys.argv[2]), sys.argv[3] + every, seconds, rounds = float(sys.argv[4]), int(sys.argv[5]), int(sys.argv[6]) + work = Path(tempfile.mkdtemp(prefix='pure-030-', dir='/dev/shm')) + try: + modules = {} + for name, source in (('items', HERE / 'items.aup'), (after, HERE / f'{after}.aup'), + ('scores', ROOT / 'benchmarks' / 'http' / 'scores.aup')): + modules[name] = work / f'{name}.pmod' + subprocess.run([str(AUP), 'build', str(source), '-o', str(modules[name])], check=True) + conf = work / 'apps.conf' + + def write(module): + conf.write_text(f"a {modules[module]} {work / 'a'}\nb {modules['scores']} {work / 'b'}\n") + + write('items') + host = subprocess.Popen(['taskset', '-c', '0-2', str(serve), '--apps', str(conf), '--port', '0', '--threads', '2', + '--workers', '2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + port = json.loads(host.stdout.readline())['port'] + count = grow(port, items, 'a') + p99 = {'quiet': [], 'changing': []} + changes = 0 + for round_ in range(1, rounds + 1): + for way in (['quiet', 'changing'] if round_ % 2 else ['changing', 'quiet']): + load = subprocess.Popen(['taskset', '-c', '3', str(LOAD), str(port), '1', str(seconds), 'score', '1', + 'keep-alive', '16', '/b'], stdout=subprocess.PIPE, text=True) + made = 0 + while way == 'changing' and load.poll() is None: + write(after if changes % 2 == 0 else 'items') + host.send_signal(signal.SIGHUP) + ready, _, _ = select.select([host.stdout], [], [], 60) + assert ready + said = json.loads(host.stdout.readline()) + assert said['apps'][0]['running'], said + changes += 1 + made += 1 + time.sleep(every) + out, _ = load.communicate() + result = json.loads(out) + assert result['5xx'] == 0 and result['errors'] == 0, result + p99[way].append(result['p99_us']) + print(json.dumps({'round': round_, 'way': way, 'items': count, 'next': after, 'changes': made, **result}), + flush=True) + host.terminate() + host.communicate(timeout=600) + quiet, changing = statistics.median(p99['quiet']), statistics.median(p99['changing']) + print(json.dumps({'items': count, 'next': after, 'every_s': every, 'quiet_p99_us': quiet, + 'changing_p99_us': changing, 'ratio': round(changing / quiet, 2)}), flush=True) + finally: + shutil.rmtree(work) + + +if __name__ == '__main__': + main() |
