import csv
import json
import sys
def load_datum(path):
rows = {}
with open(path, newline="") as handle:
reader = csv.DictReader(handle, delimiter="\t")
for row in reader:
cpu_ns = row.get("cpu_ns_per_op")
rows[row["scenario"]] = {
"us": float(row["ns_per_op"]) / 1_000.0,
"cpu_us": float(cpu_ns) / 1_000.0 if cpu_ns and float(cpu_ns) > 0.0 else None,
"alloc": float(row["allocated_bytes_per_op"]),
}
return rows
def load_akka(path):
with open(path) as handle:
data = json.load(handle)
rows = {}
for item in data:
scenario = item["benchmark"].split(".")[-1]
alloc_metric = item.get("secondaryMetrics", {}).get("gc.alloc.rate.norm")
rows[scenario] = {
"us": float(item["primaryMetric"]["score"]),
"alloc": float(alloc_metric["score"]) if alloc_metric else None,
}
return rows
def fmt(value, suffix=""):
if value is None:
return "n/a"
if value >= 100:
return f"{value:,.0f}{suffix}"
if value >= 10:
return f"{value:,.1f}{suffix}"
return f"{value:,.2f}{suffix}"
def main():
if len(sys.argv) != 3:
raise SystemExit("usage: render_table.py <datum.tsv> <akka-jmh.json>")
datum = load_datum(sys.argv[1])
akka = load_akka(sys.argv[2])
print(
"| Scenario | Datum us/op | Datum CPU us/op | Akka us/op | Speedup | "
"Datum alloc B/op | Akka alloc B/op | Alloc ratio |"
)
print("| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |")
for scenario in datum:
if scenario not in akka:
continue
datum_us = datum[scenario]["us"]
datum_cpu = datum[scenario].get("cpu_us")
akka_us = akka[scenario]["us"]
datum_alloc = datum[scenario]["alloc"]
akka_alloc = akka[scenario]["alloc"]
speedup = akka_us / datum_us if datum_us else None
alloc_ratio = akka_alloc / datum_alloc if datum_alloc and akka_alloc is not None else None
print(
f"| `{scenario}` | {fmt(datum_us)} | {fmt(datum_cpu)} | {fmt(akka_us)} | "
f"{fmt(speedup, 'x')} | {fmt(datum_alloc)} | {fmt(akka_alloc)} | {fmt(alloc_ratio, 'x')} |"
)
if __name__ == "__main__":
main()