#!/usr/bin/env python3 """Tabulate concurrent_read JSON results (clawhdf5, h5py threads/processes). python compare_concurrent_read.py clawhdf5.json h5py-threads.json h5py-procs.json Prints one Markdown table: for each layout, mode and thread count, every tool's MB/s and scaling efficiency, and the first file's MB/s relative to each of the others. Refuses to compare runs whose workload parameters differ. """ import json import sys COMPARED = ("datasets", "rows", "cols", "chunk", "deflate_level", "slab", "slabs", "seed") def main(paths): if len(paths) < 2: sys.exit(__doc__) docs = [] for p in paths: with open(p) as fh: docs.append(json.load(fh)) ref = docs[0] for d, p in zip(docs[1:], paths[1:]): diff = [k for k in COMPARED if d["params"].get(k) != ref["params"].get(k)] if diff: sys.exit(f"{p}: workload differs from {paths[0]} in {', '.join(diff)}") if d["cache"] != ref["cache"]: print(f"warning: {p} ran {d['cache']!r}, {paths[0]} ran {ref['cache']!r}", file=sys.stderr) if d.get("host") != ref.get("host"): print(f"warning: {p} ran on {d.get('host')}, {paths[0]} on {ref.get('host')}", file=sys.stderr) names = [d["tool"] for d in docs] for d in docs: extra = f", HDF5 {d['hdf5_version']}" if "hdf5_version" in d else "" print(f"- {d['tool']} {d['version']}{extra}: host {d.get('host')}, " f"{d.get('cpus')} CPUs, cache {d['cache']}, decode threads per read " f"{d.get('decode_threads')}") p = ref["params"] print(f"\n{p['datasets']} datasets of {p['rows']} x {p['cols']} f32, chunks " f"{p['chunk'][0]} x {p['chunk'][1]} (deflate {p['deflate_level']}); " f"`same`: {p['slabs']} slabs of {p['slab']} x {p['slab']}\n") index = [{(r["layout"], r["mode"], r["threads"]): r for r in d["results"]} for d in docs] keys = [(r["layout"], r["mode"], r["threads"]) for r in ref["results"]] head = ["layout", "mode", "threads"] head += [f"{n} MB/s (eff)" for n in names] head += [f"{names[0]} / {n}" for n in names[1:]] print("| " + " | ".join(head) + " |") print("|---|---|" + "---:|" * (len(head) - 2)) for key in keys: cells = [key[0], key[1], str(key[2])] rs = [ix.get(key) for ix in index] for r in rs: if r is None: cells.append("-") else: eff = "-" if r["efficiency"] is None else f"{r['efficiency']:.2f}" cells.append(f"{r['mb_s']:.0f} ({eff})") for r in rs[1:]: cells.append("-" if r is None else f"{rs[0]['mb_s'] / r['mb_s']:.2f}x") print("| " + " | ".join(cells) + " |") if __name__ == "__main__": main(sys.argv[1:])