Output
CLI
File output
Pass --outfile FILE to append records in JSONL
format. Defaults to stdout when omitted:
microbench --outfile results.jsonl -- ./run.sh
# or pipe to another tool:
microbench -- ./run.sh | jq .
Redis output
Use --redis-output KEY to RPUSH each record to a Redis list. Useful for
SLURM array jobs where many nodes write concurrently and a shared filesystem
is impractical. Requires the redis-py
package (pip install redis).
| Option | Default | Description |
|---|---|---|
--redis-host HOST |
localhost |
Redis server hostname |
--redis-port PORT |
6379 |
Redis server port |
--redis-db DB |
0 |
Redis database index |
--redis-password PASSWORD |
— | AUTH password |
HTTP output
Use --http-output URL to POST each record as JSON to an HTTP endpoint.
Useful for webhooks and real-time notifications:
Pass --http-output-header KEY:VALUE for authentication (repeatable):
microbench \
--http-output https://api.example.com/benchmarks \
--http-output-header "Authorization:Bearer $MY_TOKEN" \
-- ./run.sh
| Option | Default | Description |
|---|---|---|
--http-output-header KEY:VALUE |
— | Extra request header; repeatable |
--http-output-method METHOD |
POST |
HTTP method |
The CLI always sends the raw record JSON. To customise the payload shape
(e.g. a Slack {"text": "..."} envelope), use the Python API with a
HttpOutput subclass that overrides format_payload.
Combining outputs
All three destinations can be combined:
microbench \
--outfile /scratch/$USER/results.jsonl \
--redis-output bench:results \
--http-output https://hooks.example.com/events \
-- ./run_simulation.sh
Python API
Saving to a file
Pass outfile as a constructor argument or set it as a class attribute:
from microbench import MicroBench
# As a constructor argument
bench = MicroBench(outfile='/home/user/results.jsonl')
# Or as a class attribute
class MyBench(MicroBench):
outfile = '/home/user/results.jsonl'
Results are written in JSONL format (one JSON
object per line). When outfile is a path string, each write opens the
file with O_APPEND, which guarantees atomic appends on POSIX filesystems.
Multiple processes can safely write to the same file simultaneously — a
common pattern when running benchmark jobs across cluster nodes.
In-memory buffer
If no outfile is specified, results are written to an in-memory
io.StringIO buffer. This is the default and is useful for interactive
sessions or testing:
bench = MicroBench()
@bench
def my_function():
pass
my_function()
results = bench.get_results() # list of dicts
results = bench.get_results(format='df') # pandas DataFrame
Multiple output sinks
Pass an outputs list to write to several destinations simultaneously.
Each element must be an Output subclass instance. outfile and outputs
are mutually exclusive.
from microbench import MicroBench, FileOutput, RedisOutput
bench = MicroBench(outputs=[
FileOutput('/home/user/results.jsonl'),
RedisOutput('microbench:mykey', host='redis-host', port=6379),
])
get_results() reads from the first sink that supports it. The format and
flat arguments work the same as with FileOutput.
Redis output
Redis is useful when a shared filesystem is not available, such as on cloud or HPC clusters. Requires redis-py.
from microbench import MicroBench, RedisOutput
bench = MicroBench(outputs=[
RedisOutput('microbench:mykey', host='redis-host', port=6379)
])
@bench
def my_function():
pass
my_function()
results = bench.get_results() # list of dicts
results = bench.get_results(format='df') # pandas DataFrame
Results are appended to a Redis list using RPUSH and read back with
LRANGE.
HTTP output
HttpOutput POSTs each benchmark record as JSON to an HTTP/HTTPS endpoint.
Useful for webhooks and real-time notifications (Slack, Teams, custom event
pipelines). Uses only the Python standard library (urllib).
from microbench import MicroBench, HttpOutput
bench = MicroBench(outputs=[HttpOutput('https://example.com/events')])
Add authentication headers:
bench = MicroBench(outputs=[HttpOutput(
'https://api.example.com/benchmarks',
headers={'Authorization': 'Bearer my-secret-token'},
)])
Override format_payload() to customize the body shape (e.g. for Slack):
import json
from microbench import HttpOutput
class SlackOutput(HttpOutput):
def format_payload(self, record):
name = record.get('call', {}).get('name', '?')
return json.dumps({'text': f'Benchmark `{name}` finished.'}).encode()
bench = MicroBench(outputs=[SlackOutput('https://hooks.slack.com/services/...')])
HttpOutput raises on non-2xx responses or network failures — no silent
dropping, no automatic retry.
Custom output sinks
Subclass Output and implement write to send results anywhere:
from microbench import MicroBench, Output
class MyOutput(Output):
def write(self, bm_json_str):
send_to_my_system(bm_json_str)
bench = MicroBench(outputs=[MyOutput()])
Reading results
Read results back via get_results():
results = bench.get_results() # list of dicts — no extra dependencies
results = bench.get_results(format='df') # pandas DataFrame
# or read directly with pandas:
import pandas
results = pandas.read_json('/home/user/results.jsonl', lines=True)
Pass flat=True to flatten nested fields (e.g. mb, call, slurm, git,
cgroups) into dot-notation keys:
results = bench.get_results(flat=True)
# {'call.name': 'noop', 'mb.run_id': '...', 'slurm.job_id': '12345', ...}
Quick summary
Print min/mean/median/max/stdev of call.durations with no extra dependencies:
The module-level summary() accepts any list of result dicts: