Reporters¶
A reporter is a Python class with report_context(context) and report_runs(runs) methods;
with an optional finalize() API.
The C++ runner calls them in the main thread with the GIL held.
Built-ins¶
RichReporterStreams one row per Run as a rich-formatted table. The default for
mew runwhen no-ois given. Optional columns:Peak Mem/Total Alloc(viashow_memory=True) andSamples/Hottest Frame(viashow_cpu=True). The CLI exposes those options via--profile-memory/--sample.JSONReporterEmits a single
{"context": ..., "benchmarks": [...]}document, shaped like Google Benchmark’s own JSON. Buffers in memory and writes onfinalize(). Passoutput=Path(...), a text stream, or omit for stdout.ParquetReporterOne row per Run, static schema, user context flattened. Requires
pyarrow(pip install 'mew[dev]'orpip install pyarrow). Counters are aMAP<string, double>. The user-defined context goes into a JSON string column namedcustom— query with e.g. DuckDB’sjson_extract; session identity lands assession_id/session_tagstring columns (see Context).FanoutBroadcasts each callback to a list of reporters. Used internally by
mew runwhen multiple-osinks are supplied.report_context()returnsall(...)— Google Benchmark halts when any reporter returnsFalse, so the strictest sub-reporter wins.
Choosing a sink¶
Use case |
Recommended sink |
|---|---|
Interactive iteration on a laptop |
|
Capture a baseline for |
|
Long-running results, SQL analytics |
|
Console output + persisted artifact |
|
Custom reporters¶
Implementing the protocol is mechanical:
from typing import Any
from mew import Run
class MetricsExporter:
def __init__(self, sink):
self._sink = sink
self._context: dict[str, Any] = {}
def report_context(self, context: dict[str, Any]) -> bool:
self._context = context
return True
def report_runs(self, runs: list[Run]) -> None:
for r in runs:
self._sink.push(name=r.benchmark_name(), value=r.adjusted_real_time())
def finalize(self) -> None:
self._sink.flush()
Pass it directly to mew.run():
from mew import REGISTRY, run
run(REGISTRY.all(), reporter=MetricsExporter(sink))
DuckDB recipes¶
-- 95th percentile real_time per benchmark
SELECT name, quantile_cont(real_time, 0.95) AS p95
FROM 'results.parquet'
GROUP BY name
ORDER BY p95 DESC;
-- Custom context drill-down
SELECT name,
json_extract(custom, '$.dataset.size') AS size,
avg(real_time) AS mean_time
FROM 'results.parquet'
GROUP BY name, size;