Evaluate ClickHouse performance test results from existing CI/dashboard data or local perf.py runs. Use to check PR performance changes, run local performance tests, compare with history, assess flakiness, inspect coverage/PR relevance, and summarize whether a result is actionable.
npx skills add https://github.com/ClickHouse/ClickHouse --skill perf-comparison
Use this skill whenever the goal is to answer:
> Is this ClickHouse performance result real, flaky/noisy, already known from history, or worth deeper investigation?
The evidence may come from existing performance CI/dashboard data, a local perf.py run, or both. Do not treat this as two separate modes; use whichever evidence is available and add missing evidence only when it changes the decision.
M1:downgrade, M2:neutral are not report-ready; translate confidence into tier/reason and named evidence checks.client_time with CPU/real/memory metrics.# List performance.ci runs for a PR.
python3 scripts/perf_api.py runs --pr 104350
# Inventory a PR first. This prints a small summary layer, then separates changed slowdowns,
# changed speedups, and high-noise rows.
python3 scripts/perf_api.py pr-inventory --pr 104350 --limit 20 --with-confidence
# 30-day master status classification via play.clickhouse.com default.checks.
python3 scripts/perf_api.py master-checks --pr 104350 --limit 50
# Inspect raw CI metric TSVs only when dashboard/API cannot provide required artifact-level data.
python3 scripts/perf_api.py tsv-inventory --tsv pr_104350_amd.tsv pr_104350_arm.tsv --limit 20
# Summarize a run's changed metrics.
python3 scripts/perf_api.py changes --run-id "$RUN_ID" --with-confidence
# Inspect one query with trend/history/coverage/flamegraph diff.
python3 scripts/perf_api.py query \
--run-id "$RUN_ID" \
--test aggregation_in_order_2 \
--query-index 4 \
--metric client_time \
--arch arm \
--with-confidence --with-trend --with-history --with-coverage --with-flamegraph-diff
# Compare one test/query/metric across all dashboard runs for a PR.
python3 scripts/perf_api.py pr-query-history \
--pr 104350 \
--test aggregation_in_order_2 \
--query-index 4 \
--metric client_time \
--arch arm
# Parse local tests/performance/scripts/perf.py output.
mkdir -p tmp
python3 scripts/parse_perf_py.py tmp/perf-output.tsv
References:
references/ci-api.md — performance.ci API and dashboard workflow.references/local-perf.md — local perf.py, optional server startup, datasets, and profiling.references/verdict-rules.md — classification rules and reporting checklist.Use the richest reliable source for each question:
default.checks) for 30-day master status counts: how often the same test/query appeared slower, faster, or unstable on master. Use master-checks for this.perf.py only when explicit old/new binaries are provided and local validation is useful; report it as non-CI-equivalent.BASE="https://performance.ci.clickhouse.com/api/v1"
Find PR runs:
PR=104350
curl -fsS "$BASE/runs?q=$PR" | jq .
Get run overview:
curl -fsS "$BASE/runs/$RUN_ID?metrics=client_time,real_time,cpu_time,memory" | jq .
Get query detail:
curl -fsS "$BASE/runs/$RUN_ID/tests/$TEST/queries/$QUERY_INDEX?metrics=client_time,real_time,cpu_time,memory" | jq .
Get trend/history:
curl -fsS "$BASE/runs/$RUN_ID/tests/$TEST/trend?metric=$METRIC&queryIndex=$QUERY_INDEX&arch=$ARCH" | jq .
curl -fsS "$BASE/history/$TEST/$QUERY_INDEX?metric=$METRIC&arch=$ARCH" | jq .
Get PR coverage overlap for a test:
curl -fsS "$BASE/runs/$RUN_ID/tests/$TEST/coverage?fileSet=intersecting" | jq .
Open the UI flamegraph page first:
https://performance.ci.clickhouse.com/runs/$RUN_ID/tests/$TEST/queries/$QUERY_INDEX
Use the raw flamegraph-diff API only for machine-readable sample deltas:
curl -fsS "$BASE/runs/$RUN_ID/tests/$TEST/queries/$QUERY_INDEX/flamegraph-diff?metric=$METRIC&arch=$ARCH&traceType=CPU" | jq .
API caveats observed in live testing:
unstableQueries[] can contain high-noise/below-threshold rows even when the summary card says Unstable queries: 0; do not treat them as actionable changed rows unless they are over threshold.trend.selectedRunPoint.value may be a zero marker; use query-detail old/new values for the measurement.coverage?fileSet=intersecting may omit totals.intersectingFiles when there are zero intersecting files; use len(files) as the fallback.For each suspicious change, collect as much of this ladder as needed:
python3 scripts/perf_api.py pr-inventory --pr <PR> --with-confidence. The inventory must begin with a small generated summary layer: Top likely signal, Top likely noise, and Top improvements. Changed-row tables must separate signal evidence from noise/uncertain evidence. Do not mix high-noise rows into changed slowdown/speedup tables. Use CI artifacts only when dashboard/API cannot provide required raw data.Raw Sample Evidence, History Adaptive Threshold, Recent Master Variation, etc.). Never leave raw M1/M2/... codes unexplained.python3 scripts/perf_api.py master-checks --pr <PR> to query play.clickhouse.com default.checks over master-only runs and classify rows as new/rare/flaky/unstable/fixes-known-regression. The output should be grouped by signal vs noise/uncertain evidence and link to the test page with the query selected.10. Artifacts/logs for root cause: if dashboard/API cannot answer why, download CI artifacts for server logs, trace logs, raw profile events, SVG flamegraphs, and exact binary/build metadata.
11. Local reproduction: if needed, run perf.py against old/new binaries with isolated servers.
Stop when the verdict is clear; do not gather expensive evidence just to decorate a report. Exceptions: always inventory improvements as well as regressions; for large PRs or many changed rows, do not stop after a few representative examples; produce a portfolio/ranking summary first. Avoid repetitive all-run top tables unless the caller asks for verbose output or rerun history is central to the conclusion.
For a PR, inspect all runs returned by:
curl -fsS "$BASE/runs?q=$PR" | jq '.items[] | {runId: .identity.runId, time: .identity.runTime, changed: .changedQueries, slowdowns: .slowdownQueries, speedups: .speedupQueries}'
For a specific query:
python3 scripts/perf_api.py pr-query-history --pr "$PR" --test "$TEST" --query-index "$QUERY_INDEX" --metric "$METRIC" --arch "$ARCH"
The output must include performance.ci UI links and an oldest→newest diff chart. A missing old run endpoint is not available; do not turn an HTTP status into an investigation conclusion.
Interpretation:
Fetch coverage overlap:
curl -fsS "$BASE/runs/$RUN_ID/tests/$TEST/coverage?fileSet=intersecting" | jq .
Use:
totals.intersectingFiles > 0: PR touched files executed by the perf test.files[].path, files[].patch, coverageRanges: identify touched covered lines.If coverage is unavailable, fall back to:
gh pr diff "$PR" --name-only
gh pr diff "$PR"
Relate query to changes:
If the user wants to run a test locally or validate a patch, use ClickHouse perf.py.
Print queries first:
tests/performance/scripts/perf.py --print-queries tests/performance/$TEST.xml
Compare two already-running servers:
mkdir -p tmp
tests/performance/scripts/perf.py \
--host 127.0.0.1 127.0.0.1 \
--port ${OLD_TCP_PORT:-9000} ${NEW_TCP_PORT:-9001} \
--runs 7 \
tests/performance/$TEST.xml | tee tmp/${TEST}.perf.tsv
Run one query index:
mkdir -p tmp
tests/performance/scripts/perf.py \
--host 127.0.0.1 127.0.0.1 \
--port ${OLD_TCP_PORT:-9000} ${NEW_TCP_PORT:-9001} \
--runs 7 \
--queries-to-run "$QUERY_INDEX" \
tests/performance/$TEST.xml | tee tmp/${TEST}_${QUERY_INDEX}.perf.tsv
Parse output:
python3 scripts/parse_perf_py.py tmp/${TEST}_${QUERY_INDEX}.perf.tsv
If servers are not running and the user wants help, use references/local-perf.md and optionally scripts/local_servers.sh. Prefer release/static builds. Do not compare debug/sanitizer builds unless the user explicitly wants that.
Local binary contract:
scripts/local_servers.sh requires explicit local paths: OLD_CLICKHOUSE NEW_CLICKHOUSE [WORKDIR].OLD_TCP_PORT, NEW_TCP_PORT, OLD_HTTP_PORT, NEW_HTTP_PORT.Praktika CI artifact lookup for performance-style release binaries:
# First get PR/run identity. Use identity.newSha for candidate and identity.oldSha for base/reference.
python3 scripts/perf_api.py runs --pr "$PR"
# Candidate PR binary from Praktika artifact report.
PR=<pr-number>
SHA=<candidate-sha>
ARCH=arm # arm or amd, matching the run/result being reproduced
JOB="build_${ARCH}_release"
REPORT="https://clickhouse-builds.s3.amazonaws.com/PRs/${PR}/${SHA}/${JOB}/artifact_report_${JOB}.json"
curl -fsS "$REPORT" | jq -r '.build_urls[] | select(endswith("/clickhouse"))'
# Exact master/reference binary.
SHA=<reference-sha>
URL="https://clickhouse-builds.s3.amazonaws.com/REFs/master/${SHA}/${JOB}/clickhouse"
curl -sfI "$URL"
If the user approves a URL, download it to a named path and chmod +x; then pass those paths to local_servers.sh. Record binary path, SHA, architecture, build job, source URL, and version()/buildId() output in the report. Avoid non-SHA-pinned master/amd64/clickhouse or master/aarch64/clickhouse fallbacks for validation unless the user explicitly accepts them.
perf.py prints important lines like:
report-threshold <relative_threshold>
diff <query_index> <old_median> <new_median> <relative_diff> <pvalue>
Treat a local result as meaningful when:
abs(relative_diff) exceeds the report threshold.pvalue <= 0.05.Use one of:
real regressionlikely noiseneeds rerununstable testreal improvementlocal-only evidencenot enough evidence## Performance verdict
Short verdict: <label>
Confidence: <high | medium | low>
## Evidence checked
- Run/API URLs:
- Test/query/metric/arch:
- Old/new/diff/threshold:
- Repeated PR runs:
- Confidence:
- History/trend:
- Coverage/PR relation:
- Flamegraph/profile: exact UI query-page link plus top sample deltas; raw API link only as backup, or explicit `not available` / `no frames returned`.
- Local perf.py, if any:
## Changed metrics
<table>
## Why this verdict
Short explanation that distinguishes current accepted evidence from stale/exploratory measurements.
## Recommended next step
- no action
- rerun performance CI
- run local perf.py
- inspect flamegraph hotspot
- inspect PR code around covered files
- bisect / targeted local validation
Query openFDA API for drugs, devices, adverse events, recalls, regulatory submissions (510k, PMA), substance identification (UNII), for FDA regulatory data analysis and safety research.
Access AlphaFold 200M+ AI-predicted protein structures. Retrieve structures by UniProt ID, download PDB/mmCIF files, analyze confidence metrics (pLDDT, PAE), for drug discovery and structural biology.
Access AlphaFold's 200M+ AI-predicted protein structures. Retrieve structures by UniProt ID, download PDB/mmCIF files, analyze confidence metrics (pLDDT, PAE), for drug discovery and structural biology.
> Generate or improve a company-specific data analysis skill by extracting tribal knowledge from analysts. "Help me create a skill for our database", "Generate a data skill for [company]" → Discovers schemas, asks key questions, generates initial skill with reference files "Update the data skill with [metrics/tables/terminology]", "Improve the [domain] reference" → Loads existing skill, asks targeted questions, appends/updates reference files Use when data analysts want Claude to understand their company's specific data warehouse, terminology, metrics definitions, and common query patterns.
Master advanced AgentDB features including QUIC synchronization, multi-database management, custom distance metrics, hybrid search, and distributed systems integration. Use when building distributed AI systems, multi-agent coordination, or advanced vector search applications.
NCBI GEO access via GEOparse and E-utilities. Search by keyword/organism/platform, download GSE series matrices, parse GPL annotations, extract GSM metadata, load expression matrices into pandas. For single-cell use cellxgene-census; for multi-DB access use gget-genomic-databases.
Master advanced AgentDB features including QUIC synchronization, multi-database management, custom distance metrics, and hybrid search for distributed AI systems.
Master advanced AgentDB features including QUIC synchronization, multi-database management, custom distance metrics, hybrid search, and distributed systems integration. Use when building distributed AI systems, multi-agent coordination, or advanced vector search applications.
Take clickhouse/perf-comparison from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.