aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--benchmarks/http/README.md4
-rw-r--r--benchmarks/http/run.py47
2 files changed, 40 insertions, 11 deletions
diff --git a/benchmarks/http/README.md b/benchmarks/http/README.md
index 94b228b..3abd431 100644
--- a/benchmarks/http/README.md
+++ b/benchmarks/http/README.md
@@ -31,3 +31,7 @@ aup build scores.aup -o scores.pmod
python3 run.py --module scores.pmod --suite app --rounds 3 --seconds 4 \
--only pure-serve,pure-serve-2,axum-memory,axum-durable,drogon-memory,drogon-durable
```
+
+앱 벤치마크의 마지막 작업(`mixed`)은 내구성 점수 POST 8연결과 합계 GET 56연결을 부하 생성기 둘로 함께 보내, 쓰기가
+동기화하는 동안 읽기가 기다리는지 본다. 두 행(posts, reads)으로
+나오고, CPU 1초당 답은 두 행을 합친 것이다.
diff --git a/benchmarks/http/run.py b/benchmarks/http/run.py
index 7c5ab98..bad9cc4 100644
--- a/benchmarks/http/run.py
+++ b/benchmarks/http/run.py
@@ -107,12 +107,28 @@ def probe_ms(directory, count=16):
return round(statistics.median(times), 2)
+def load_command(port, connections, seconds, method, keys, mode, body=16):
+ return ['taskset', '-c', '3', str(HERE / 'load'), str(port), str(connections), str(seconds), method, str(keys),
+ mode, str(body)]
+
+
def load(port, connections, seconds, method, keys, mode, body=16):
- output = subprocess.run(['taskset', '-c', '3', str(HERE / 'load'), str(port), str(connections), str(seconds),
- method, str(keys), mode, str(body)], capture_output=True, text=True, check=True)
+ output = subprocess.run(load_command(port, connections, seconds, method, keys, mode, body), capture_output=True,
+ text=True, check=True)
return json.loads(output.stdout)
+def mixed(port, seconds, writers, readers):
+ """Durable posts and reads of the total at once, from two load processes:
+ whether reads wait while writes sync."""
+ writing = subprocess.Popen(load_command(port, writers, seconds, 'score', writers, 'keep-alive'),
+ stdout=subprocess.PIPE, text=True)
+ reads = load(port, readers, seconds, 'total', readers, 'keep-alive')
+ writes = json.loads(writing.communicate()[0])
+ assert writing.returncode == 0
+ return writes, reads
+
+
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--module', type=Path, required=True, help='editor.pmod built by aup, or scores.pmod for --suite app')
@@ -159,6 +175,9 @@ def main():
('score, 8 conn, keep-alive', dict(connections=8, method='score', keys=8, mode='keep-alive', writes=True)),
('total, 64 conn, keep-alive', dict(connections=64, method='total', keys=64, mode='keep-alive')),
('page 20 rows, 64 conn, keep-alive', dict(connections=64, method='page', keys=64, mode='keep-alive')),
+ # Reported as two rows: the posts, and the reads made meanwhile.
+ ('mixed, 8 score + 56 total conn', dict(connections=64, method='mixed', keys=64, mode='keep-alive',
+ writes=True)),
]
for name in ('pure-program', 'axum-atomic', 'drogon-atomic'):
del servers[name] # atomic is durable for a log already
@@ -184,15 +203,21 @@ def main():
put(port, 'k0', b'B' * (1 << 20), 1)
probe = probe_ms(base) if workload['method'] == 'put' or workload.get('writes') else None
used = cpu_seconds(process.pid)
- measured = load(port, workload['connections'], args.seconds, workload['method'],
- workload['keys'], workload['mode'])
+ if workload['method'] == 'mixed':
+ writes, reads = mixed(port, args.seconds, 8, 56)
+ parts = [(f'{label}: posts', writes), (f'{label}: reads', reads)]
+ else:
+ parts = [(label, load(port, workload['connections'], args.seconds, workload['method'],
+ workload['keys'], workload['mode']))]
used = cpu_seconds(process.pid) - used
- measured.update(server=name, workload=label, round=round_, probe_ms=probe,
- rss_kib=rss_kib(process.pid, 'VmRSS:'), cpu_seconds=round(used, 2),
- ok_per_cpu_second=round(measured['2xx'] / used) if used else 0,
- ok_per_second=round(measured['2xx'] / args.seconds), idle_rss_kib=idle)
- results.append(measured)
- print(json.dumps(measured), flush=True)
+ answered = sum(measured['2xx'] for _, measured in parts) # per CPU second: all parts together
+ for part, measured in parts:
+ measured.update(server=name, workload=part, round=round_, probe_ms=probe,
+ rss_kib=rss_kib(process.pid, 'VmRSS:'), cpu_seconds=round(used, 2),
+ ok_per_cpu_second=round(answered / used) if used else 0,
+ ok_per_second=round(measured['2xx'] / args.seconds), idle_rss_kib=idle)
+ results.append(measured)
+ print(json.dumps(measured), flush=True)
peak = rss_kib(process.pid, 'VmHWM:')
process.send_signal(signal.SIGINT if name.startswith('axum') else signal.SIGTERM)
process.communicate(timeout=30)
@@ -207,7 +232,7 @@ def main():
print(f"medians over {args.rounds} round(s)")
print(f"{'workload':32s} {'server':14s} {'2xx/s':>9s} {'2xx/cpu-s':>10s} {'p50 us':>8s} {'p99 us':>8s} "
f"{'errors':>7s} {'non-2xx':>8s} {'probe ms':>9s}")
- for label, _ in workloads:
+ for label in dict.fromkeys(r['workload'] for r in results):
for name in chosen:
rows = [r for r in results if r['server'] == name and r['workload'] == label]
if not rows: