Fetch EVM benchmark suites from the Benchmarkoor API and produce clean tabular outputs.
Project description
benchmarkoor-fetch
Fetch EVM benchmark suites from the Benchmarkoor
API and write clean tabular outputs (runtimes.csv, opcounts.json,
bench_data.parquet, trace.parquet, meta.json).
Data-ingestion only — no modelling, no gas analysis. The artifact bundle feeds evm-gasfit, which owns the gas-cost estimation step.
Install
pip install benchmarkoor-fetch
Requires Python ≥ 3.11.
Auth
The Benchmarkoor API requires a bearer token. Set it once:
export BENCHMARKOOR_TOKEN=...
You can also pass it per-call: --token … on the CLI, or
BenchmarkoorClient(token=…) in Python. It is never read from the YAML
config.
CLI quickstart
Write a fetch.yaml:
query:
network: jochemnet
fork: amsterdam
test_type: compute
start_date: "2026-05-18"
end_date: "2026-05-20"
fork is always required. network and test_type are used to discover
the latest matching suite_hash; if you already know the hashes, list them
under suites: instead and omit network / test_type:
query:
fork: amsterdam
suites:
- 0xaaa111
- 0xbbb222
To keep only the runs whose run_id matches a regex, add run_id_pattern:
query:
fork: amsterdam
suites:
- 0xaaa111
run_id_pattern: '.*-full' # keep runs whose run_id ends with `-full`
run_id_pattern is matched against each run_id with re.fullmatch, so the
whole run_id must match — use .*…* to get substring behaviour (e.g.
'.*bal-full.*' to keep any run_id containing bal-full). A malformed
regex is rejected at config load.
By default only the per-run runtime is written. To also capture
throughput (megagas per second), or to fetch only throughput, set
query.metrics (default [runtime]; allowed values runtime, mgas_s):
query:
fork: amsterdam
metrics: [runtime, mgas_s] # also write mgas_s.csv
runtime produces runtimes.csv (test_runtime_ms) and mgas_s produces
mgas_s.csv (test_mgas_s); each estimator-input CSV is written only when its
metric is selected.
Note:
query.metricsonly controls which measurements are written. Bothtest_time_nsandtest_mgas_sare always downloaded from the API regardless of your selection. This is deliberate: it keeps the per-run cache content-addressed, so a single cached entry serves any metric selection and switchingmetricsnever forces a refetch. The fetch cost is the same whether you request one metric or both.
Then run:
benchmarkoor-fetch run --config fetch.yaml --out ./data
If --out is omitted, outputs land in
./{earliest_run_ts}_{latest_run_ts}/ using the actual run timestamps of
the data fetched (not the configured window).
Any query.* or output.* field can be overridden on the command line:
benchmarkoor-fetch run --config fetch.yaml \
--fork osaka --start-date 2026-05-01 --end-date 2026-05-08 \
--metrics runtime,mgas_s \
--out ./data
Resolve the latest suite hash for a (network, fork, test_type) tuple without fetching the bundle:
benchmarkoor-fetch suites --network jochemnet --fork amsterdam --test-type compute
Exit codes: 0 success · 1 config/input error · 2 HTTP error ·
3 empty result.
Verbosity: by default the CLI prints high-level milestones (suite
resolution, runs listed, trace fetch) and a tqdm progress bar while
fetching test stats. Pass --verbose to also emit per-event detail (cache
hit/miss, per-run fetch lines), or --quiet to suppress milestones and
progress; only warnings and errors are shown. --verbose and --quiet
are mutually exclusive.
Python / notebook quickstart
Style A — config-driven, full pipeline:
from benchmarkoor_fetch import BenchmarkoorClient, FetchConfig
config = FetchConfig.from_yaml("fetch.yaml")
client = BenchmarkoorClient() # picks up BENCHMARKOOR_TOKEN
result = client.run(config) # returns FetchResult
result.bench_df # merged DataFrame
result.trace_df # per-fixture opcode counts
result.write("./data") # writes the artifact bundle
Style B — granular, for notebooks that want to inspect mid-pipeline (see examples/quickstart.ipynb for the runnable version):
client = BenchmarkoorClient()
suite_hash = client.resolve_suite(
network="jochemnet", fork="amsterdam", test_type="compute"
)
runs = client.list_runs(suite_hash, start_date="2026-05-18", end_date="2026-05-20")
raw_df = client.fetch_test_stats(runs, suite_hash=suite_hash)
trace = client.fetch_trace(suite_hash)
bench_df, trace_df = client.parse(raw_df, trace, fork="amsterdam")
Outputs
Written to --out:
| File | Contents |
|---|---|
runtimes.csv |
client_name, fixture_name, test_runtime_ms — one row per benchmark run. Written when runtime is in query.metrics. |
mgas_s.csv |
client_name, fixture_name, test_mgas_s — one row per benchmark run. Written when mgas_s is in query.metrics. |
opcounts.json |
{fixture_name: {opcount, OPCODE: count, …}}. |
bench_data.parquet |
The full merged frame: run_id, client_name, test_title, test_file, test_name, test_opcode, test_params, test_runtime_ms, ingestion_timestamp, block_limit_million, opcount. Includes test_mgas_s when mgas_s is selected, and omits test_runtime_ms when runtime is not. |
trace.parquet |
Per-fixture trace keyed by test_title. |
meta.json |
Resolved suite hashes, query block (including the selected metrics), fetched-at timestamp, package version, row counts. |
Runtimes are kept in milliseconds (test_runtime_ms) on the wire and
on disk — converting to seconds is left to the consumer. Throughput
(test_mgas_s) is in megagas per second.
Feeding evm-gasfit
The two-step workflow is:
# 1. Ingest with benchmarkoor-fetch
benchmarkoor-fetch run --config fetch.yaml --out ./data
# 2. Estimate gas costs with evm-gasfit, pointing at the same folder
evm-gasfit fit --inputs ./data ...
evm-gasfit consumes runtimes.csv + opcounts.json from the output
directory; bench_data.parquet and trace.parquet are there for direct
DataFrame analysis.
Caching
Responses are cached on disk under ./.cache/benchmarkoor-fetch/
(relative to the current working directory) by default. The cache is content-addressed and never expires — keys are
built so that a hit guarantees byte-identical bytes. Suite discovery is
intentionally not cached (it must always reflect the latest suite).
Bypass per-run with --no-cache, relocate with --cache-dir <path>, or
disable in YAML via cache.enabled: false.
Cached test_stats entries always hold every metric (both test_time_ns and
test_mgas_s), independent of query.metrics, so changing the metric
selection reuses the existing cache and never triggers a refetch. The one
exception is entries written before mgas_s support existed: they lack the
test_mgas_s column, so the first mgas_s run against an already-cached suite
should be forced with --no-cache (or clear the cache dir) to repopulate it.
Development
pip install -e ".[dev]"
pytest
ruff check src tests
ruff format src tests
License
See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file benchmarkoor_fetch-0.3.0.tar.gz.
File metadata
- Download URL: benchmarkoor_fetch-0.3.0.tar.gz
- Upload date:
- Size: 52.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5a60b8428f699ad55a8398bd9514e609cee3a9667e6cf6072f8f1d6543cb2cc
|
|
| MD5 |
de16c455e06923dece58a2c17a1afeea
|
|
| BLAKE2b-256 |
44f2000442714dc846cf154156076302cdd579886ef3e49d0df109dcfa8237c8
|
Provenance
The following attestation bundles were made for benchmarkoor_fetch-0.3.0.tar.gz:
Publisher:
release.yml on misilva73/benchmarkoor-fetch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
benchmarkoor_fetch-0.3.0.tar.gz -
Subject digest:
b5a60b8428f699ad55a8398bd9514e609cee3a9667e6cf6072f8f1d6543cb2cc - Sigstore transparency entry: 1779238818
- Sigstore integration time:
-
Permalink:
misilva73/benchmarkoor-fetch@b43f431ad0b34f1902fa06c41bf6ea8ae78dcd21 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/misilva73
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b43f431ad0b34f1902fa06c41bf6ea8ae78dcd21 -
Trigger Event:
push
-
Statement type:
File details
Details for the file benchmarkoor_fetch-0.3.0-py3-none-any.whl.
File metadata
- Download URL: benchmarkoor_fetch-0.3.0-py3-none-any.whl
- Upload date:
- Size: 39.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d29fdfda1ed5b6bc041ce618742b0d0039b68bbe0cb2d28431188778577ba23d
|
|
| MD5 |
5e502789f1399ac27752e47550ff8abb
|
|
| BLAKE2b-256 |
161ccde1cfb2386d0633e895c1a409239aa4f6e8ca684aa0e38649fa1b8a3c01
|
Provenance
The following attestation bundles were made for benchmarkoor_fetch-0.3.0-py3-none-any.whl:
Publisher:
release.yml on misilva73/benchmarkoor-fetch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
benchmarkoor_fetch-0.3.0-py3-none-any.whl -
Subject digest:
d29fdfda1ed5b6bc041ce618742b0d0039b68bbe0cb2d28431188778577ba23d - Sigstore transparency entry: 1779238923
- Sigstore integration time:
-
Permalink:
misilva73/benchmarkoor-fetch@b43f431ad0b34f1902fa06c41bf6ea8ae78dcd21 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/misilva73
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b43f431ad0b34f1902fa06c41bf6ea8ae78dcd21 -
Trigger Event:
push
-
Statement type: