Architecture
A high-level view of the rust-bench system: its components, how they communicate, the multi-platform/multi-repository model, and the lifecycle of a benchmark request. This is the reference layer (factual/structural). For step-by-step runbooks see the guides.
1. Overview
rust-bench is a runtime performance benchmarking and profiling framework for Rust programs, built on rustc-perf and extended for runtime benchmarks, custom metrics, a TUI comparison interface, and multi-platform/multi-repository support.
The system measures how fast Rust programs execute when compiled with a given rustc, using hardware performance counters (perf_event_open), wall-clock timing, and memory high-water-mark measurement. It supports both local benchmarking (single machine, results in a SQLite DB) and an automated, distributed flow in which a central Site receives webhooks, a set of Collectors pull jobs from a queue and execute them, and the Site posts comparison comments back to the originating PR/MR.
Compile-time benchmark machinery inherited from upstream rustc-perf exists in the codebase but is out of scope for this documentation set.
2. Components
┌──────────────────────────────────────────────┐
GitCode/GitHub │ Site │
webhooks ───► │ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ HTTP API │ │ Job queue│ │ Platform API │ │
│ │ /server │ │ /tick │ │ GitHub/GitCode│ │
│ └──────────┘ └────┬─────┘ └───────────────┘ │
└────────────────────┼──────────────────────────┘
│ Postgres job_queue
▼
┌──────────────────────────────────────────────────────────────┐
│ Collector(s) │
│ collect-job-queue.sh loop → benchmark_job_queue │
│ ┌────────────────┐ ┌────────────────────────────────────┐│
│ │ toolchain build│ │ benchlib message protocol (stdout) ││
│ │ /artifact fetch│ │ ← BenchmarkMessage::Result (JSON) ││
│ └────────────────┘ └────────────────────────────────────┘│
└──────────────────────────────┬──────────────────────────────┘
│ results
▼
┌────────────────┐
│ Database │ Postgres (distributed)
│ (Postgres / │ SQLite (local only)
│ SQLite) │
└────────────────┘
Site (site/)
The web server and job-queue orchestrator. Entry point site/src/main.rs:16:
- Loads config from
site-config.toml(or env vars) and the DB into aSiteCtxt(site/src/load.rs:383). - Starts an HTTP server (
site/src/server.rs) on port2346(envPORT) serving the API, frontend, and the webhook endpoint at/perf/webhook(server.rs:343). - Spawns a periodic job-queue tick every
QUEUE_UPDATE_INTERVAL_SECONDS(default 30 s) that creates requests, enqueues jobs, and posts completion comments (site/src/job_queue/mod.rs:419,main.rs:80). - Holds one
PlatformApiclient per configured repo key (load.rs:401) for outbound GitHub/GitCode calls (posting comments, fetching PR/commit data, collaborator checks). - On startup, seeds
benchmark_requestrows for the last 30 days of merge commits per repo (load.rs:541-613, invoked atmain.rs:72).
Collector (collector/)
The benchmark executor. Binary collector (collector/src/bin/collector.rs), library collector/src/lib.rs:
- Two main modes:
bench_runtime_local(single-shot local run into a DB) andbenchmark_job_queue(daemon loop pulling from Postgres). - Discovers and compiles runtime benchmark group crates (
collector/src/runtime/benchmark.rs), runs each benchmark binary, and reads line-delimited JSONBenchmarkMessage::Resultframes from stdout (collector/src/runtime/mod.rs:124-157). - Writes per-iteration numeric samples to
runtime_pstatand per-benchmark JSON reports toruntime_pstat.json_value(mod.rs:232-274). - Built via
collect-job-queue.sh(production loop) with--features s3-sdkfor self-profile S3 storage.
Database (database/)
Two interchangeable backends behind a Connection/Pool trait (database/src/lib.rs, database/src/pool/):
- Postgres (
pool/postgres.rs) — required for the distributed job queue (multi-collector). - SQLite (
pool/sqlite.rs) — local single-machine use only; does not supportbenchmark_job_queue.
The schema is duplicated across both backends via parallel migrations. See database/schema.md.
benchlib (collector/benchlib/)
The measurement library linked into every runtime benchmark binary (collector/benchlib/src/lib.rs):
- Defines the
BenchmarkMessage/BenchmarkResult/BenchmarkSampleprotocol (benchlib/src/comm/messages.rs) and well-knownMETRIC_*constants. - Measures hardware counters via the
perf-eventcrate (perf_event_open(2)syscall), wall time viaInstant, andmax-rssvia/usr/bin/time. Linux-only. - Provides the
#[bench]proc-macro (collector/benchlib-macros/) and acustomframework (benchlib/src/custom.rs) for benchmarks needing full control over measurement/CLI args.
3. Repositories and platforms
rust-bench benchmarks more than one repository, hosted on more than one forge.
Platforms
RepoPlatform (collector/src/lib.rs:36) is Github or Gitcode, serialized lowercase and used as the prefix of repo identifiers like github/rust-lang/rust or gitcode/xuanwu/rust. The platform determines:
- Webhook headers:
X-GitHub-EventvsX-GitCode-Event(event names differ too: GitHubissue_comment/push; GitCodeNote Hook/Push Hook/Tag Push Hook) —site/src/api.rs:922-945. - Signature header:
X-Hub-Signature-256(GitHub) vsX-GitCode-Signature-256(GitCode) —api.rs:947-952. - API base / web base / PR-MR URL path —
site/src/load.rs:93-122. - Auth strategy: GitHub uses HTTP Basic (
rust-bench+ token); GitCode uses Bearer token —site/src/github/platform_client.rs:151-164.
Repositories
Each repo is a [repos.<key>] table in site-config.toml (site/src/load.rs:55). A repo carries:
repo— the platform-prefixed identifier (<platform>/<owner>/<repo>).default_branch,benchmark_groups(default groups to run),build_cmd/build_dir(for non-Rust repos),is_rust,post_build.
The database stores the repo key (e.g. rust, daft), never the full identifier. An incoming webhook's repository path is mapped back to a repo key via Config::repo_key_for_repo (load.rs:268); an unknown repo returns 403 FORBIDDEN (site/src/request_handlers/webhook.rs:64-76).
A repo may be non-Rust (is_rust = false, e.g. the Daft dataframe library): the collector runs build_cmd to produce artifacts, then post_build to install them, before benchmarking. The QueueRuntimeConfig payload on each job carries the per-repo build instructions to the collector (database/src/lib.rs:1627).
4. Request lifecycle
A benchmark request moves through the following states (database/src/lib.rs:1134; DB strings are snake_case waiting_for_artifacts / artifacts_ready / in_progress / completed):
flowchart LR
W[waiting_for_artifacts] -->|try build artifacts appear| A
A[artifacts_ready] -->|cron enqueues jobs| I
I[in_progress] -->|all jobs done, no failures| C[completed]
I -->|job failures| C
- Creation — a webhook arrives at
/perf/webhook(server.rs:343). After HMAC-SHA256 verification against[keys.<platform>].secret(webhook.rs:5-23), the platform and event type are detected (api.rs:922-945):pushto the default branch → oneMasterrequest per merge commit (github.rs:206-273).Tag Push Hook(GitCode) or apushwhoserefisrefs/tags/...(GitHub) → oneReleaserequest (github.rs:165-204,platform_client.rs:244-254).issue_comment/Note Hookcontaining/rust-bench try|master|tag→ aTry/Master/Releaserequest (github.rs:596-863). The author must be a collaborator of the upstream repo (github.rs:551-582).
- Queueing — the periodic tick (
job_queue/mod.rs:419) ordersartifacts_ready/in_progressrequests topologically by parent completion (mod.rs:80-168), keeps at most one requestin_progress, and enqueues one job per(benchmark_group, collector_tag)for the chosen request and its parent (the latter is backfilling) —mod.rs:222-362. - Execution — a collector dequeues a matching job (
job_queuepoll every 30 s), builds/fetches the artifact per theQueueRuntimeConfig, compiles and runs the benchmark group, and writes results to the DB. See job-queue.md and the deploying-collector guide. - Completion — the tick detects all (non-optional) jobs of the
in_progressrequest finished, marks itcompleted, and forTry/Masterrequests posts a comparison comment to the PR/MR with per-collector-tag and cross-machine comparison links (job_queue/mod.rs:538-639,site/src/github/comparison_summary.rs:26-134).Releaserequests get no comment.
5. Data model
A condensed view; full column definitions live in database/schema.md.
artifact— uniquely keyed by(name, tag, repo).nameis a SHA or tag;tagis the collector tag (defaultdefault);repois the repo key. The same commit on two machines is two rows.runtime_pstat_series— a(benchmark, target, metric)triple;runtime_pstatholds the per-(series, artifact, collection)measuredvalue(numeric) and optionaljson_value(structured reports, e.g.perf-recordentries).collector_config—(name unique, is_active, last_heartbeat_at, date_added, commit_sha).nameis the collector tag.job_queue—(request_tag, benchmark_group, tag)unique; carriescollector_name,status,retry,is_optional, and the serializedruntime_config. Status strings:queued/in_progress/success/failure.benchmark_request—(tag, commit_type, pr, repo, status, benchmark_groups, ...).commit_typeismaster/try/release.
Cross-references
- How to run benchmarks locally → local-benchmarking guide
- How to wire up GitCode/GitHub → platform-integration guide
- Config file reference → configuration.md
- Queue mechanics, retries, backfilling → job-queue.md
- Deployment model → deployment.md
- Comparison algorithm → comparison-analysis.md