Result Export Formats¶
BenchBox exports benchmark results in multiple formats for analysis, visualization, and integration with external tools.
Export Commands¶
Basic Export¶
# Run benchmark and export results
benchbox run --platform duckdb --benchmark tpch --scale 0.1
# Results are automatically saved to benchmark_runs/results/
ls benchmark_runs/results/
# tpch_duckdb_sf0.01_20251212_143021.json
Export to Other Formats¶
# Export most recent result to CSV
benchbox export --last --format csv
# Export to multiple formats
benchbox export --last --format csv --format html
# Export a specific result file
benchbox export benchmark_runs/results/tpch_duckdb_sf0.01_20251212_143021.json --format csv --format html
Custom Output Directory¶
# Local directory
benchbox run --platform duckdb --benchmark tpch --output ./my_results/
# Cloud storage
benchbox run --platform snowflake --benchmark tpch --output s3://bucket/results/
JSON Format (Schema v2.1)¶
The JSON export is the canonical schema-v2 result bundle containing complete
benchmark details. BenchBox currently writes schema version "2.1" in the
top-level version field.
Consumer policy is intentionally split by use case:
Consumer |
Accepted versions |
Behavior |
|---|---|---|
Producer/exporter |
|
New bundles are written with the current producer version. |
Runtime loader and exporter listing |
|
Unknown versions fail closed and should be re-exported. |
Normalizer |
|
Known v2 bundles use exact v2 field mapping; v1.x and unknown shapes use legacy best-effort extraction. |
Public submission validator |
Numeric |
Forward-compatible for schema-v2 minor versions, but missing or malformed versions are rejected. |
Explorer pipeline input |
|
Unsupported bundles are rejected before explorer read-model projection. |
Schema Structure¶
{
"version": "2.1",
"run": {
"id": "tpch-duckdb-20260521",
"timestamp": "2026-05-21T14:30:21.123456Z",
"total_duration_ms": 45230,
"query_time_ms": 39800
},
"benchmark": {
"id": "tpch",
"name": "TPC-H",
"scale_factor": 0.1
},
"platform": {
"name": "duckdb",
"version": "1.2.0"
},
"config": {
"execution_mode": "sql"
},
"summary": {
"queries": {
"total": 22,
"passed": 22,
"failed": 0
},
"timing": {
"total_ms": 39800,
"avg_ms": 1809.1
},
"validation": "passed",
"tpc_metrics": {
"power_at_size": 89.5
}
},
"phases": {
"data_generation": { "...": "..." },
"schema_creation": { "...": "..." },
"data_loading": { "...": "..." },
"power_test": { "...": "..." }
},
"queries": [
{
"id": "Q1",
"ms": 1520,
"rows": 4,
"iter": 1,
"stream": 0,
"run_type": "measurement",
"status": "SUCCESS"
}
],
"environment": {
"os": "macOS",
"arch": "arm64"
}
}
Field Reference¶
Version¶
Field |
Type |
Description |
|---|---|---|
|
string |
Result bundle schema version. Current producer version is |
Benchmark Block¶
Field |
Type |
Description |
|---|---|---|
|
string |
Benchmark identifier (tpch, tpcds, ssb, etc.) |
|
string |
Display name |
|
float |
Data scale factor |
|
string |
Optional run/test classification |
Platform Block¶
Field |
Type |
Description |
|---|---|---|
|
string |
Platform identifier |
|
string |
Platform/driver version |
|
object |
Optional normalized deployment metadata |
|
object |
Optional normalized environment facets |
Platform-specific extensions should stay inside the existing schema-v2 blocks
where possible. Current canonical locations are platform.* for platform
facets and raw platform metadata, phases.<stage> for lifecycle-stage
summaries, and comparisons.* for cross-engine comparison data. New top-level
keys require a public-contract update and consumer tests.
Run Block¶
Field |
Type |
Description |
|---|---|---|
|
string |
Run start time (ISO 8601) |
|
string |
Run identifier |
|
number |
Total benchmark duration |
|
number |
Total query execution duration |
Phases Block¶
Phases are keyed by lifecycle stage. Each phase block may carry status, duration, counts, and stage-specific metadata.
{
"data_generation": {
"duration_ms": 5230,
"status": "SUCCESS",
"tables_generated": 8,
"total_rows_generated": 150000
},
"schema_creation": {
"duration_ms": 120,
"status": "SUCCESS",
"tables_created": 8
},
"data_loading": {
"duration_ms": 3500,
"status": "SUCCESS",
"tables_loaded": 8
},
"power_test": {
"duration_ms": 39800,
"status": "SUCCESS"
}
}
Summary Block¶
Field |
Type |
Description |
|---|---|---|
|
int |
Total query records represented in the bundle |
|
int |
Count of passed queries |
|
int |
Count of failed queries |
|
number |
Total query execution time in milliseconds |
|
number |
Average query execution time in milliseconds |
|
string or object |
Validation result summary |
|
object |
Optional TPC-style metrics such as |
Query Execution Details¶
Each query execution record contains:
{
"id": "Q6",
"ms": 234,
"rows": 1,
"iter": 1,
"stream": 0,
"run_type": "measurement",
"status": "SUCCESS"
}
CSV Format¶
CSV export provides tabular query-level data for spreadsheet analysis.
Query Results CSV¶
id,ms,rows,iter,stream,run_type,status
Q1,1520,4,1,0,measurement,SUCCESS
Q2,892,460,1,0,measurement,SUCCESS
Q3,1230,10,1,0,measurement,SUCCESS
...
Summary CSV¶
metric,value
benchmark,tpch
scale_factor,0.1
platform,duckdb
total_time_ms,39800
avg_time_ms,1809.1
power_at_size,89.5
total_duration_ms,45230
HTML Format¶
HTML export generates a standalone report with formatted tables.
# Generate HTML report from most recent result
benchbox export --last --format html
# Export a specific result file to HTML
benchbox export benchmark_runs/results/tpch_duckdb_sf0.01_20251212_143021.json --format html
The HTML report includes:
Summary metrics card
Query results table with timing data
Phase duration breakdown
Validation status table
Platform and configuration details
Visualizing Results¶
Use benchbox visualize to generate ASCII charts from any result file:
# Auto-detect latest result and render all applicable charts
benchbox visualize
# Visualize a specific result file
benchbox visualize benchmark_runs/results/tpch_duckdb_sf0.01_20251212_143021.json
# Specific chart type
benchbox visualize benchmark_runs/results/*.json --chart-type performance_bar
# Save plain-text output to file
benchbox visualize benchmark_runs/results/*.json --no-color > charts.txt
See the Visualization Guide for chart types, templates, and customization options.
Loading Results in Python¶
Load JSON Results¶
import json
from pathlib import Path
# Load result file
result_file = Path("benchmark_runs/results/tpch_duckdb_sf0.01_20251212_143021.json")
with result_file.open() as f:
results = json.load(f)
# Access metrics
print(f"Power at Size: {results['summary']['tpc_metrics']['power_at_size']}")
print(f"Total time: {results['summary']['timing']['total_ms']}ms")
# Access query details
for query in results['queries']:
print(f"{query['id']}: {query['ms']}ms")
Load into Pandas¶
import pandas as pd
import json
# Load JSON
with open("benchmark_runs/results/tpch_duckdb_sf0.01_*.json") as f:
results = json.load(f)
# Convert queries to DataFrame
queries = results['queries']
df = pd.DataFrame(queries)
# Analyze
print(df.describe())
print(df.groupby('id')['ms'].mean())
Load CSV Results¶
import pandas as pd
# Load query results
df = pd.read_csv("benchmark_runs/results/tpch_duckdb_sf0.01_queries.csv")
# Quick analysis
print(f"Total queries: {len(df)}")
print(f"Mean execution time: {df['ms'].mean():.2f}ms")
print(f"Slowest query: {df.loc[df['ms'].idxmax(), 'id']}")
Visualization Examples¶
CLI Visualization¶
# Render all applicable charts for a result file
benchbox visualize benchmark_runs/results/tpch_duckdb_sf0.01_*.json
# Compare multiple platforms
benchbox visualize duckdb_result.json sqlite_result.json --template head_to_head
# Per-query histogram (auto-splits for large benchmarks)
benchbox visualize tpcds_result.json --chart-type query_histogram
Python API Visualization¶
from benchbox.core.visualization import ResultPlotter
from benchbox.core.visualization.ascii import ASCIIBarChart
from benchbox.core.visualization.ascii.bar_chart import BarData
# Load results from JSON files
plotter = ResultPlotter.from_sources(["results/duckdb.json", "results/sqlite.json"])
# Render a bar chart
bar_data = [BarData(label=r.platform, value=r.total_time_ms or 0) for r in plotter.results]
chart = ASCIIBarChart(data=bar_data, title="Platform Comparison")
print(chart.render())
# Export to plain-text file
from benchbox.core.visualization.exporters import export_ascii
export_ascii(
ascii_content=chart.render(),
output_dir="./charts",
base_name="platform_comparison",
format="txt",
)
Schema Versioning¶
Current Version: 2.1¶
Schema v2.1 is the current producer version for BenchBox result bundles. It
uses top-level version, run, benchmark, platform, summary, queries,
and optional companion blocks such as phases, environment,
normalized_cost, validation, and comparisons.
Runtime loading and explorer generation intentionally accept only known v2
minor versions ("2.0" and "2.1"). The public submission validator accepts
numeric 2.x versions to allow forward-compatible submissions, but it rejects
missing values and malformed strings such as "2.x". Legacy v1.x result shapes
are not runtime-loadable; they are handled only by the normalizer’s best-effort
compatibility path.
Version History¶
Version |
Changes |
|---|---|
2.1 |
Current producer schema for result bundles |
2.0 |
First schema-v2 bundle contract consumed by loader, submissions, and explorer |
1.x |
Legacy shape supported only by normalization helpers |
Loading Legacy Results¶
import json
from benchbox.core.results.normalizer import normalize_result_dict
with open("old_result.json") as f:
result = normalize_result_dict(json.load(f))
print(f"Schema version family: {result.schema_version}")
Anonymization¶
Results are anonymized by default to remove sensitive information:
Connection strings → hashed
Hostnames → generalized
Usernames → removed
API keys/tokens → stripped
Disable Anonymization¶
Anonymization can be configured programmatically via the Python API:
Anonymization Config¶
from benchbox.core.results.exporter import ResultExporter
from benchbox.core.results.anonymization import AnonymizationConfig
config = AnonymizationConfig(
anonymize_hostname=True,
anonymize_username=True,
anonymize_connection_string=True,
preserve_platform_version=True
)
exporter = ResultExporter(anonymize=True, anonymization_config=config)
Integration Examples¶
Export to Data Warehouse¶
import json
import pandas as pd
# Load results
with open("results.json") as f:
results = json.load(f)
# Flatten to table
queries = []
for q in results['queries']:
queries.append({
'run_id': results['run']['id'],
'benchmark': results['benchmark']['id'],
'platform': results['platform']['name'],
'scale_factor': results['benchmark']['scale_factor'],
**q
})
df = pd.DataFrame(queries)
# Upload to warehouse
# df.to_sql('benchmark_queries', engine, if_exists='append')
CI/CD Integration¶
# Run benchmark and check threshold
benchbox run --platform duckdb --benchmark tpch --scale 0.01 \
--output ./results/
# Parse results in CI script
uv run -- python -c "
import json
import sys
with open('results/tpch_duckdb_sf0.01_*.json') as f:
results = json.load(f)
power = results['summary']['tpc_metrics']['power_at_size']
if power < 50: # Performance threshold
print(f'FAIL: Power@Size {power} below threshold 50')
sys.exit(1)
print(f'PASS: Power@Size {power}')
"