#!/usr/bin/env python3 """HTTP benchmarks: Pure's document servers against an axum service with the same contract, on the same machine, with the same load generator. Servers are pinned to CPUs 0-2 and the load to CPU 3; stores live under --directory (use the device you care about: fsync costs are the device's). Prints one JSON object per (server, workload) and a summary table. """ import argparse import json import os import select import shutil import signal import struct import subprocess import sys import tempfile import time import http.client from pathlib import Path HERE = Path(__file__).resolve().parent PURE = HERE.parent.parent / 'prototypes' / 'connections' def start(args): process = subprocess.Popen(['taskset', '-c', '0-2'] + [str(a) for a in args], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ready, _, _ = select.select([process.stdout], [], [], 20) assert ready, 'server did not start' port = json.loads(process.stdout.readline())['port'] return process, port def rss_kib(pid, field): for line in Path(f'/proc/{pid}/status').read_text().splitlines(): if line.startswith(field): return int(line.split()[1]) return 0 def put(port, key, body, expected): connection = http.client.HTTPConnection('127.0.0.1', port, timeout=30) headers = {'Content-Length': str(len(body) + 8)} headers['If-None-Match' if expected == 0 else 'If-Match'] = '*' if expected == 0 else f'"{expected}"' connection.request('PUT', f'/objects/{key}', struct.pack('9s} {'p50 us':>8s} {'p99 us':>8s} {'errors':>7s} {'non-2xx':>8s}") for r in results: print(f"{r['workload']:32s} {r['server']:14s} {r['ok_per_second']:9d} {r['p50_us']:8d} {r['p99_us']:8d} " f"{r['errors']:7d} {r['4xx'] + r['5xx']:8d}") print() for name in servers: rows = [r for r in results if r['server'] == name] if rows: print(f"{name:14s} idle RSS {rows[0]['idle_rss_kib']} KiB, peak RSS {rows[0]['peak_rss_kib']} KiB") if __name__ == '__main__': sys.exit(main())