Skip to content

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).

microbench \
    --redis-output bench:results \
    --redis-host redis.example.com \
    -- ./run_simulation.sh
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:

microbench --http-output https://api.example.com/benchmarks -- ./run.sh

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:

bench.summary()
# n=10  min=0.000031  mean=0.000038  median=0.000036  max=0.000059  stdev=0.000008

The module-level summary() accepts any list of result dicts:

from microbench import summary
summary(bench.get_results())