"""Summarise one perftest run: latency, errors, throughput and CPU per pod.""" import csv, json, os, sys from collections import defaultdict run = sys.argv[1]; d = os.path.expanduser(f"~/.cache/perftest/results/{run}") s = json.load(open(f"{d}/summary.json"))["metrics"] pt, fl, rq = s["page_time"], s["page_failures"], s["http_reqs"] print(f"== {run}") print(f"page p50 {pt['med']:.0f} ms p95 {pt['p(95)']:.0f} ms p99 {pt['p(99)']:.0f} ms max {pt['max']:.0f} ms | " f"failures {fl['value']*100:.2f}% | {rq['rate']:.1f} req/s overall | actions {s.get('user_actions',{}).get('count')}") h, hf = s.get("page_time{phase:hold}"), s.get("page_failures{phase:hold}") if h: print(f" HOLD PHASE (all 500 signed in): p50 {h['med']:.0f} ms p90 {h['p(90)']:.0f} ms p95 {h['p(95)']:.0f} ms p99 {h['p(99)']:.0f} ms max {h['max']:.0f} ms | failures {hf['value']*100:.2f}% | {s['http_reqs{phase:hold}']['count']/(270 if "rush" not in run else 270):.1f} req/s (hold window)") for k, v in sorted(s.items()): if k.startswith("page_time{name:"): print(f" {k[15:-1]:32s} p50 {v['med']:6.0f} p95 {v['p(95)']:6.0f} max {v['max']:6.0f} ms") rows = defaultdict(list) for r in csv.DictReader(open(f"{d}/cpu.csv")): try: rows[r["pod"]].append((int(r["t"]), int(r["usage_usec"]), int(r["mem_bytes"]))) except (ValueError, TypeError): pass for pod, pts in sorted(rows.items()): pts.sort(); rates = [(b[1]-a[1])/1e6/(b[0]-a[0]) for a, b in zip(pts, pts[1:]) if b[0] > a[0]] hold = rates[len(rates)//3:] or rates # skip the ramp if rates: print(f" cpu {pod[:40]:40s} hold-avg {sum(hold)/len(hold):.2f} cores peak {max(rates):.2f} mem peak {max(p[2] for p in pts)/2**20:.0f} MiB") print(" " + open(f"{d}/pods.txt").read().replace("\n", "\n ")) try: vals=[int(l.split(",")[1]) for l in open(f"{d}/node.csv").read().splitlines()[1:]] hold=vals[len(vals)//2:] or vals print(f" node homeserver-02 busy: hold-avg {sum(hold)/len(hold):.0f}% peak {max(vals)}% of 8 threads") except FileNotFoundError: pass