From 2866df5a6d983e01a0cb6f0375e26ebda95312af Mon Sep 17 00:00:00 2001 From: helly25 <6420169+helly25@users.noreply.github.com> Date: Sat, 7 Nov 2026 12:46:05 +0000 Subject: [PATCH 01/20] Qualify extended production benchmark workloads across historical builds --- docs/benchmark-chart-sensitivity-audit.md | 135 +++ docs/benchmark-correctness-audit.md | 7 + docs/benchmark-extended-history-campaign.md | 125 +++ .../chart-sensitivity-audit-20261107.json | 310 +++++++ .../extended-history-revisions-20261107.json | 782 ++++++++++++++++++ ...xtended-history-viewer-check-20261107.json | 34 + tools/BUILD.bazel | 92 +++ tools/benchmark_extended.py | 206 +++++ tools/benchmark_extended_build.py | 130 +++ tools/benchmark_extended_build_test.py | 44 + tools/benchmark_extended_history.py | 283 +++++++ tools/benchmark_extended_history_test.py | 71 ++ tools/benchmark_extended_report.py | 189 +++++ tools/benchmark_extended_report_test.py | 67 ++ tools/benchmark_extended_test.py | 106 +++ 15 files changed, 2581 insertions(+) create mode 100644 docs/benchmark-chart-sensitivity-audit.md create mode 100644 docs/benchmark-extended-history-campaign.md create mode 100644 docs/benchmarks/chart-sensitivity-audit-20261107.json create mode 100644 docs/benchmarks/extended-history-revisions-20261107.json create mode 100644 docs/benchmarks/extended-history-viewer-check-20261107.json create mode 100644 tools/benchmark_extended.py create mode 100644 tools/benchmark_extended_build.py create mode 100644 tools/benchmark_extended_build_test.py create mode 100644 tools/benchmark_extended_history.py create mode 100644 tools/benchmark_extended_history_test.py create mode 100644 tools/benchmark_extended_report.py create mode 100644 tools/benchmark_extended_report_test.py create mode 100644 tools/benchmark_extended_test.py diff --git a/docs/benchmark-chart-sensitivity-audit.md b/docs/benchmark-chart-sensitivity-audit.md new file mode 100644 index 00000000000..28003f8ebbc --- /dev/null +++ b/docs/benchmark-chart-sensitivity-audit.md @@ -0,0 +1,135 @@ +# Benchmark chart sensitivity audit, 2026-11-07 + +The [extended history campaign](benchmark-extended-history-campaign.md) implements additional +workloads and qualifies them against 130 historical production builds on drogon. + +The standard landscape does not provide a sufficient view of XFF's optimization progress. +Its arithmetic reproduces the retained measurements, and its browser renderer responds to +changed timings. However, its workload and executable coverage exclude several large measured +improvements, and it does not show a controlled XFF-before/after comparison. A similar-looking +surface cannot establish that the optimizations were ineffective. + +## Evidence and boundaries + +Source: `ae8c5af3eb11dc8571f11db9b307b0db948f78c6` (#1130). +Pages: `153d58627f2132b838a091ffcfdb30dd49571b8b`. +The live `/xff/benchmarks/catalog.json` exactly matched this snapshot, including its SHA-256. +The catalog contains 528 entries; the browser's duplicate selection leaves 490 reports across +five datasets. See the [machine-readable results](benchmarks/chart-sensitivity-audit-20261107.json). + +The current-performance assessment excludes local Linux v2 at the user's direction because it +has not been measured recently. Its retained arithmetic checks remain historical evidence only; +its age and clipping statistics are not explanations for the current CI charts. + +An independent calculation selects each participant's recorded fastest samples and recomputes +`100 * (1 - XFF/reference)` and `-log10(XFF/reference)`. It checks the decoded packed figures +against raw records by task, tree, worker count, file count and reference tool, across all three +orders, both metrics and every available worker pair. All 3,178,656 plotted values match. +Catalog revisions and available catalog binary hashes also match their underlying reports. + +A headless Chromium control serves the retained site and its published JavaScript locally. +Selecting the previous and latest Linux versions loads different commits and values. Picked +surface values match the selected figures. A separately generated synthetic report halves every +XFF elapsed sample while preserving reference samples. All 468 default figure values change by +the expected formula `new_height = 50 + old_height / 2`, and the rendered canvas changes. +The synthetic data is an explicitly labelled sensitivity control; it is never published or +substituted for a historical measurement. + +This does not independently verify every historical executable, its compiler, its fixture oracle, +or the cause of historical timing variation. The claimed optimization results below come from +their existing qualification reports; those experiments were not rerun in this audit. + +## Published coverage is incomplete for the intended question + +The actively updated CI datasets contain 138 selected revisions per platform through #1122, +November 6. They do not retain every merge. The workload coverage and hosted-run comparisons +below assess these CI datasets; the older local datasets remain in the historical inventory. + +The chart measures the lean `//xff/cli:xff` production executable. It does not measure the +extended `xff_full` executable or exercise its archive features. Its command policy fixes +`--no-config --no-pager --color=never --sort=none --exact --case=sensitive --gitignore=off +--hidden`, uses the relative root `.`, and emits NUL-delimited paths with `-print0`. + +There are seven XFF tasks with reference comparisons: file discovery, `*.txt` names, two exact +content searches, and three ordered-subsequence fuzzy path filters. These yield nine task/reference +pairs. `files-safe` has XFF measurements but no reference, so `relative_results()` omits it from +the landscape. The three precomputed fuzzy-list tasks measure fzf alone. Fuzzy path filtering +does not exercise content-similarity scoring. + +Specific mismatches between demonstrated gains and the chart: + +| Change | Existing qualification evidence | Why the standard chart misses the gain | +| :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | +| #1105 archive directory ranges | Complete 100k-member TAR traversals fall from about 9-14 seconds to 94-187 milliseconds across both hosts | No archives; lean binary | +| #1116 empty CCTZ fragments | macOS timestamp-bearing metadata commands improve about 92% | No formatted timestamps; output is `-print0` | +| #1091 uniform native case | Linux broad 100k-file name search falls from about 129 ms to 44 ms with one worker | Every chart command passes `--exact`, bypassing native-case lookup | +| #1090 names-only listing paths | Broad absolute-root listings improve about 9-14%; short relative-root controls are mostly neutral on Mac and 1-2% slower on Linux | Chart always uses the short relative root `.` | +| #1094 compact traversal metadata | Broad native listings improve about 5-6% on Mac and 8-9% on Linux; memory improves too | This path is exercised, but the chart shows only competitor-relative elapsed time, with no uncertainty or memory history | + +Sources: [archive ranges](benchmarks/archive-directory-range-20261105.md), +[CCTZ](benchmarks/cctz-empty-format-20261105.md), +[native case](benchmarks/uniform-native-case-20261104.md), +[listing paths](benchmarks/native-name-paths-20261104.md), and +[compact metadata](benchmarks/compact-traversal-metadata-20261104.md). +These are workload-specific results, not additive percentages or universal binary speedups. + +## Movement exists, but the chart is a poor progress measure + +For Linux broad/100k/one-worker `files` versus rg, the published #1093 report records XFF at +63.655 ms and rg at 47.570 ms; #1094 records 59.888 ms and 48.282 ms. The chart value moves +from -33.814% to -24.037%, exactly as the raw data requires. This is an example of actual chart +movement, not a paired causal estimate of #1094: these are different hosted runs. + +Six reports (#1102, #1103, #1104, #1105, #1117 and #1107) record the same Linux executable +SHA-256 `09c997ab01d2d7dfe916bf1cced7b54757c6b6b25f8d2a9743812e9db23efb51` and the same +OS release. Yet that same listing cell ranges from 57.341 to 64.831 ms, and its XFF/rg ratio +from 1.2186 to 1.2930. This is observed variation across hosted runs of an unchanged binary; +it cannot be explained by an XFF code improvement between those measurements. It does not +identify the cause of that variation or estimate uncertainty for every workload. + +The surface shows XFF/reference in each run, not XFF/new versus XFF/old. Reference normalization +adds a corrected time to the hover details; it intentionally does not change the ratio or surface. +Thus changing the Timings selector does not change geometry. Hosted sample aggregation pools +three hosts' samples and selects fastest samples separately per participant; the selected XFF +and reference host contributions can differ. Neither that estimator nor a reference ratio is a +substitute for an interleaved old/new experiment with uncertainty. + +The latest CI default views have no clipped points, so clipping does not explain their apparent +lack of movement. As a general display constraint, the default percentage range is +/-100 with +capping: any XFF/reference ratio >=2 reaches the same bottom boundary, and percentage gains +approach +100 asymptotically. Logarithmic scale can expose differences if its selected range +includes them. Auto range rescales each report and is unsuitable for judging uniform changes by +shape alone. These general constraints are not evidence of clipping in the current CI views. + +Recent published Similarity order is shared within compatible history after #1093; Average order +still changes with each report. A shared task order helps track cells but does not supply missing +workloads, new measurements or a historical baseline. + +## Changes needed before treating this as an optimization dashboard + +1. Show each dataset's latest measured source and its distance behind current main prominently. + Give the standard landscape an explicit workload scope and identify the measured binary. +2. Retain a permanent, versioned suite of production commands covering ordinary native-case + and exact-case discovery, relative and absolute roots, metadata/time output, summaries, + content search, similarity, comparisons, and full-binary archive traversal. Keep the existing + competitor suite as one view; do not silently change its historical workload definition. +3. Measure selected old/new production binaries interleaved on the same host and fixture, with + an identical-binary control. Publish absolute elapsed time, first-result latency, CPU and memory, + paired changes and uncertainty. Preserve worker budgets, raw samples and executable identities. +4. Display XFF-only workloads even when no competing tool implements the same operation. Add an + XFF-before/after view with fixed task positions and scales; show unavailable cells and clipping + counts. Keep competitor-relative values and reference corrections explicitly labelled. +5. Link each claimed speedup to its exercised workload and add that workload to continuing + regression coverage. Qualify a small representative panel before expanding historical runs. + +No new benchmark campaign is needed to establish the coverage and presentation defects above. +Repeating the current matrix alone would continue to miss archive, timestamp and native-case gains. + +## Retained audit artifacts + +The local evidence directory is `/private/tmp/xff-chart-evidence-20261107/`: +the extracted Pages snapshot, live catalog, selected records, independent `audit.py`, complete +`audit-summary.json`, per-cell `cells.csv`, `browser-check.mjs`, browser results and original versus +synthetic screenshots. Their hashes and representative raw-derived rows are in the linked JSON. +Browser controls used the existing installed Playwright/Chromium; no production files or published +measurements were changed. The temporary server and browser were closed after verification. diff --git a/docs/benchmark-correctness-audit.md b/docs/benchmark-correctness-audit.md index b03f336aca8..defa31a84b7 100644 --- a/docs/benchmark-correctness-audit.md +++ b/docs/benchmark-correctness-audit.md @@ -1,5 +1,12 @@ # Benchmark correctness audit and native investigation +The [2026-11-07 chart sensitivity audit](benchmark-chart-sensitivity-audit.md) revisits whether +the published landscape can demonstrate optimization progress. Its raw-to-figure arithmetic and +browser sensitivity checks pass, but it identifies workloads that bypass major optimized paths, +omitted XFF-only tasks, and limits of competitor-relative presentation in the current CI charts. +The current assessment excludes the old local Linux v2 dataset. +The earlier consistency checks below do not establish that the benchmark covers those improvements. + ## Scope and status Implementation and native-session handoff: [PR #990](https://github.com/mboworks/xff/pull/990), diff --git a/docs/benchmark-extended-history-campaign.md b/docs/benchmark-extended-history-campaign.md new file mode 100644 index 00000000000..ee0c97e9d90 --- /dev/null +++ b/docs/benchmark-extended-history-campaign.md @@ -0,0 +1,125 @@ +# Extended benchmark history qualification + +This campaign qualifies additional CLI workloads against the last 130 merged PRs at +`ae8c5af3eb11dc8571f11db9b307b0db948f78c6` (PR #1130). Its oldest revision is +`21c7f3656b005b23113d936c1cd2ca0fd2221ab2` (PR #977). The manifest selects first-parent +commits with PR numbers; PR numbers are not a contiguous range. +The [frozen revision manifest](benchmarks/extended-history-revisions-20261107.json) is retained +with the implementation. + +It follows the [chart sensitivity audit](benchmark-chart-sensitivity-audit.md). These workloads +have their own recipe, `extended-production-v1`, and must remain a separate dataset from core +measurements. They use the existing 3D visualization framework. The stale local Linux v2 dataset +is outside this investigation. + +## Workloads fixed before collecting timings + +| Task | Operation | Equivalent traditional tool | Reason for inclusion | +| :-------------- | :--------------------------------------------------------- | :-------------------------- | :------------------------------------------------- | +| `files-exact` | List regular files with NUL termination | GNU find | Simple traversal control | +| `name-native` | Native-case `*.txt` match under an absolute root | GNU find | Native-case discovery and absolute-root work | +| `metadata-time` | Type, name and size filters; print path, size and UTC date | GNU find | Metadata and timestamp formatting | +| `content-regex` | Match a status regex in text files | ripgrep | Traversal, filename filtering and content matching | +| `archive-tar` | List matching regular-file members in a TAR | GNU tar | Archive indexing and virtual directory traversal | + +Each task has broad/deep fixtures and one/three allowed physical CPU cores. Native tasks use +100, 10,000 and 100,000 files; archives use 100, 1,000 and 10,000 members: 60 cells per revision, +7,800 historical cells in total. Missing sizes remain missing in the renderer. + +Fixtures contain deterministic ASCII names and text, fixed UTC modification times and modes, +matching and nonmatching files, and 256-byte/8-KiB contents. Archive fixtures contain regular +members without explicit directory entries. Fixture contents and metadata are verified before +and after collection. Native fixtures require Linux case-sensitive tmpfs; this qualification +does not establish the same case semantics on a macOS filesystem. + +The TAR reference transforms displayed names to the same `fixture.tar/member` spelling as XFF. +Native references use identical roots and output delimiters. Every invocation must succeed +without diagnostics and produce the exact expected multiset of records. Duplicate, missing or +extra records invalidate the invocation. Expected outputs come from the fixture recipe, rather +than another measured tool's output. + +## Build and measurement contract + +- Build every exact historical checkout with its own configuration and pinned dependencies: + `//xff/cli:xff_full --config=clang_release --config=xff_full`. +- Disable system/home Bazel rc files; reject dirty trees and workspace `.bazelrc.user` overrides. +- Resolve the configured executable with `cquery` using the same options, then immediately copy + it to its revision directory. Retain source/tree identity, SHA-256, build logs and link actions. +- Require ThinLTO link evidence. Historical compiler/dependency changes are part of this + production-history comparison; results cannot automatically be attributed solely to XFF source. +- Finish every build, including the native resource launcher, before accepting timing samples. +- Keep fixtures on `/dev/shm` tmpfs. The disk holding binaries/logs/results is not the measured + fixture filesystem. No disk-storage throughput conclusion follows from these measurements. +- Rotate historical XFF, fixed PR #1130 XFF, and the traditional tool through each execution + position. Use one correctness-checked warm-up round and nine measured rounds per cell. +- Use the existing chart estimator, mean of the fastest seven of nine. Retain all nine samples + and warm-ups. The existing native launcher measures command CPU, RSS, wall time, output bytes + and first-output time. Python validation/serialization occurs after the timed interval. +- Record affinity, commands, locale, timezone, fixture identity, output hashes/counts, host + pressure/load/memory context, binary hashes and accounting method. Timeouts terminate the + worker process group. Failed attempts remain separate from completed cells. +- Resume only an identical contract. Interrupted cells restart as new attempts. Executable or + fixture identity drift invalidates a campaign instead of silently combining populations. + +The fixed-current participant provides a nearby control for host load. A historical binary that +is byte-identical to current provides an identical-binary noise control. Interleaving reduces +shared host effects; workload-dependent interference can remain. The analysis also computes a +paired-round bootstrap interval using all nine rounds. That interval describes within-cell +variability, not independent-machine reproducibility. + +## Reproduction + +The tools have Bazel owners and support direct Python 3.13 invocation. Building requires an +isolated checkout at `BUILD_ROOT/checkout` and a JSON revision list containing `sha`, `pr`, `date` +and `subject`. Retain this manifest. + +```sh +python3.13 tools/benchmark_extended_build.py \ + --root=BUILD_ROOT --revisions=revisions.json --disk-cache=BAZEL_DISK_CACHE + +python3.13 tools/benchmark_extended_history.py \ + --root=MEASUREMENT_ROOT --build-root=BUILD_ROOT --revisions=revisions.json \ + --fixture=/dev/shm/xff-extended-fixtures --resource-launcher=NATIVE_LAUNCHER + +python3.13 tools/benchmark_extended_report.py \ + --campaign=MEASUREMENT_ROOT --output=REPORT_DIRECTORY \ + --renderer-js=THREE_LANDSCAPE_JS +``` + +The report exports every cell to CSV, endpoint summaries/control noise to JSON, and two datasets +using the existing 3D history viewer: traditional tools and fixed-current XFF comparisons. Serve +the report directory over HTTP for JSON fetches. `--allow-partial` is for monitoring; the default +refuses incomplete campaigns. + +The historical LLVM 22 linker on drogon requires ICU 70. System installation required interactive +sudo authentication, so the official Ubuntu `libicu70_70.1-2ubuntu1_amd64.deb` was extracted into +the campaign's `compat` directory. `--build-library-path=PATH` supplies those libraries to build +actions and records their hashes. XFF itself does not link ICU. The package SHA-256 is +`223c1e6cebf2a6748637303227d8b84337c14a2d30eacbc46a68d02557dcff3e`. +The package, download URL, hashes and library list are retained in `installed-dependencies.json`. + +## Evidence and status + +On `drogon.boerger.online`, the root is `/home/marcus/Documents/xff-chart-campaign-20261107`: + +- `xff-extended-history-revisions.json`: frozen 130-revision selection. +- `qualified/binaries/SHA/`: production executable and build/link evidence. +- `qualified/build-status.json`: build progress; initial failed dependency attempts are retained + separately under the campaign root's `binaries` directory. +- `preflight-full.json`: 240 full-size output checks across both endpoints and their references. +- `preflight-native-worker.json`: checks through the actual accounting worker; preparation + timings are explicitly excluded because builds were running concurrently. +- `measurements/contract.json`, `fixtures.json`, `progress.json`: frozen population and progress. +- `measurements/cells/SHA/TASK/SHAPE/FILES/CPUS/complete.json`: accepted raw cell data. +- `measurements/cells/.../attempts/`: warm-ups, samples and failure evidence. +- `qualified/logs/build-campaign.log` and `logs/measurements.log`: progress logs. + +The 240 endpoint functional checks and native-worker checks passed. Historical build/measurement +collection is in progress; these functional checks establish no performance improvement. +Select CI workloads from completed results, retain the simple control, and report flat or +regressing cases alongside improvements. + +The [synthetic viewer check](benchmarks/extended-history-viewer-check-20261107.json) verifies +both exported dataset views in Chromium. Both historical versions produce their exact expected +heights; 60 measured points remain present and all 20 unavailable cells remain empty. This +artifact contains synthetic renderer checks only, not performance measurements. diff --git a/docs/benchmarks/chart-sensitivity-audit-20261107.json b/docs/benchmarks/chart-sensitivity-audit-20261107.json new file mode 100644 index 00000000000..9db705d1fca --- /dev/null +++ b/docs/benchmarks/chart-sensitivity-audit-20261107.json @@ -0,0 +1,310 @@ +{ + "pages_commit": "153d58627f2132b838a091ffcfdb30dd49571b8b", + "source_commit": "ae8c5af3eb11dc8571f11db9b307b0db948f78c6", + "selected_reports": 490, + "checked_points": 3178656, + "errors": [], + "live_catalog_sha256": "bdfe8b375ded842ddea815f8001b816d0ad3faf31a5c3b0855f21193ba5029f8", + "live_catalog_matches_snapshot": true, + "scope": "Recorded sample to chart arithmetic and browser sensitivity; no new performance collection or full executable provenance re-verification.", + "current_performance_assessment": { + "datasets": ["linux / x86_64", "macos / arm64"], + "excluded_at_user_direction": "Local / linux-zen5 / x86_64 / broad/v2 + deep/v2", + "reason": "No recent measurements; retained Linux v2 arithmetic and clipping statistics are historical evidence only and do not explain current CI chart behavior." + }, + "series": [ + { + "dataset": "Local / linux-zen5 / x86_64 / broad/v1 + deep/v1", + "reports": 70, + "distinct_binary_hashes": 38, + "latest": { + "commit": "c33efe99d0df0b4866a9f77fde71dde9959d3cdb", + "date": "2026-10-06T02:40:08Z", + "links": [ + { + "label": "PR #981", + "href": "https://github.com/mboworks/xff/pull/981" + } + ], + "report": "local/linux-zen5/04f25c4ca10d9ab4894b96320aa99eb84ec0ecf45368df692ed4002baf980cb2/c33efe99d0df0b4866a9f77fde71dde9959d3cdb/", + "default_points": 468, + "default_capped": 0, + "half_time_still_capped": 0, + "omitted_xff_tasks": { + "files-safe": 78 + } + }, + "mainline_commits_after_latest": 128 + }, + { + "dataset": "Local / linux-zen5 / x86_64 / broad/v2 + deep/v2", + "reports": 72, + "distinct_binary_hashes": 38, + "latest": { + "commit": "9210100af8007a2f17b22597a349714d9e6069e1", + "date": "2026-10-06T22:08:43Z", + "links": [ + { + "label": "PR #985", + "href": "https://github.com/mboworks/xff/pull/985" + } + ], + "report": "local/linux-zen5/b7bb50f259fd384e20e29cc69874178dc2ac9221137017998cbcc709ed87f6f9/9210100af8007a2f17b22597a349714d9e6069e1/", + "default_points": 468, + "default_capped": 42, + "half_time_still_capped": 8, + "omitted_xff_tasks": { + "files-safe": 78 + } + }, + "mainline_commits_after_latest": 126 + }, + { + "dataset": "Local / macos-m5-pro / arm64 / broad/v1 + deep/v1", + "reports": 72, + "distinct_binary_hashes": 41, + "latest": { + "commit": "9210100af8007a2f17b22597a349714d9e6069e1", + "date": "2026-10-06T22:08:43Z", + "links": [ + { + "label": "PR #985", + "href": "https://github.com/mboworks/xff/pull/985" + } + ], + "report": "local/macos-m5-pro/14620686da0d294b9bf80298fa064467e2fa3e45923e4b827ec34e77b34b9dde/9210100af8007a2f17b22597a349714d9e6069e1/", + "default_points": 468, + "default_capped": 0, + "half_time_still_capped": 0, + "omitted_xff_tasks": { + "files-safe": 78 + } + }, + "mainline_commits_after_latest": 126 + }, + { + "dataset": "linux / x86_64", + "reports": 138, + "distinct_binary_hashes": 80, + "latest": { + "commit": "0e95e191ba7d7ee3769217e7fbf82a825ff9b90d", + "date": "2026-11-06T19:06:09Z", + "links": [ + { + "label": "PR #1122", + "href": "https://github.com/mboworks/xff/pull/1122" + } + ], + "report": "runs/42276661623/1/linux/", + "default_points": 468, + "default_capped": 0, + "half_time_still_capped": 0, + "omitted_xff_tasks": { + "files-safe": 52 + } + }, + "mainline_commits_after_latest": 9 + }, + { + "dataset": "macos / arm64", + "reports": 138, + "distinct_binary_hashes": 138, + "latest": { + "commit": "0e95e191ba7d7ee3769217e7fbf82a825ff9b90d", + "date": "2026-11-06T19:06:09Z", + "links": [ + { + "label": "PR #1122", + "href": "https://github.com/mboworks/xff/pull/1122" + } + ], + "report": "runs/42276661623/1/macos/", + "default_points": 468, + "default_capped": 0, + "half_time_still_capped": 0, + "omitted_xff_tasks": { + "files-safe": 52 + } + }, + "mainline_commits_after_latest": 9 + } + ], + "browser": { + "synthetic_control": "halve every XFF elapsed sample; reference samples unchanged", + "errors": [], + "latest": { + "commit": "0e95e191ba7d7ee3769217e7fbf82a825ff9b90d", + "version": "138 of 138", + "metric": "percent", + "range": "100", + "picks": 74, + "maxError": 0, + "heightRange": [-49.41909765688375, 83.75368932652991] + }, + "previous": { + "commit": "2487927cc6b1de326ea3c6c058dc493214354bec", + "version": "137 of 138", + "metric": "percent", + "range": "100", + "picks": 75, + "maxError": 0 + }, + "counterfactual": { + "checkedPoints": 468, + "maxError": 1.4210854715202004e-14, + "picks": 66, + "originalScreenshot": "554cb3e9ff0d7efb57cd143a6eafeac64a51ba2b0a633616f79c65d7cf0069ad", + "syntheticScreenshot": "f983742aa29228392c8cb9792b0ca1deef7134c8ca8517e1413504f876da93c0" + } + }, + "linux_1093_1094": [ + { + "platform": "linux / x86_64", + "date": "2026-11-04T23:39:42Z", + "commit": "a7a6125a9358f1020fc914d6c91bbf8c6e66392f", + "report": "runs/41935477473/1/linux/", + "binary": "c4a734d126d335b293510ecb77d0f7f59aea19b942bb200a7ce5434ba56b8a33", + "dataset": "broad", + "task": "files", + "cpus": "1", + "files": "100000", + "reference": "rg", + "xff_ms": "63.65512385713958", + "reference_ms": "47.569683285709225", + "ratio": "1.3381447901349115", + "height": "-33.81447901349115", + "fixture": "4fec4112050c07e58e1c6d30ba3049d0868d9cf576a1ebab6c5bff793999b025" + }, + { + "platform": "linux / x86_64", + "date": "2026-11-05T01:46:19Z", + "commit": "bb0185a0379075480eb8b1499f5bc5ff8cfafaa8", + "report": "runs/41950760925/1/linux/", + "binary": "b1a7bea12f32f8ded3413f4b6b99a7720f17e24227c9135b284d98f50bcf1edb", + "dataset": "broad", + "task": "files", + "cpus": "1", + "files": "100000", + "reference": "rg", + "xff_ms": "59.88791642857905", + "reference_ms": "48.28247728571", + "ratio": "1.2403654450908606", + "height": "-24.036544509086056", + "fixture": "4fec4112050c07e58e1c6d30ba3049d0868d9cf576a1ebab6c5bff793999b025" + } + ], + "linux_identical_binary_control": [ + { + "platform": "linux / x86_64", + "date": "2026-11-05T17:08:19Z", + "commit": "55ea67e3f06e5055b43d8cb780661901731592f2", + "report": "runs/42071636652/1/linux/", + "binary": "09c997ab01d2d7dfe916bf1cced7b54757c6b6b25f8d2a9743812e9db23efb51", + "dataset": "broad", + "task": "files", + "cpus": "1", + "files": "100000", + "reference": "rg", + "xff_ms": "57.341299714279", + "reference_ms": "47.05371942858148", + "ratio": "1.2186347946693585", + "height": "-21.863479466935853", + "fixture": "4fec4112050c07e58e1c6d30ba3049d0868d9cf576a1ebab6c5bff793999b025" + }, + { + "platform": "linux / x86_64", + "date": "2026-11-05T18:53:16Z", + "commit": "f3ec0faf7a1bb16ddb0b3b8bcee2c3e5bd970df2", + "report": "runs/42088571729/1/linux/", + "binary": "09c997ab01d2d7dfe916bf1cced7b54757c6b6b25f8d2a9743812e9db23efb51", + "dataset": "broad", + "task": "files", + "cpus": "1", + "files": "100000", + "reference": "rg", + "xff_ms": "64.83135542858268", + "reference_ms": "51.71553057143846", + "ratio": "1.2536148176808584", + "height": "-25.361481768085838", + "fixture": "4fec4112050c07e58e1c6d30ba3049d0868d9cf576a1ebab6c5bff793999b025" + }, + { + "platform": "linux / x86_64", + "date": "2026-11-05T20:46:57Z", + "commit": "455dcd8eb5dd98b09f3117f5316136b6d43cfd8e", + "report": "runs/42106576310/1/linux/", + "binary": "09c997ab01d2d7dfe916bf1cced7b54757c6b6b25f8d2a9743812e9db23efb51", + "dataset": "broad", + "task": "files", + "cpus": "1", + "files": "100000", + "reference": "rg", + "xff_ms": "62.68778028572797", + "reference_ms": "48.794140857138146", + "ratio": "1.284739913123346", + "height": "-28.47399131233459", + "fixture": "4fec4112050c07e58e1c6d30ba3049d0868d9cf576a1ebab6c5bff793999b025" + }, + { + "platform": "linux / x86_64", + "date": "2026-11-05T22:29:23Z", + "commit": "245e74ff6cbe6c0f84a074be669c60ac7cbc5e8f", + "report": "runs/42121915666/1/linux/", + "binary": "09c997ab01d2d7dfe916bf1cced7b54757c6b6b25f8d2a9743812e9db23efb51", + "dataset": "broad", + "task": "files", + "cpus": "1", + "files": "100000", + "reference": "rg", + "xff_ms": "60.077836714283094", + "reference_ms": "48.359569285712006", + "ratio": "1.2423153804232347", + "height": "-24.231538042323475", + "fixture": "4fec4112050c07e58e1c6d30ba3049d0868d9cf576a1ebab6c5bff793999b025" + }, + { + "platform": "linux / x86_64", + "date": "2026-11-06T00:26:31Z", + "commit": "b60cf7a5a92609f9fadddd4759d3c55e755a69b6", + "report": "runs/42136840761/1/linux/", + "binary": "09c997ab01d2d7dfe916bf1cced7b54757c6b6b25f8d2a9743812e9db23efb51", + "dataset": "broad", + "task": "files", + "cpus": "1", + "files": "100000", + "reference": "rg", + "xff_ms": "61.81004171427925", + "reference_ms": "50.18462614285519", + "ratio": "1.2316529276980412", + "height": "-23.165292769804125", + "fixture": "4fec4112050c07e58e1c6d30ba3049d0868d9cf576a1ebab6c5bff793999b025" + }, + { + "platform": "linux / x86_64", + "date": "2026-11-06T03:31:50Z", + "commit": "ccb1f0a202ed59b30246c14e424a400e47acc447", + "report": "runs/42157108661/1/linux/", + "binary": "09c997ab01d2d7dfe916bf1cced7b54757c6b6b25f8d2a9743812e9db23efb51", + "dataset": "broad", + "task": "files", + "cpus": "1", + "files": "100000", + "reference": "rg", + "xff_ms": "63.105239285716515", + "reference_ms": "48.80616985714629", + "ratio": "1.2929766763182406", + "height": "-29.297667631824066", + "fixture": "4fec4112050c07e58e1c6d30ba3049d0868d9cf576a1ebab6c5bff793999b025" + } + ], + "evidence_directory": "/private/tmp/xff-chart-evidence-20261107", + "artifact_hashes": { + "audit.py": "5109db79d01589b40c626e86618dac8602dcf0f3c596ebbf88eb66d7a5e10941", + "audit-summary.json": "af8f443033f40a38320b1f5192561423d73638750e886e7d4629b43ad386997f", + "cells.csv": "8a7dc35d997cfbd52507b2d6b3db3bd1885a3bba4915962cf7bf477c18661a02", + "browser-check.mjs": "35be5509a59bff8ea86b10b853d9fdfded7a6bf6d7ea61147317510004d21d7d", + "browser-check.json": "73b1fc94408f21998f7f4c42e3c26f97f7deda04387be00274e0144b0b0a1c58", + "browser-original.png": "554cb3e9ff0d7efb57cd143a6eafeac64a51ba2b0a633616f79c65d7cf0069ad", + "browser-synthetic-half-time.png": "f983742aa29228392c8cb9792b0ca1deef7134c8ca8517e1413504f876da93c0" + } +} diff --git a/docs/benchmarks/extended-history-revisions-20261107.json b/docs/benchmarks/extended-history-revisions-20261107.json new file mode 100644 index 00000000000..bbfdaab8fa7 --- /dev/null +++ b/docs/benchmarks/extended-history-revisions-20261107.json @@ -0,0 +1,782 @@ +[ + { + "sha": "21c7f3656b005b23113d936c1cd2ca0fd2221ab2", + "date": "2026-10-06T02:23:48+01:00", + "subject": "Prepare peer and expected-hash field templates once (#977)", + "pr": 977 + }, + { + "sha": "c33efe99d0df0b4866a9f77fde71dde9959d3cdb", + "date": "2026-10-06T03:40:08+01:00", + "subject": "Adapt benchmark shard count to runner CPU agreement (#981)", + "pr": 981 + }, + { + "sha": "103fbf65b22979f75f5adbac67a53f15cf74d03e", + "date": "2026-10-06T21:09:52+01:00", + "subject": "Improve local benchmark backfill and upload workflow (#982)", + "pr": 982 + }, + { + "sha": "9210100af8007a2f17b22597a349714d9e6069e1", + "date": "2026-10-06T23:08:43+01:00", + "subject": "Add versioned prepared benchmark layouts (#985)", + "pr": 985 + }, + { + "sha": "61ab1ce41300aa785d6beafb46c29b29dc832b8d", + "date": "2026-10-07T22:29:50+01:00", + "subject": "Distinguish benchmark layout versions in explorer (#986)", + "pr": 986 + }, + { + "sha": "4bce0bb39186d1dfbe122038f17ef660447599c6", + "date": "2026-10-07T23:23:39+01:00", + "subject": "Clarify benchmark dataset selection and upload batches (#987)", + "pr": 987 + }, + { + "sha": "fa41587198981a5619e408c41be80cb22b8dd439", + "date": "2026-10-09T17:03:40+01:00", + "subject": "Refine benchmark viewer cards and threshold controls (#988)", + "pr": 988 + }, + { + "sha": "772994ab7905be77915978f06ea90ae5934aaeef", + "date": "2026-10-09T18:20:37+01:00", + "subject": "Call benchmark viewer measurement series Dataset (#989)", + "pr": 989 + }, + { + "sha": "4ea895f63106f05df7c90b629d20433ae1e03016", + "date": "2026-10-09T22:05:33+01:00", + "subject": "Verify benchmark build provenance and show binary evidence in the viewer (#990)", + "pr": 990 + }, + { + "sha": "dac3747d63cad713def0b949a934dfe36f82da63", + "date": "2026-10-10T11:32:31+01:00", + "subject": "Enable opt-in native Linux benchmark performance counters (#993)", + "pr": 993 + }, + { + "sha": "88d4facd15ebd00acf749222b3028de2e8916970", + "date": "2026-10-10T12:44:39+01:00", + "subject": "Correct native benchmark accounting and retain audit evidence (#994)", + "pr": 994 + }, + { + "sha": "bbc0bf9376c7fc41fe75094998c3c7e74bd02e94", + "date": "2026-10-10T13:42:01+01:00", + "subject": "Fix benchmark launcher staging and consolidate audit preparation (#999)", + "pr": 999 + }, + { + "sha": "b137c8a6800aa0c1d6f2d67342f291b25783747f", + "date": "2026-10-10T17:31:06+01:00", + "subject": "Publish executor dispatch evidence and simplify history chart folding (#1003)", + "pr": 1003 + }, + { + "sha": "d73eea93ac97f401fe12ba2ba139eb6b8601ec19", + "date": "2026-10-14T21:35:19+01:00", + "subject": "Bump rules_cc from 0.2.25 to 0.2.26 (#1004)", + "pr": 1004 + }, + { + "sha": "20095dd53c31e510aac2256fc93d34026e4f463c", + "date": "2026-10-14T21:58:37Z", + "subject": "Bump pcre2 from 10.48 to 10.49 (#1006)", + "pr": 1006 + }, + { + "sha": "33a01e13d7cd27ee7f866802fc2f74998fdcaabb", + "date": "2026-10-15T00:16:51+01:00", + "subject": "Bump rules_python from 2.3.4 to 2.4.2 (#1007)", + "pr": 1007 + }, + { + "sha": "bfe77198c06bc1e4a23e23ea292ab47cb4b6a0e4", + "date": "2026-10-15T00:28:32Z", + "subject": "Bump zstd from 1.5.7.bcr.2 to 1.5.7.bcr.3 (#1005)", + "pr": 1005 + }, + { + "sha": "1f85d90e3441737304d9f3647523cfc408ca54a9", + "date": "2026-10-15T03:34:18+01:00", + "subject": "Handle contract drift in adaptive benchmark sampling (#1009)", + "pr": 1009 + }, + { + "sha": "a5f9c9ec07419101cfe73ec4b42c3c29c529edad", + "date": "2026-10-17T10:57:28+01:00", + "subject": "Fix clang-tidy source queries and batch preparation builds (#1010)", + "pr": 1010 + }, + { + "sha": "a21ada79bbe9cad232a174cfdb4e8923ed891f2a", + "date": "2026-10-17T12:38:48+01:00", + "subject": "Bump toolchains_llvm from 1.11.1 to 1.11.3 (#1008)", + "pr": 1008 + }, + { + "sha": "ae62c828a3f3502a9bcf4805188913a1aaaf264c", + "date": "2026-10-18T23:31:25+01:00", + "subject": "Resolve golden test inputs through runfiles lookup (#1012)", + "pr": 1012 + }, + { + "sha": "801087f3e9a8bf192928896c7f24c369003d1e7b", + "date": "2026-10-23T02:56:26+01:00", + "subject": "Follow stable LLVM 23 releases from the pinned catalogue (#1011)", + "pr": 1011 + }, + { + "sha": "3dbc47cc2a1d84c0e6b60f0a497c1d3ce160351f", + "date": "2026-10-23T04:10:00+01:00", + "subject": "Bump setup-bazel to 0.19.1 and align pin checks (#1013)", + "pr": 1013 + }, + { + "sha": "8e95f5546187b2a6f4ec165af9cf794af18ac4a1", + "date": "2026-10-27T01:23:53Z", + "subject": "Add reverse diffs and configurable patch paths (#1019)", + "pr": 1019 + }, + { + "sha": "1642f49d7b400596af3ed627f5b9f42cc24e4237", + "date": "2026-10-27T02:19:56Z", + "subject": "Allow stamped release versions in the rg alias test (#1021)", + "pr": 1021 + }, + { + "sha": "eaa034527a286ed87f1f74b8e88ba5b7007fb31a", + "date": "2026-10-27T06:43:43Z", + "subject": "Open CHANGELOG section for 0.10.0 (#1020)", + "pr": 1020 + }, + { + "sha": "02292572cac61101036c032ece8e11675d580d7e", + "date": "2026-10-28T01:21:30Z", + "subject": "Add selectable ignore policies to tree comparison (#1022)", + "pr": 1022 + }, + { + "sha": "b52571f81b8ecec116a4249f51b7d5e72175248c", + "date": "2026-10-28T23:28:49Z", + "subject": "Unify generated help references and remove duplicate navigation (#1023)", + "pr": 1023 + }, + { + "sha": "f0407980edd2bc2497dc0f406b2fed1977caaaea", + "date": "2026-10-29T02:06:19Z", + "subject": "Apply explicit ignore files to both comparison roots (#1024)", + "pr": 1024 + }, + { + "sha": "4c87962565391caf32b669c6a8a55d7495999921", + "date": "2026-10-29T02:52:41Z", + "subject": "Produce complete Git patches for tree comparisons (#1025)", + "pr": 1025 + }, + { + "sha": "b7fd2c2d0c5d50d8e5895f36fe39f802ac2dcb76", + "date": "2026-10-29T03:30:29Z", + "subject": "Place comparison features under the 0.10.0 release (#1026)", + "pr": 1026 + }, + { + "sha": "d406f4132d067d4e87a8df1426753a7d0203abd6", + "date": "2026-10-29T04:10:06Z", + "subject": "Honor no-ignore for ordinary explicit ignore files (#1027)", + "pr": 1027 + }, + { + "sha": "d47b00bfeeb3b98606d806c4b21664870d3ddfaa", + "date": "2026-10-29T04:56:29Z", + "subject": "Diagnose ineffective file-diff normalization before actions (#1028)", + "pr": 1028 + }, + { + "sha": "3292b6f308ab92f61d8575c95ee2cef2c41e4205", + "date": "2026-10-29T05:34:26Z", + "subject": "Round-trip staged release comparison patches through Git (#1029)", + "pr": 1029 + }, + { + "sha": "96174bbdd64ab2325224f47bab43888fa224595b", + "date": "2026-10-29T21:21:24Z", + "subject": "Open CHANGELOG section for 0.11.0 (#1030)", + "pr": 1030 + }, + { + "sha": "bfae14510a3e302f524b96719a695ca4bb07ffbd", + "date": "2026-10-30T23:45:26Z", + "subject": "Recover the original 0.9.0 release without moving its tag (#1031)", + "pr": 1031 + }, + { + "sha": "3803544ef4a24e0a72e54a317ee5091638bc70ae", + "date": "2026-10-31T15:27:47Z", + "subject": "Upgrade five dependencies and fix Bazel integration (#1032)", + "pr": 1032 + }, + { + "sha": "a721b98a306dd9021d31bbc485ae4c7c82ceba00", + "date": "2026-10-31T19:59:00Z", + "subject": "Upgrade bashtest to 0.7.1 and remove launcher workaround (#1033)", + "pr": 1033 + }, + { + "sha": "974d137026818bba1c1deaf6cfc4fffe676b314e", + "date": "2026-10-31T22:11:51Z", + "subject": "Avoid Abseil hardware-clock calibration during worker startup (#1034)", + "pr": 1034 + }, + { + "sha": "66302319f016c5f459b0260a2e727bd32073ed24", + "date": "2026-11-01T10:43:47Z", + "subject": "Clarify benchmark uploader revision overlap (#1036)", + "pr": 1036 + }, + { + "sha": "b68a9c3a58abd219a5043d5737e23f6ebe5ee26c", + "date": "2026-11-01T11:35:52Z", + "subject": "Make local benchmark uploads and publication more reliable (#1038)", + "pr": 1038 + }, + { + "sha": "8ff28cde9c67bd498f9016935da01506ffb5845c", + "date": "2026-11-01T12:37:28Z", + "subject": "Isolate executor diagnostics and query download support (#1035)", + "pr": 1035 + }, + { + "sha": "473f73452a6b47d7a3b522f2cc6128c4fafa86d8", + "date": "2026-11-01T13:41:30Z", + "subject": "Avoid temporary key construction and retain executor audit evidence (#1037)", + "pr": 1037 + }, + { + "sha": "7b72a5f0a52e838dfe0b199ea0386c8e6b3dcd39", + "date": "2026-11-01T18:38:17Z", + "subject": "Bound sibling reads on the existing directory pool (#1039)", + "pr": 1039 + }, + { + "sha": "16e70cb97de93c7ab4ae8c9e990e1842d50cc528", + "date": "2026-11-01T21:40:15Z", + "subject": "Use fixed 1 MiB blocks for retained collection text (#1040)", + "pr": 1040 + }, + { + "sha": "cf23601ab3533c2acb938acda1439dcd69091f61", + "date": "2026-11-01T23:34:14Z", + "subject": "Share collection name and root storage with owned paths (#1041)", + "pr": 1041 + }, + { + "sha": "2b21790502fd6bf9b6e1afb53cc1444cf140f296", + "date": "2026-11-02T00:25:41Z", + "subject": "Prepare simple native globs and avoid pattern copies (#1042)", + "pr": 1042 + }, + { + "sha": "9e4338a6ea3b47431e612a1fa24b818b3269193d", + "date": "2026-11-02T01:26:44Z", + "subject": "Reuse fuzzy score rows and cache normalization ceilings (#1043)", + "pr": 1043 + }, + { + "sha": "d546fcb3d864ed18776f642c1aa0fe904e9f8bfa", + "date": "2026-11-02T02:30:36Z", + "subject": "Render lexical filename fields from borrowed path slices (#1044)", + "pr": 1044 + }, + { + "sha": "35479b4fe8dec5a7a9400bca69f69516df5f56f0", + "date": "2026-11-02T03:31:09Z", + "subject": "Record rejected field lookup allocation experiments (#1045)", + "pr": 1045 + }, + { + "sha": "7c0f507f7c815146a9b746e40269377dbc768b37", + "date": "2026-11-02T04:25:35Z", + "subject": "Avoid redundant zeroing in native bounded range reads (#1046)", + "pr": 1046 + }, + { + "sha": "c14d39cf281c084f8833bc877fca6999e2f9f810", + "date": "2026-11-02T05:40:01Z", + "subject": "Reuse budgeted native comparison cursor buffers (#1047)", + "pr": 1047 + }, + { + "sha": "7cf2a52441d626888b5840d09a4646d6dedca6b9", + "date": "2026-11-02T06:41:21Z", + "subject": "Reuse typed directory task slots with atomic completion (#1048)", + "pr": 1048 + }, + { + "sha": "901c8fea916124f4d0e195c5385f2a977b44093d", + "date": "2026-11-02T08:15:37Z", + "subject": "Pack owned matcher and deferred entry text (#1049)", + "pr": 1049 + }, + { + "sha": "2d615ea1e447e55c266a47799ad6cd64bd4e246d", + "date": "2026-11-02T10:02:48Z", + "subject": "Reuse bounded matcher output capacities across batches (#1050)", + "pr": 1050 + }, + { + "sha": "d903ea98a98f4220d9372ab0404ee974eccb8690", + "date": "2026-11-02T11:07:53Z", + "subject": "Limit warmed matcher participation to available work chunks (#1051)", + "pr": 1051 + }, + { + "sha": "76cc22da343841f9786bc9f78e21e839084a780f", + "date": "2026-11-02T12:17:40Z", + "subject": "Record direct evaluator worker qualification and rejection (#1052)", + "pr": 1052 + }, + { + "sha": "dc4e70237eff58916c4eb6990047904536397264", + "date": "2026-11-02T13:14:55Z", + "subject": "Reuse requested content values across worker stages (#1053)", + "pr": 1053 + }, + { + "sha": "96fa46b86017dc2a79bc97624af9ac98401190ed", + "date": "2026-11-02T13:53:40Z", + "subject": "Reuse immutable default catalogs across library runs (#1054)", + "pr": 1054 + }, + { + "sha": "00d4f84df01e00f1ce2d7c83576ac38b2eb2fb7b", + "date": "2026-11-02T14:57:51Z", + "subject": "Prepare immutable file-diff configuration once per style (#1055)", + "pr": 1055 + }, + { + "sha": "fc2cd316e81d7319aa44912e786e7aad4492cd0a", + "date": "2026-11-02T20:24:00Z", + "subject": "Prepare compact hash-primary operands once per expression (#1056)", + "pr": 1056 + }, + { + "sha": "6bebe940ba36328a399461a19434bf627118bf75", + "date": "2026-11-02T21:02:54Z", + "subject": "Aggregate ordinary comparison side totals directly (#1057)", + "pr": 1057 + }, + { + "sha": "c004bcc65f16df2a264fd5451e4bc7262fecd137", + "date": "2026-11-02T22:25:59Z", + "subject": "Free hosted Linux build space before LLVM extraction (#1058)", + "pr": 1058 + }, + { + "sha": "4b823112efb377658029a2a3d5c4c51594f03e25", + "date": "2026-11-03T01:21:35Z", + "subject": "Aggregate five Bazel dependency bumps (#1065)", + "pr": 1065 + }, + { + "sha": "22702c34a0bcb261238af40f82818369fa46a4ab", + "date": "2026-11-03T01:24:02Z", + "subject": "perf: reduce byte-word shingle allocation and copying (#1059)", + "pr": 1059 + }, + { + "sha": "09e6bbfff3275ed36eba7b98052cf5d0877d94f7", + "date": "2026-11-03T02:42:57Z", + "subject": "Reuse archive input buffers without per-chunk allocations (#1066)", + "pr": 1066 + }, + { + "sha": "fb726c946063d567320d76f2f3d706f0a0997e57", + "date": "2026-11-03T03:38:30Z", + "subject": "Borrow cached digests and streamline output records (#1067)", + "pr": 1067 + }, + { + "sha": "58ba30eeb90499f50e98da480b8d965047352b1f", + "date": "2026-11-03T04:47:07Z", + "subject": "Reuse caller-owned buffers for memory and archive member streams (#1068)", + "pr": 1068 + }, + { + "sha": "6d6a2c9abf972ffffd064939381a1df2f40c2776", + "date": "2026-11-03T05:44:49Z", + "subject": "Fill source results directly and reuse owned decoder blocks (#1069)", + "pr": 1069 + }, + { + "sha": "44e7e30102eb6c6ae122135189b6c62340c35bdb", + "date": "2026-11-03T07:51:58Z", + "subject": "Bind hash field qualifiers once without growing template segments (#1070)", + "pr": 1070 + }, + { + "sha": "79f8b371480551c70654e1e83712ebdb6539ca0a", + "date": "2026-11-03T09:06:21Z", + "subject": "Skip discarded archive payloads through bounded owned cursors (#1071)", + "pr": 1071 + }, + { + "sha": "0fe856d76f6583c3a0023cf6f8f5654bf949bd40", + "date": "2026-11-03T10:26:07Z", + "subject": "Reuse coordinator-owned raw listing records (#1072)", + "pr": 1072 + }, + { + "sha": "6db2de9e49f19107f49e257486b50694a764cf23", + "date": "2026-11-03T11:32:14Z", + "subject": "Borrow the similarity reference sniff prefix (#1073)", + "pr": 1073 + }, + { + "sha": "7173ffcbc66063560d31e04fdd58fa4a1c6ebe8c", + "date": "2026-11-03T13:01:55Z", + "subject": "Free unused hosted SDKs before extracting LLVM toolchains (#1074)", + "pr": 1074 + }, + { + "sha": "62400cd3b12ec42c2b1aa7dec049c2510cbf456a", + "date": "2026-11-03T15:49:15Z", + "subject": "Reuse freshly verified literal similarity references (#1075)", + "pr": 1075 + }, + { + "sha": "653f5ed25b68e84e0b292afa9671289eade3b534", + "date": "2026-11-03T17:35:11Z", + "subject": "Move already-owned single-word similarity keys (#1076)", + "pr": 1076 + }, + { + "sha": "35b810bb806aa169c075c01a449a408cd3758248", + "date": "2026-11-03T18:31:01Z", + "subject": "Probe the smaller similarity shingle set (#1077)", + "pr": 1077 + }, + { + "sha": "76054b3a9c60baa72afd0452bbc3ac6bc2f79efd", + "date": "2026-11-03T20:22:28Z", + "subject": "Benchmark ZIP readers and retain rejected native-seek evaluation (#1078)", + "pr": 1078 + }, + { + "sha": "01ace14aa38a87db7d2f1441043cd61cf0b3de49", + "date": "2026-11-04T00:08:29Z", + "subject": "Reuse bounded encoded path-record storage (#1079)", + "pr": 1079 + }, + { + "sha": "0d64bb3974f4e70bc5dfc36ea8647e7e7db3cbf5", + "date": "2026-11-04T01:50:02Z", + "subject": "Reduce hosted MSan debug payload to avoid cold-build disk exhaustion (#1081)", + "pr": 1081 + }, + { + "sha": "669f68a3e26303c06325c6beaee44019481bcaf9", + "date": "2026-11-04T04:13:14Z", + "subject": "Decide similarity thresholds with exact batched bounds (#1080)", + "pr": 1080 + }, + { + "sha": "6e6b25ffc8696d6d28867a1ee6ea2e9beb00a77d", + "date": "2026-11-04T06:06:23Z", + "subject": "Reuse coordinator-owned column cells and bounded CSV/TSV row storage (#1082)", + "pr": 1082 + }, + { + "sha": "f9a73afa1497589b49f33c99c49248adf3a7b38e", + "date": "2026-11-04T07:19:35Z", + "subject": "Preserve short-word batches and reuse long-word similarity scratch (#1083)", + "pr": 1083 + }, + { + "sha": "f06cea15f5b1b0b04be246501c894b79782eb0fd", + "date": "2026-11-04T08:19:37Z", + "subject": "Reuse field contexts and transfer owned scalar output (#1084)", + "pr": 1084 + }, + { + "sha": "790dd72d400f7ac3e8656ea48c7ba718b41badd2", + "date": "2026-11-04T09:42:31Z", + "subject": "Construct only the selected comparison-summary output (#1085)", + "pr": 1085 + }, + { + "sha": "ba9b2baaf8d7ed7a7ffdeac7a16bd63f43255071", + "date": "2026-11-04T10:43:52Z", + "subject": "Use fixed-size numeric summary cells (#1086)", + "pr": 1086 + }, + { + "sha": "f7bdc5d248e76a54278aef5030c0a3468505bd2f", + "date": "2026-11-04T12:25:05Z", + "subject": "Encode summary cells without intermediate row vectors (#1087)", + "pr": 1087 + }, + { + "sha": "9bd70fc9b4607cd8a586615c630706f85416e62c", + "date": "2026-11-04T14:51:03Z", + "subject": "Retain compact comparison entries and path storage (#1088)", + "pr": 1088 + }, + { + "sha": "bec36225c686b58914e8ab9792e822d56fe1ef07", + "date": "2026-11-04T16:58:29Z", + "subject": "Append borrowed comparison categories in merge order (#1089)", + "pr": 1089 + }, + { + "sha": "798c2c0a3b4f9c1acfa050f2eac1b8902ba89ae8", + "date": "2026-11-04T19:17:45Z", + "subject": "Reuse native directory paths across leaf visits (#1090)", + "pr": 1090 + }, + { + "sha": "e66bdbe1097f4a051580dcbb68d17e745ec5e9ba", + "date": "2026-11-04T20:34:21Z", + "subject": "Avoid leaf metadata reads for uniform case policies (#1091)", + "pr": 1091 + }, + { + "sha": "a89459ed819af4fa6841a9ab7eca4e554949fd72", + "date": "2026-11-04T21:53:43Z", + "subject": "Accumulate native directory entries in stable segments (#1092)", + "pr": 1092 + }, + { + "sha": "a7a6125a9358f1020fc914d6c91bbf8c6e66392f", + "date": "2026-11-04T23:39:42Z", + "subject": "Keep benchmark task positions stable across merged history (#1093)", + "pr": 1093 + }, + { + "sha": "bb0185a0379075480eb8b1499f5bc5ff8cfafaa8", + "date": "2026-11-05T01:46:19Z", + "subject": "Keep traversal records compact with listing-owned metadata (#1094)", + "pr": 1094 + }, + { + "sha": "6792b5030de70a737dec2878673aebaa6ddc57af", + "date": "2026-11-05T03:32:21Z", + "subject": "Reuse native stat paths for eager directory listings (#1095)", + "pr": 1095 + }, + { + "sha": "39282994e036bb4dc43c2ca9ffdb2a2f498bb99d", + "date": "2026-11-05T04:48:08Z", + "subject": "Use scoped terminated storage for native stat paths (#1096)", + "pr": 1096 + }, + { + "sha": "910e2a7bbae50a3562135784d56e2ba903e89e7c", + "date": "2026-11-05T05:59:37Z", + "subject": "Record native-case experiment decisions and device-cache regressions (#1097)", + "pr": 1097 + }, + { + "sha": "7c8cd64e02a84ce13f5a7d3b3dd37290307a40a9", + "date": "2026-11-05T07:22:18Z", + "subject": "Reuse prepared folded ASCII glob shapes with native fallbacks (#1098)", + "pr": 1098 + }, + { + "sha": "76185cb37fa2d4f6cb36876efde58b0ede0e753a", + "date": "2026-11-05T09:06:33Z", + "subject": "Retain host-specific MSan caches under their sanitizer allowance (#1099)", + "pr": 1099 + }, + { + "sha": "57e9287e675f180ef6a7b0cc5d4e883605b1bfdf", + "date": "2026-11-05T11:00:54Z", + "subject": "Reuse optional bulk directory metadata with ordinary stat fallbacks (#1100)", + "pr": 1100 + }, + { + "sha": "318edb2f60ce1a9a526fc94a15ea7cdad4c4d181", + "date": "2026-11-05T14:14:49Z", + "subject": "Check XFF-owned headers through Bazel clang-tidy aliases (#1101)", + "pr": 1101 + }, + { + "sha": "55ea67e3f06e5055b43d8cb780661901731592f2", + "date": "2026-11-05T17:08:19Z", + "subject": "Skip unused ordinary scopes after comparison-only summaries (#1102)", + "pr": 1102 + }, + { + "sha": "f3ec0faf7a1bb16ddb0b3b8bcee2c3e5bd970df2", + "date": "2026-11-05T18:53:16Z", + "subject": "Record comparison-storage experiments without adopting regressions (#1103)", + "pr": 1103 + }, + { + "sha": "455dcd8eb5dd98b09f3117f5316136b6d43cfd8e", + "date": "2026-11-05T20:46:57Z", + "subject": "Reuse archive session input for format detection (#1104)", + "pr": 1104 + }, + { + "sha": "245e74ff6cbe6c0f84a074be669c60ac7cbc5e8f", + "date": "2026-11-05T22:29:23Z", + "subject": "Bound archive directory listings to their ordered subtree (#1105)", + "pr": 1105 + }, + { + "sha": "b60cf7a5a92609f9fadddd4759d3c55e755a69b6", + "date": "2026-11-06T00:26:31Z", + "subject": "Allow OS-version fallback after exhausting exact benchmark quorums (#1117)", + "pr": 1117 + }, + { + "sha": "e7e42d01e0678590fc06bd90b9143682a84aef7d", + "date": "2026-11-06T01:50:29Z", + "subject": "Resolve Bazel virtual include aliases for local clang-tidy scope (#1106)", + "pr": 1106 + }, + { + "sha": "ccb1f0a202ed59b30246c14e424a400e47acc447", + "date": "2026-11-06T03:31:50Z", + "subject": "Bound initial storage for archive directory listings (#1107)", + "pr": 1107 + }, + { + "sha": "adae6c9cd98bdd4b15f7b2867d08b1bfe12e1fad", + "date": "2026-11-06T04:40:27Z", + "subject": "Reuse indexed metadata during archive directory walks (#1108)", + "pr": 1108 + }, + { + "sha": "a1ff80a81c1ff2c4fd93898aeaf07dc2fc5764ff", + "date": "2026-11-06T05:46:37Z", + "subject": "Reuse complete Darwin bulk observations for non-followed symlinks (#1109)", + "pr": 1109 + }, + { + "sha": "e9bebfa5bfd85137de756047795887d45248ec18", + "date": "2026-11-06T06:49:18Z", + "subject": "Record rejected native metadata and queue cleanup experiments (#1110)", + "pr": 1110 + }, + { + "sha": "5cade08b6701417b07343b12ac86331ed0c3b941", + "date": "2026-11-06T07:59:12Z", + "subject": "Fix benchmark preview readiness for the combined aggregate (#1111)", + "pr": 1111 + }, + { + "sha": "852539d084ca1c4bb1756b0f83eb4b50b2b19b85", + "date": "2026-11-06T09:03:22Z", + "subject": "Defer coverage publication when its source is retried (#1112)", + "pr": 1112 + }, + { + "sha": "5729026a8482a2bc331058ee658017f9aba74298", + "date": "2026-11-06T10:09:24Z", + "subject": "Avoid unnecessary symlink target reads in formatted listings (#1113)", + "pr": 1113 + }, + { + "sha": "713abe5fa302c9ff78e7df769304f90379566c83", + "date": "2026-11-06T11:21:49Z", + "subject": "Record the published site storage review (#1114)", + "pr": 1114 + }, + { + "sha": "ab909839da7d1ae34ea63eab75ec83dc62fd33fb", + "date": "2026-11-06T12:35:53Z", + "subject": "Retain measured PGO and short-readlink performance decisions (#1115)", + "pr": 1115 + }, + { + "sha": "f4cee33eeb6b6cf00c1b39003b11fafbb262f79b", + "date": "2026-11-06T13:29:25Z", + "subject": "Skip empty CCTZ formatter fragments before libc (#1116)", + "pr": 1116 + }, + { + "sha": "c7bb70cc6f3e6441ff25c999667d76f48ffe9acb", + "date": "2026-11-06T14:32:34Z", + "subject": "Avoid temporary archive member keys (#1118)", + "pr": 1118 + }, + { + "sha": "2487927cc6b1de326ea3c6c058dc493214354bec", + "date": "2026-11-06T16:42:21Z", + "subject": "Reserve archive listings from child counts (#1120)", + "pr": 1120 + }, + { + "sha": "d9bf84b04784daf1d457a213f2dba277ba32ed2e", + "date": "2026-11-06T17:51:54Z", + "subject": "Avoid redundant archive directory separator scans (#1121)", + "pr": 1121 + }, + { + "sha": "0e95e191ba7d7ee3769217e7fbf82a825ff9b90d", + "date": "2026-11-06T19:06:09Z", + "subject": "Avoid copying owned archive bytes before parsing (#1122)", + "pr": 1122 + }, + { + "sha": "83657b9dfe35adda2a4cede5a1ae71db2f2b870d", + "date": "2026-11-06T20:08:59Z", + "subject": "Append structured field values without intermediate strings (#1123)", + "pr": 1123 + }, + { + "sha": "de2fa3557d69e9c3eb1c52bb2b0300566f960fea", + "date": "2026-11-06T22:11:55Z", + "subject": "Record completed-frontier comparison rejection (#1124)", + "pr": 1124 + }, + { + "sha": "c95140674254c371844f1fab27a64951a80dac55", + "date": "2026-11-06T23:53:55Z", + "subject": "Reserve LTO links for production CLIs and share Linux fat objects (#1119)", + "pr": 1119 + }, + { + "sha": "9bf1aad510d843d1d6338fbdf23107a30d339730", + "date": "2026-11-07T02:38:27Z", + "subject": "Record shared-worker qualification and retain specialized pools (#1125)", + "pr": 1125 + }, + { + "sha": "d8cf61cccd4b0efed5058bf6fa45228e47162b48", + "date": "2026-11-07T04:10:09Z", + "subject": "Record archive insertion qualification and reconcile tracking (#1126)", + "pr": 1126 + }, + { + "sha": "1786340680499f50b08dee5b1ceffbc20fd7b533", + "date": "2026-11-07T07:02:39Z", + "subject": "Reuse validated rg output transactions in matcher results (#1127)", + "pr": 1127 + }, + { + "sha": "1278c8943a6abd236a2f20e3937cc8e23a0f95a7", + "date": "2026-11-07T08:14:55Z", + "subject": "Decode embedded language JSON into final owned storage (#1128)", + "pr": 1128 + }, + { + "sha": "77aa9ef9bc9475adcbdd37cf3004143a96f03060", + "date": "2026-11-07T09:22:56Z", + "subject": "Record rejected hinted archive ancestor insertion screen (#1129)", + "pr": 1129 + }, + { + "sha": "ae8c5af3eb11dc8571f11db9b307b0db948f78c6", + "date": "2026-11-07T11:11:19Z", + "subject": "Stop main benchmarks once three of four candidates agree (#1130)", + "pr": 1130 + } +] diff --git a/docs/benchmarks/extended-history-viewer-check-20261107.json b/docs/benchmarks/extended-history-viewer-check-20261107.json new file mode 100644 index 00000000000..297ec5dc684 --- /dev/null +++ b/docs/benchmarks/extended-history-viewer-check-20261107.json @@ -0,0 +1,34 @@ +{ + "purpose": "synthetic renderer validation; not measurements", + "results": [ + { + "dataset": "Drogon / extended-production-v1 / Fixed XFF at PR #2", + "version": "0", + "measuredPoints": 60, + "missingPoints": 20, + "height": -100 + }, + { + "dataset": "Drogon / extended-production-v1 / Fixed XFF at PR #2", + "version": "1", + "measuredPoints": 60, + "missingPoints": 20, + "height": 0 + }, + { + "dataset": "Drogon / extended-production-v1 / Traditional tools", + "version": "0", + "measuredPoints": 60, + "missingPoints": 20, + "height": 50 + }, + { + "dataset": "Drogon / extended-production-v1 / Traditional tools", + "version": "1", + "measuredPoints": 60, + "missingPoints": 20, + "height": 75 + } + ], + "errors": [] +} diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel index 2ac6847336d..01184ba30da 100644 --- a/tools/BUILD.bazel +++ b/tools/BUILD.bazel @@ -922,6 +922,10 @@ test_suite( ":benchmark_campaign_test", ":benchmark_compare_test", ":benchmark_datasets_test", + ":benchmark_extended_build_test", + ":benchmark_extended_history_test", + ":benchmark_extended_report_test", + ":benchmark_extended_test", ":benchmark_fixture_test", ":benchmark_history_test", ":benchmark_landscape_test", @@ -1168,6 +1172,94 @@ py_library( ], ) +py_library( + name = "benchmark_extended_lib", + srcs = ["benchmark_extended.py"], + imports = ["."], +) + +py_test( + name = "benchmark_extended_test", + size = "small", + srcs = ["benchmark_extended_test.py"], + deps = [":benchmark_extended_lib"], +) + +py_library( + name = "benchmark_extended_build_lib", + srcs = ["benchmark_extended_build.py"], + imports = ["."], +) + +py_binary( + name = "benchmark_extended_build", + srcs = ["benchmark_extended_build.py"], +) + +py_test( + name = "benchmark_extended_build_test", + size = "small", + srcs = ["benchmark_extended_build_test.py"], + deps = [":benchmark_extended_build_lib"], +) + +py_library( + name = "benchmark_extended_history_lib", + srcs = ["benchmark_extended_history.py"], + imports = ["."], + deps = [ + ":benchmark_extended_lib", + ":process_resources_lib", + ], +) + +py_binary( + name = "benchmark_extended_history", + srcs = ["benchmark_extended_history.py"], + deps = [ + ":benchmark_extended_lib", + ":process_resources_lib", + ], +) + +py_test( + name = "benchmark_extended_history_test", + size = "small", + srcs = ["benchmark_extended_history_test.py"], + deps = [ + ":benchmark_extended_history_lib", + ":benchmark_extended_lib", + ], +) + +py_library( + name = "benchmark_extended_report_lib", + srcs = ["benchmark_extended_report.py"], + imports = ["."], + deps = [ + ":benchmark_extended_lib", + ":benchmark_landscape_lib", + ":benchmark_matrix_lib", + ], +) + +py_binary( + name = "benchmark_extended_report", + srcs = ["benchmark_extended_report.py"], + deps = [ + ":benchmark_extended_lib", + ":benchmark_landscape_lib", + ":benchmark_matrix_lib", + ], +) + +py_test( + name = "benchmark_extended_report_test", + size = "small", + srcs = ["benchmark_extended_report_test.py"], + deps = [":benchmark_extended_report_lib"], +) + py_binary( name = "benchmark_compare", srcs = ["benchmark_compare.py"], diff --git a/tools/benchmark_extended.py b/tools/benchmark_extended.py new file mode 100644 index 00000000000..0970cadb1f9 --- /dev/null +++ b/tools/benchmark_extended.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: Copyright (c) M. Boerger, the MBO Works authors +# SPDX-License-Identifier: Apache-2.0 +"""Versioned production workloads for the extended benchmark qualification campaign.""" + +from collections import Counter +from dataclasses import dataclass +import hashlib +import io +import json +import os +from pathlib import Path +import tarfile + + +RECIPE = 'extended-production-v1' +MTIME = 1577923200 # 2020-01-02 00:00:00 UTC. +PATTERN = r'(ERROR|WARN) service=api_[0-9]+ status=5[0-9]{2}' +TASKS = ('files-exact', 'name-native', 'metadata-time', 'content-regex', 'archive-tar') + + +@dataclass(frozen=True) +class Case: + name: str + shape: str + files: int + cpus: int + + def __post_init__(self): + if (self.name not in TASKS or self.shape not in ('broad', 'deep') or + type(self.files) is not int or self.files < 1 or type(self.cpus) is not int or self.cpus < 1): + raise ValueError('invalid extended case') + + @property + def key(self): + return f'{self.name}/{self.shape}/{self.files}/{self.cpus}' + + +def cases(): + """Include large traversal cells without making every archive trial a 100k scan.""" + return [Case(name, shape, count, cpus) for name in TASKS + for shape in ('broad', 'deep') + for count in ((100, 1000, 10000) if name == 'archive-tar' else (100, 10000, 100000)) + for cpus in (1, 3)] + + +def entries(shape, count, archive=False): + if shape not in ('broad', 'deep') or count < 1: + raise ValueError('invalid fixture dimensions') + for index in range(count): + if archive: + directory = f'd{index // 100:04}/' + if shape == 'deep': + directory = 'level/' * (index // 100 % 8 + 1) + directory + else: + directory = '' if shape == 'broad' else 'level/' * (index % 40 + 1) + name = directory + f'item_{index:06}.' + ('txt' if index % 2 == 0 else 'log') + matched = index % 3 == 0 + size = 8192 if index % 50 == 0 else 256 + tail = (b'ERROR service=api_12 status=503\n' if matched else + b'ERROR service=api_12 status=200\n') + data = b'x' * (size - len(tail) - 1) + b'\n' + tail + yield name, data, matched + + +def fixture_identity(shape, count, archive=False): + digest = hashlib.sha256() + digest.update(f'{RECIPE}/{shape}/{count}/{archive}/{MTIME}'.encode()) + for name, data, _ in entries(shape, count, archive): + digest.update(name.encode() + b'\0' + data + b'\0') + return digest.hexdigest() + + +def prepare(parent, selected_cases=None): + """Create only inside a new owned directory; callers verify tmpfs before collection.""" + parent = Path(parent) + parent.mkdir(exist_ok=False) + (parent / 'empty').write_bytes(b'') + (parent / 'home').mkdir() + specifications = sorted({(case.shape, case.files, case.name == 'archive-tar') + for case in (cases() if selected_cases is None else selected_cases)}) + records = [] + for shape, count, archive in specifications: + root = parent / ('archive' if archive else 'native') / shape / str(count) + root.mkdir(parents=True) + if archive: + with tarfile.open(root / 'fixture.tar', 'w', format=tarfile.USTAR_FORMAT) as handle: + for name, data, _ in entries(shape, count, True): + member = tarfile.TarInfo(name) + member.size, member.mtime, member.mode = len(data), MTIME, 0o644 + member.uid = member.gid = 0 + handle.addfile(member, io.BytesIO(data)) + content_hash = hashlib.sha256((root / 'fixture.tar').read_bytes()).hexdigest() + else: + for name, data, _ in entries(shape, count): + target = root / name + target.parent.mkdir(parents=True, exist_ok=True) + target.write_bytes(data) + target.chmod(0o644) + os.utime(target, (MTIME, MTIME)) + content_hash = None + records.append({'shape': shape, 'files': count, 'archive': archive, + 'fixture_identity': fixture_identity(shape, count, archive), + 'archive_sha256': content_hash}) + (parent / 'manifest.json').write_text(json.dumps({'recipe': RECIPE, 'fixtures': records}, indent=2) + '\n') + return records + + +def commands(case, parent, binary, tools): + parent = Path(parent) + root = parent / ('archive' if case.name == 'archive-tar' else 'native') / case.shape / str(case.files) + base = [str(binary), '--no-config', '--no-pager', '--color=never', '--sort=none', + '--gitignore=off', '--hidden', f'--jobs={case.cpus}'] + find = [tools['find'], '-P', str(root), '-type', 'f'] + if case.name == 'files-exact': + return {'xff': [*base, '--exact', '.', '-type', 'f', '-print0'], + 'find': [tools['find'], '-P', '.', '-type', 'f', '-print0']}, root, b'\0' + if case.name == 'name-native': + return {'xff': [*base, str(root), '-type', 'f', '-name', '*.txt', '-print0'], + 'find': [*find, '-name', '*.txt', '-print0']}, root, b'\0' + if case.name == 'metadata-time': + template = r'%p\t%s\t%TY-%Tm-%Td\0' + return {'xff': [*base, '--exact', '--timezone=UTC', str(root), '-type', 'f', + '-name', '*.txt', '-size', '+128c', '-printf', template], + 'find': [*find, '-name', '*.txt', '-size', '+128c', '-printf', template]}, root, b'\0' + if case.name == 'content-regex': + return {'xff': [*base, '--exact', '--case=sensitive', '--regextype=RE2', str(root), + '-type', 'f', '-name', '*.txt', '-rxc', PATTERN, '-print0'], + 'rg': [tools['rg'], '--no-config', '--hidden', '--no-ignore', '--color=never', + '--case-sensitive', '--text', f'--threads={case.cpus}', '-g', '*.txt', + '--files-with-matches', '--null', '-e', PATTERN, str(root)]}, root, b'\0' + if case.name == 'archive-tar': + return {'xff': [*base, '--exact', '--archive=roots', '--archive-separator=/', + 'fixture.tar', '-type', 'f', '-name', '*.txt', '-print'], + 'tar': [tools['tar'], '-tf', 'fixture.tar', '--wildcards', '*.txt', + '--transform=s,^,fixture.tar/,', '--show-transformed-names']}, root, b'\n' + raise ValueError('unknown extended task: ' + case.name) + + +def expected(case, parent): + root = Path(parent) / 'native' / case.shape / str(case.files) + result = [] + for name, data, matched in entries(case.shape, case.files, case.name == 'archive-tar'): + if case.name != 'files-exact' and not name.endswith('.txt'): + continue + if case.name == 'content-regex' and not matched: + continue + if case.name == 'archive-tar': + value = 'fixture.tar/' + name + elif case.name == 'files-exact': + value = './' + name + elif case.name == 'metadata-time': + value = f'{root / name}\t{len(data)}\t2020-01-02' + else: + value = str(root / name) + result.append(value.encode()) + return result + + +def validate(sample, wanted, separator): + if sample['exit_codes'] != [0] or sample['stderr_bytes'] or sample['stderr']: + raise ValueError(f'command failed: exit={sample["exit_codes"]}; ' + f'stderr={sample["stderr"][:2000]!r}') + output = sample['output'] + if output and not output.endswith(separator): + raise ValueError('output lacks its final record separator') + actual = output.removesuffix(separator).split(separator) if output else [] + if Counter(actual) != Counter(wanted): + missing = list((Counter(wanted) - Counter(actual)).items())[:3] + extra = list((Counter(actual) - Counter(wanted)).items())[:3] + raise ValueError(f'output oracle mismatch; missing={missing!r}; extra={extra!r}') + if sample['stdout_bytes'] != len(output): + raise ValueError('output byte accounting mismatch') + return hashlib.sha256(output).hexdigest() + + +def verify(parent, selected_cases=None): + """Re-read fixture contents and metadata before accepting or resuming measurements.""" + parent = Path(parent) + specifications = {(case.shape, case.files, case.name == 'archive-tar') + for case in (cases() if selected_cases is None else selected_cases)} + manifest = json.loads((parent / 'manifest.json').read_text()) + if manifest['recipe'] != RECIPE or len(manifest['fixtures']) != len(specifications): + raise ValueError('fixture manifest changed') + for record in manifest['fixtures']: + shape, count, archive = record['shape'], record['files'], record['archive'] + if (shape, count, archive) not in specifications: + raise ValueError('unexpected fixture specification') + root = parent / ('archive' if archive else 'native') / shape / str(count) + if record['fixture_identity'] != fixture_identity(shape, count, archive): + raise ValueError('fixture recipe identity changed') + if archive: + if hashlib.sha256((root / 'fixture.tar').read_bytes()).hexdigest() != record['archive_sha256']: + raise ValueError('archive fixture changed') + continue + paths = set() + for name, data, _ in entries(shape, count): + target = root / name + stat = target.stat() + if target.is_symlink() or target.read_bytes() != data or stat.st_mtime != MTIME or stat.st_mode & 0o777 != 0o644: + raise ValueError('native fixture changed: ' + str(target)) + paths.add(name) + actual = {str(p.relative_to(root)) for p in root.rglob('*') if not p.is_dir()} + if actual != paths: + raise ValueError('native fixture population changed') + return manifest diff --git a/tools/benchmark_extended_build.py b/tools/benchmark_extended_build.py new file mode 100644 index 00000000000..d9e5e535e7c --- /dev/null +++ b/tools/benchmark_extended_build.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: Copyright (c) M. Boerger, the MBO Works authors +# SPDX-License-Identifier: Apache-2.0 +"""Freeze historical full production executables before extended measurements.""" + +import argparse +from datetime import datetime, timezone +import hashlib +import json +from pathlib import Path +import shutil +import subprocess +import time + + +def digest(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def write(path, value): + temporary = path.with_suffix(path.suffix + '.tmp') + temporary.write_text(json.dumps(value, indent=2) + '\n') + temporary.replace(path) + + +def git(checkout, *args): + return subprocess.check_output(['git', '-C', str(checkout), *args], text=True).strip() + + +def clean_source(checkout, sha): + if git(checkout, 'rev-parse', 'HEAD') != sha or git(checkout, 'status', '--porcelain'): + raise ValueError('historical checkout must exactly match its clean revision') + if (checkout / '.bazelrc.user').exists(): + raise ValueError('workspace Bazel override is forbidden') + return {'revision': sha, 'tree': git(checkout, 'rev-parse', 'HEAD^{tree}'), 'clean': True} + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--root', type=Path, required=True) + parser.add_argument('--revisions', type=Path, required=True) + parser.add_argument('--disk-cache', type=Path, required=True) + parser.add_argument('--jobs', type=int, default=6) + parser.add_argument('--build-library-path', type=Path) + args = parser.parse_args() + root, checkout = args.root.resolve(), args.root.resolve() / 'checkout' + revisions = json.loads(args.revisions.read_text()) + policy = {'revisions': revisions, 'target': '//xff/cli:xff_full', + 'configs': ['clang_release', 'xff_full'], 'driver_sha256': digest(Path(__file__)), + 'startup_flags': ['--nosystem_rc', '--nohome_rc'], 'jobs': args.jobs, + 'disk_cache': str(args.disk_cache.resolve())} + if args.build_library_path: + library_path = args.build_library_path.resolve(strict=True) + policy['build_library_path'] = str(library_path) + policy['build_libraries'] = {p.name: digest(p) for p in sorted(library_path.iterdir()) if p.is_file()} + contract_path = root / 'build-contract.json' + if contract_path.exists() and json.loads(contract_path.read_text()) != policy: + raise ValueError('cannot resume a changed build contract') + write(contract_path, policy) + status_path = root / 'build-status.json' + status = json.loads(status_path.read_text()) if status_path.exists() else {} + # Endpoints first permit functional qualification while the remaining builds run. + order = [revisions[-1], *revisions[:-1]] + for index, revision in enumerate(order, 1): + sha = revision['sha'] + directory = root / 'binaries' / sha + directory.mkdir(parents=True, exist_ok=True) + identity, executable = directory / 'build.json', directory / 'xff_full' + if identity.exists(): + saved = json.loads(identity.read_text()) + if saved['source']['revision'] != sha or saved['sha256'] != digest(executable): + raise ValueError('retained executable mismatch: ' + sha) + status[sha] = {'status': 'built', 'sha256': saved['sha256']} + write(status_path, status) + continue + started = time.monotonic() + print(f'BUILD {index}/{len(order)} PR #{revision["pr"]} {sha}', flush=True) + status[sha] = {'status': 'building', 'started_at': datetime.now(timezone.utc).isoformat()} + write(status_path, status) + try: + subprocess.run(['git', '-C', str(checkout), 'checkout', '--detach', sha], check=True) + source = clean_source(checkout, sha) + bazel = ['bazel', *policy['startup_flags']] + options = ['--config=clang_release', '--config=xff_full', + '--disk_cache=' + str(args.disk_cache.resolve()), '--jobs=' + str(args.jobs)] + if args.build_library_path: + options.append('--action_env=LD_LIBRARY_PATH=' + str(args.build_library_path.resolve())) + command = [*bazel, 'build', '//xff/cli:xff_full', *options] + with (directory / 'build.log').open('w') as log: + subprocess.run(command, cwd=checkout, stdout=log, stderr=subprocess.STDOUT, check=True) + query = [*bazel, 'cquery', 'config(//xff/cli:xff_full, target)', *options, + '--output=starlark', '--starlark:expr=target.files_to_run.executable.path'] + artifact = subprocess.check_output(query, cwd=checkout, stderr=log, text=True).strip() + if not artifact or len(artifact.splitlines()) != 1: + raise ValueError('configured executable query is ambiguous') + if clean_source(checkout, sha) != source: + raise ValueError('source identity changed during build') + built = checkout / artifact + binary_hash = digest(built) + shutil.copy2(built, executable) + if digest(executable) != binary_hash: + raise ValueError('frozen executable copy mismatch') + # Link actions record the actual production LTO command for this revision. + with (directory / 'link-actions.json').open('w') as actions: + subprocess.run([*bazel, 'aquery', 'mnemonic("CppLink", //xff/cli:xff_full)', + *options, '--output=jsonproto'], cwd=checkout, stdout=actions, + stderr=log, check=True) + saved = {'source': source, 'sha256': binary_hash, 'bytes': executable.stat().st_size, + 'command': command, 'query': query, 'artifact': artifact, + 'elapsed_seconds': time.monotonic() - started, + 'completed_at': datetime.now(timezone.utc).isoformat(), + 'configuration': {name: digest(checkout / name) for name in + ('.bazelrc', '.bazelversion', 'MODULE.bazel', 'MODULE.bazel.lock', + 'bazelmod/llvm.MODULE.bazel') if (checkout / name).is_file()}} + write(identity, saved) + status[sha] = {'status': 'built', 'sha256': binary_hash, 'seconds': saved['elapsed_seconds']} + print(f'BUILT {index}/{len(order)} {sha[:10]} {binary_hash} {saved["elapsed_seconds"]:.1f}s', flush=True) + except (subprocess.CalledProcessError, ValueError, OSError) as error: + status[sha] = {'status': 'build-failed', 'error': str(error), + 'seconds': time.monotonic() - started} + print(f'FAILED {sha}: {error}', flush=True) + write(status_path, status) + raise + write(status_path, status) + print('BUILD PHASE COMPLETE', json.dumps({state: sum(v['status'] == state for v in status.values()) + for state in sorted({v['status'] for v in status.values()})}), flush=True) + + +if __name__ == '__main__': + main() diff --git a/tools/benchmark_extended_build_test.py b/tools/benchmark_extended_build_test.py new file mode 100644 index 00000000000..491b0dea477 --- /dev/null +++ b/tools/benchmark_extended_build_test.py @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: Copyright (c) M. Boerger, the MBO Works authors +# SPDX-License-Identifier: Apache-2.0 +"""Keep historical source and binary provenance fail closed without invoking Bazel.""" + +from pathlib import Path +import tempfile +import unittest +from unittest import mock + +import benchmark_extended_build as build + + +class BenchmarkExtendedBuildTest(unittest.TestCase): + def test_clean_source_records_exact_revision_and_tree(self): + with tempfile.TemporaryDirectory() as temporary: + with mock.patch.object(build, 'git', side_effect=['revision', '', 'tree']) as git: + self.assertEqual(build.clean_source(Path(temporary), 'revision'), + {'revision': 'revision', 'tree': 'tree', 'clean': True}) + self.assertEqual([call.args[1:] for call in git.call_args_list], + [('rev-parse', 'HEAD'), ('status', '--porcelain'), ('rev-parse', 'HEAD^{tree}')]) + + def test_dirty_or_wrong_checkout_and_local_bazel_override_are_rejected(self): + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + for answers in (['wrong'], ['revision', ' M source.cc']): + with mock.patch.object(build, 'git', side_effect=answers), self.assertRaises(ValueError): + build.clean_source(root, 'revision') + (root / '.bazelrc.user').touch() + with mock.patch.object(build, 'git', side_effect=['revision', '']), self.assertRaisesRegex(ValueError, 'override'): + build.clean_source(root, 'revision') + + def test_identity_hash_changes_with_artifact_contents(self): + with tempfile.TemporaryDirectory() as temporary: + path = Path(temporary) / 'xff' + path.write_bytes(b'old') + old = build.digest(path) + path.write_bytes(b'new') + self.assertNotEqual(build.digest(path), old) + build.write(Path(temporary) / 'identity.json', {'hash': old}) + self.assertFalse((Path(temporary) / 'identity.json.tmp').exists()) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/benchmark_extended_history.py b/tools/benchmark_extended_history.py new file mode 100644 index 00000000000..27a8f35b3ac --- /dev/null +++ b/tools/benchmark_extended_history.py @@ -0,0 +1,283 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: Copyright (c) M. Boerger, the MBO Works authors +# SPDX-License-Identifier: Apache-2.0 +"""Measure frozen historical executables against a current anchor and reference tools. + +Linux qualification only. This separate versioned campaign never appends incompatible +workloads to the published core dataset. Each command uses the existing native resource +launcher; fresh fork workers provide timeout and affinity isolation. Validation and JSON +serialization occur after the measured interval. All raw timing samples are retained. +""" + +import argparse +from dataclasses import asdict +from datetime import datetime, timezone +import fcntl +import gzip +import hashlib +import json +import multiprocessing +import os +from pathlib import Path +import platform +import random +import shutil +import signal +import subprocess +import sys +import time + +import benchmark_extended as suite +import process_resources + + +def digest(path): + return hashlib.sha256(Path(path).read_bytes()).hexdigest() + + +def write(path, value): + temporary = path.with_suffix(path.suffix + '.tmp') + temporary.write_text(json.dumps(value, indent=2) + '\n') + temporary.replace(path) + + +def freeze(path, value): + if path.exists() and json.loads(path.read_text()) != value: + raise ValueError('cannot resume changed contract: ' + str(path)) + write(path, value) + + +def cpu_allocation(count): + """Prefer separate physical cores over sibling hardware threads.""" + cores = {} + for cpu in sorted(os.sched_getaffinity(0)): + topology = Path(f'/sys/devices/system/cpu/cpu{cpu}/topology') + key = ((topology / 'physical_package_id').read_text(), (topology / 'core_id').read_text()) + cores.setdefault(key, cpu) + result = list(cores.values())[:count] + if len(result) != count: + raise ValueError('not enough allowed physical cores') + return result + + +def worker(connection, spec, wanted, separator, failure_path): + """Fresh worker; no Python process is included in command resource accounting.""" + sample = None + try: + os.setsid() + os.sched_setaffinity(0, spec['affinity']) + with open(spec['stdin'], 'rb') as source: + sample = process_resources.measure_pipeline( + [spec['command']], source=source, cwd=spec['cwd'], environment=spec['environment'], + launcher=spec['launcher'], stderr_limit=8192) + output_hash = suite.validate(sample, wanted, separator) + sample.pop('output') + sample.update(stdout_sha256=output_hash, validated_records=len(wanted)) + connection.send({'sample': sample}) + except BaseException as error: + if sample is not None and 'output' in sample: + with gzip.open(failure_path, 'wb') as output: + output.write(sample.pop('output')) + connection.send({'error': repr(error), 'sample': sample}) + finally: + connection.close() + + +def invoke(spec, wanted, separator, failure_path, timeout=120): + context = multiprocessing.get_context('fork') + receiver, sender = context.Pipe(duplex=False) + child = context.Process(target=worker, args=(sender, spec, wanted, separator, failure_path)) + child.start() + sender.close() + try: + if not receiver.poll(timeout): + # setsid precedes launch; kill only our worker's own process group. + if child.is_alive() and os.getpgid(child.pid) == child.pid: + os.killpg(child.pid, signal.SIGKILL) + else: + child.kill() + raise ValueError(f'measurement exceeded {timeout} seconds') + response = receiver.recv() + if 'error' in response: + raise ValueError(str(response)) + return response['sample'] + finally: + receiver.close() + child.join(timeout=5) + if child.is_alive(): + child.kill() + child.join() + + +def host_context(): + return {'utc': datetime.now(timezone.utc).isoformat(), 'loadavg': os.getloadavg(), + 'meminfo': Path('/proc/meminfo').read_text(), + 'cpu_stat': Path('/proc/stat').read_text(), + 'pressure': {name: (Path('/proc/pressure') / name).read_text() + for name in ('cpu', 'memory', 'io')}} + + +def round_order(labels, case_index, repetition): + offset = (case_index + repetition) % len(labels) + return labels[offset:] + labels[:offset] + + +def collect_cell(case, revision, anchor, root, fixture, tools, launcher, affinity, index, repetitions): + directory = root / 'cells' / revision['sha'] / case.key + directory.mkdir(parents=True, exist_ok=True) + completed = directory / 'complete.json' + if completed.exists(): + return json.loads(completed.read_text()) + attempts = directory / 'attempts' + attempts.mkdir(exist_ok=True) + attempt = attempts / str(len(list(attempts.iterdir())) + 1) + attempt.mkdir() + wanted = suite.expected(case, fixture) + commands, cwd, separator = suite.commands(case, fixture, revision['binary'], tools) + anchor_commands, _, _ = suite.commands(case, fixture, anchor['binary'], tools) + commands['anchor'] = anchor_commands['xff'] + labels = list(commands) + environment = {'PATH': '/usr/bin:/bin', 'HOME': str(fixture / 'home'), 'LC_ALL': 'C', 'TZ': 'UTC'} + row = {'case': asdict(case), 'revision': revision, 'anchor': anchor, + 'expected_records': len(wanted), 'expected_sha256': hashlib.sha256(b'\0'.join(sorted(wanted))).hexdigest(), + 'commands': commands, 'cwd': str(cwd), 'affinity': affinity[:case.cpus], 'environment': environment, + 'before': host_context(), 'samples': [], 'attempt': str(attempt)} + write(attempt / 'start.json', row) + try: + with (attempt / 'samples.jsonl').open('x') as raw: + for repetition in range(repetitions + 1): + for label in round_order(labels, index, repetition): + spec = {'command': commands[label], 'cwd': str(cwd), 'environment': environment, + 'stdin': str(fixture / 'empty'), 'launcher': launcher, + 'affinity': affinity[:case.cpus]} + record = {'label': label, 'round': repetition, + 'phase': 'warmup' if repetition == 0 else 'measured', + 'utc': datetime.now(timezone.utc).isoformat()} + record.update(invoke(spec, wanted, separator, attempt / 'failed-output.gz')) + row['samples'].append(record) + raw.write(json.dumps(record) + '\n') + raw.flush() + row['after'] = host_context() + write(completed, row) + except BaseException as error: + write(attempt / 'failure.json', {'error': repr(error), 'context': host_context()}) + raise + return row + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--root', type=Path, required=True) + parser.add_argument('--build-root', type=Path, required=True) + parser.add_argument('--revisions', type=Path, required=True) + parser.add_argument('--fixture', type=Path, required=True) + parser.add_argument('--resource-launcher', type=Path, required=True) + parser.add_argument('--cases', type=Path, help='Optional frozen JSON list of Case records for qualification') + parser.add_argument('--repetitions', type=int, default=9) + parser.add_argument('--keep', type=int, default=7) + parser.add_argument('--limit', type=int, help='Stop cleanly after this many new cells; contract is unchanged') + args = parser.parse_args() + if sys.platform != 'linux' or not 1 <= args.keep <= args.repetitions: + parser.error('requires Linux and 1 <= keep <= repetitions') + root, fixture, builds = args.root.resolve(), args.fixture.resolve(), args.build_root.resolve() + root.mkdir(parents=True, exist_ok=True) + collection_lock = (root / 'collection.lock').open('a') + fcntl.flock(collection_lock, fcntl.LOCK_EX | fcntl.LOCK_NB) + if (root / 'invalid.json').exists(): + raise ValueError('campaign identity changed previously; inspect invalid.json before starting a new campaign') + revisions = json.loads(args.revisions.read_text()) + cases = [suite.Case(**case) for case in json.loads(args.cases.read_text())] if args.cases else suite.cases() + if not revisions or not cases or len({r['sha'] for r in revisions}) != len(revisions) or len({c.key for c in cases}) != len(cases): + raise ValueError('empty or duplicate revisions/cases') + affinity = cpu_allocation(max(case.cpus for case in cases)) + # Collection requires already-frozen binaries. Build completion is checked by the operator; + # no compiler is invoked anywhere in this measurement driver. + for revision in revisions: + directory = builds / 'binaries' / revision['sha'] + identity = json.loads((directory / 'build.json').read_text()) + binary = directory / 'xff_full' + if identity['source']['revision'] != revision['sha'] or digest(binary) != identity['sha256']: + raise ValueError('binary/source identity mismatch') + actions = json.loads((directory / 'link-actions.json').read_text()) + links = [action['arguments'] for action in actions['actions'] + if identity['artifact'] in action.get('arguments', [])] + if len(links) != 1 or '-flto=thin' not in links[0]: + raise ValueError('production ThinLTO link evidence is missing: ' + revision['sha']) + revision.update(binary=str(binary), binary_sha256=identity['sha256'], build_sha256=digest(directory / 'build.json'), + link_actions_sha256=digest(directory / 'link-actions.json')) + anchor = revisions[-1] + tools = {} + for name in ('find', 'rg', 'tar'): + path = str(Path(shutil.which(name)).resolve(strict=True)) + tools[name] = {'path': path, 'sha256': digest(path), + 'version': subprocess.check_output([path, '--version'], text=True).strip()} + launcher = process_resources.launcher_identity(args.resource_launcher) + filesystem = subprocess.check_output(['findmnt', '-n', '-o', 'FSTYPE', '-T', str(fixture.parent)], text=True).strip() + if filesystem != 'tmpfs': + raise ValueError('fixtures must reside on tmpfs, found: ' + filesystem) + contract = {'recipe': suite.RECIPE, 'cases': [asdict(case) for case in cases], 'revisions': revisions, + 'repetitions': args.repetitions, 'keep': args.keep, 'estimator': 'mean-fastest', + 'warmup_rounds': 1, 'anchor': anchor, 'fixture': str(fixture), 'filesystem': filesystem, + 'tools': tools, 'launcher': launcher, 'affinity': affinity, 'platform': platform.platform(), + 'cpuinfo': Path('/proc/cpuinfo').read_text().split('\n\n')[0], + 'python': sys.version, 'drivers': {Path(module).name: digest(module) for module in + (__file__, suite.__file__, process_resources.__file__)}, + 'build_contract_sha256': digest(builds / 'build-contract.json'), + 'order': 'seed 20261107 shuffles revisions and cells; participant start rotates each round', + 'output_retention': 'all outputs checked; successful output hash/count retained; failing output gzip retained'} + # cpu MHz fluctuates: record it as context, never as a resume identity field. + contract['cpuinfo'] = '\n'.join(line for line in contract['cpuinfo'].splitlines() if not line.startswith('cpu MHz')) + freeze(root / 'contract.json', contract) + if not fixture.exists(): + suite.prepare(fixture, cases) + manifest = suite.verify(fixture, cases) + freeze(root / 'fixtures.json', manifest) + order = list(revisions) + random.Random(20261107).shuffle(order) + ordered_cases = list(cases) + random.Random(20261108).shuffle(ordered_cases) + progress = {'total': len(order) * len(cases), 'completed': 0, 'new_cells': 0, 'state': 'running'} + started = time.monotonic() + for revision in order: + for case in ordered_cases: + completed = root / 'cells' / revision['sha'] / case.key / 'complete.json' + existing = completed.exists() + try: + collect_cell(case, revision, anchor, root, fixture, {key: value['path'] for key, value in tools.items()}, + launcher['path'], affinity, progress['completed'], args.repetitions) + except BaseException as error: + progress.update(state='failed', error=repr(error), pr=revision['pr'], case=case.key) + write(root / 'progress.json', progress) + raise + progress['completed'] += 1 + if not existing: + progress['new_cells'] += 1 + progress.update(utc=datetime.now(timezone.utc).isoformat(), pr=revision['pr'], case=case.key, + session_seconds=time.monotonic() - started) + write(root / 'progress.json', progress) + print(f'CELL {progress["completed"]}/{progress["total"]} PR #{revision["pr"]} {case.key} ' + f'{progress["session_seconds"]:.1f}s session', flush=True) + if args.limit and progress['new_cells'] >= args.limit: + print('Requested cell limit reached; resume with the same contract.', flush=True) + return + for record in (revision, anchor): + if digest(record['binary']) != record['binary_sha256']: + write(root / 'invalid.json', {'reason': 'binary changed while collecting', 'revision': record['sha']}) + raise ValueError('binary changed while collecting') + try: + suite.verify(fixture, cases) + for tool in tools.values(): + if digest(tool['path']) != tool['sha256']: + raise ValueError('reference executable changed while collecting') + if process_resources.launcher_identity(launcher['path']) != launcher: + raise ValueError('resource launcher changed while collecting') + except BaseException as error: + write(root / 'invalid.json', {'reason': repr(error)}) + raise + progress.update(state='complete', utc=datetime.now(timezone.utc).isoformat()) + write(root / 'progress.json', progress) + print('MEASUREMENT PHASE COMPLETE', flush=True) + + +if __name__ == '__main__': + main() diff --git a/tools/benchmark_extended_history_test.py b/tools/benchmark_extended_history_test.py new file mode 100644 index 00000000000..7be1172caff --- /dev/null +++ b/tools/benchmark_extended_history_test.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: Copyright (c) M. Boerger, the MBO Works authors +# SPDX-License-Identifier: Apache-2.0 +"""Guard interleaving, frozen contracts, resume, and failed-output retention.""" + +import json +from pathlib import Path +import tempfile +import unittest +from unittest import mock + +import benchmark_extended as suite +import benchmark_extended_history as history + + +class BenchmarkExtendedHistoryTest(unittest.TestCase): + def test_each_participant_gets_each_order_position(self): + labels = ['xff', 'find', 'anchor'] + for case in range(3): + orders = [history.round_order(labels, case, repetition) for repetition in range(1, 10)] + for position in range(3): + self.assertEqual([order[position] for order in orders].count('xff'), 3) + self.assertEqual([order[position] for order in orders].count('find'), 3) + self.assertEqual([order[position] for order in orders].count('anchor'), 3) + + def test_resume_rejects_changed_contract(self): + with tempfile.TemporaryDirectory() as temporary: + path = Path(temporary) / 'contract.json' + history.freeze(path, {'sha': 'old', 'keep': 7}) + history.freeze(path, {'sha': 'old', 'keep': 7}) + with self.assertRaisesRegex(ValueError, 'changed contract'): + history.freeze(path, {'sha': 'new', 'keep': 7}) + self.assertEqual(json.loads(path.read_text()), {'sha': 'old', 'keep': 7}) + + def test_warmups_and_all_samples_are_retained_and_completed_cells_resume(self): + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + case = suite.Case('files-exact', 'broad', 3, 1) + revision = {'sha': 'old', 'binary': '/old/xff'} + anchor = {'sha': 'new', 'binary': '/new/xff'} + sample = {'elapsed_seconds': .1, 'stdout_sha256': 'hash', 'validated_records': 3} + with mock.patch.object(history, 'invoke', return_value=sample) as invoke, \ + mock.patch.object(history, 'host_context', return_value={'utc': 'fixed'}): + args = (case, revision, anchor, root, root / 'fixture', {'find': '/bin/find'}, '/launcher', [0, 1, 2], 0, 3) + row = history.collect_cell(*args) + self.assertEqual(invoke.call_count, 12) + self.assertEqual(sum(s['phase'] == 'warmup' for s in row['samples']), 3) + self.assertEqual(sum(s['phase'] == 'measured' for s in row['samples']), 9) + self.assertEqual(row['commands']['xff'][0], '/old/xff') + self.assertEqual(row['commands']['anchor'][0], '/new/xff') + self.assertEqual(history.collect_cell(*args), row) + self.assertEqual(invoke.call_count, 12) + + def test_failed_attempt_never_becomes_a_completed_cell(self): + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + case = suite.Case('files-exact', 'broad', 3, 1) + args = (case, {'sha': 'old', 'binary': '/old'}, {'sha': 'new', 'binary': '/new'}, + root, root / 'fixture', {'find': '/bin/find'}, '/launcher', [0], 0, 1) + with mock.patch.object(history, 'invoke', side_effect=ValueError('incorrect output')), \ + mock.patch.object(history, 'host_context', return_value={}): + for _ in range(2): + with self.assertRaisesRegex(ValueError, 'incorrect output'): + history.collect_cell(*args) + directory = root / 'cells/old' / case.key + self.assertFalse((directory / 'complete.json').exists()) + self.assertTrue((directory / 'attempts/1/failure.json').is_file()) + self.assertTrue((directory / 'attempts/2/failure.json').is_file()) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/benchmark_extended_report.py b/tools/benchmark_extended_report.py new file mode 100644 index 00000000000..6eb5f00dd40 --- /dev/null +++ b/tools/benchmark_extended_report.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: Copyright (c) M. Boerger, the MBO Works authors +# SPDX-License-Identifier: Apache-2.0 +"""Analyze every extended-history cell and export the existing 3D history viewer.""" + +import argparse +from collections import defaultdict +import csv +import hashlib +import json +import math +from pathlib import Path +import random +import shutil +import statistics + +import benchmark_extended as suite +import benchmark_landscape as landscape +import benchmark_matrix as matrix + + +def mean_fastest(samples, keep): + values = [sample['elapsed_seconds'] for sample in samples] + if not 1 <= keep <= len(values) or any(not math.isfinite(value) or value <= 0 for value in values): + raise ValueError('invalid timing population') + return statistics.fmean(sorted(values)[:keep]) + + +def paired_interval(left, right): + """95% bootstrap interval for paired geometric ratios, using all measured rounds. + + This describes within-cell variability, not independent-machine reproducibility. + It deliberately differs from the existing chart's fastest-7/9 estimator. + """ + a = {sample['round']: sample['elapsed_seconds'] for sample in left} + b = {sample['round']: sample['elapsed_seconds'] for sample in right} + if len(a) != len(left) or len(b) != len(right) or a.keys() != b.keys() or not a: + raise ValueError('unpaired or duplicate rounds') + values = [math.log(a[key] / b[key]) for key in sorted(a)] + rng = random.Random(20261107) + estimates = sorted(math.exp(statistics.fmean(rng.choices(values, k=len(values)))) for _ in range(1000)) + return [estimates[24], estimates[974]] + + +def summarize_cell(row, contract): + participants = defaultdict(list) + for sample in row['samples']: + if sample['phase'] == 'measured': + participants[sample['label']].append(sample) + if set(participants) != set(row['commands']): + raise ValueError('missing participant measurements') + for samples in participants.values(): + if len(samples) != contract['repetitions'] or {s['round'] for s in samples} != set(range(1, contract['repetitions'] + 1)): + raise ValueError('missing or repeated sampling rounds') + if any(s['exit_codes'] != [0] or s['stderr_bytes'] or s['validated_records'] != row['expected_records'] for s in samples): + raise ValueError('unvalidated sample') + means = {label: mean_fastest(samples, contract['keep']) for label, samples in participants.items()} + references = set(means) - {'xff', 'anchor'} + if len(references) != 1: + raise ValueError('expected one traditional reference') + reference = references.pop() + lower, upper = paired_interval(participants['xff'], participants['anchor']) + return dict(row['case'], sha=row['revision']['sha'], pr=row['revision']['pr'], + binary_sha256=row['revision']['binary_sha256'], reference=reference, + xff_seconds=means['xff'], anchor_seconds=means['anchor'], reference_seconds=means[reference], + reference_over_xff=means[reference] / means['xff'], + historical_over_current=means['xff'] / means['anchor'], + current_time_reduction_percent=100 * (1 - means['anchor'] / means['xff']), + paired_ratio_ci_low=lower, paired_ratio_ci_high=upper) + + +def as_report(rows, contract, view): + """Adapt real cells without filling unmeasured sizes or mixing suite identities.""" + tasks = [] + for row in rows: + case = row['case'] + participants = {} + for label, command in row['commands'].items(): + if ((label == 'anchor' and view == 'traditional') or + (label not in ('xff', 'anchor') and view == 'anchor')): + continue + name = 'xff-at-' + str(contract['anchor']['pr']) if label == 'anchor' else label + participants[name] = {'pipeline': [command], 'cwd': row['cwd'], + 'samples': [sample for sample in row['samples'] + if sample['label'] == label and sample['phase'] == 'measured']} + tasks.append({'name': case['name'], 'dataset': case['shape'], 'shape': case['shape'], + 'files': case['files'], 'input_files': case['files'], 'cpus': case['cpus'], + 'expected_count': row['expected_records'], 'expected_sha256': row['expected_sha256'], + 'participants': participants, 'skips': {}}) + return {'contract': {'suite': contract['recipe'], 'platform': contract['platform'], + 'cpu_counts': sorted({case['cpus'] for case in contract['cases']}), + 'file_counts': sorted({case['files'] for case in contract['cases']}), + 'affinity_by_cpu_count': {str(n): contract['affinity'][:n] + for n in {case['cpus'] for case in contract['cases']}}, + 'repetitions': contract['repetitions'], 'retained': contract['keep'], + 'estimator': 'mean-fastest'}, 'tasks': tasks} + + +def export_viewer(output, contract, revisions, renderer): + assets = output / 'assets' + assets.mkdir(exist_ok=True) + shutil.copyfile(renderer, assets / 'three-landscape.js') + catalog = [] + for view, title in [('traditional', 'Traditional tools'), ('anchor', f'Fixed XFF at PR #{contract["anchor"]["pr"]}')]: + reports = [(revision, rows, as_report(rows, contract, view)) for revision, rows in revisions] + order = landscape.common_task_order([matrix.relative_results(report) for _, _, report in reports]) + for revision, rows, report in reports: + directory = output / revision['sha'] + directory.mkdir(exist_ok=True) + data = landscape.figures(report, task_order=order) + (directory / (view + '.json')).write_text(json.dumps(data, allow_nan=False) + '\n') + document = landscape.render(report, '', task_order=order).replace( + '', '') + (directory / (view + '.html')).write_text(document) + catalog.append({'platform': 'Drogon / ' + contract['recipe'] + ' / ' + title, + 'platform_name': contract['platform'], 'dataset_type': contract['recipe'] + ' / ' + title, + 'commit': revision['sha'], 'date': revision['date'], + 'label': f'PR #{revision["pr"]} / {revision["sha"][:10]}', + 'source': 'merged', 'source_label': 'Merged history', 'local': True, + 'measured': rows[-1]['after']['utc'], 'measurement_date': rows[-1]['after']['utc'], + 'report': revision['sha'] + '/' + view + '.html', + 'figures': revision['sha'] + '/' + view + '.json', + 'links': [{'label': f'PR #{revision["pr"]}', 'href': f'https://github.com/mboworks/xff/pull/{revision["pr"]}'}], + 'binary': {'state': 'Consistent', 'sha256': revision['binary_sha256'], + 'reason': 'Clean historical source, configured production ThinLTO build, frozen executable hash checked before and after collection.'}, + 'identity': 'Drogon Linux extended qualification', 'platform_details': contract['platform']}) + (output / 'catalog.json').write_text(json.dumps(catalog, indent=2) + '\n') + intro = ('
Independent extended suite; production full binaries on Linux tmpfs. ' + 'Each historical run is interleaved with the fixed current binary and a traditional tool. ' + f'{len(revisions)} complete revisions are shown, including regressions and unchanged controls.
') + (output / 'index.html').write_text(intro + landscape.history_panel(catalog) + '') + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--campaign', type=Path, required=True) + parser.add_argument('--output', type=Path, required=True) + parser.add_argument('--renderer-js', type=Path) + parser.add_argument('--allow-partial', action='store_true') + args = parser.parse_args() + root = args.campaign + if (root / 'invalid.json').exists(): + raise ValueError('campaign identity verification failed') + progress = json.loads((root / 'progress.json').read_text()) + if not args.allow_partial and progress['state'] != 'complete': + raise ValueError('measurement campaign is not complete') + contract = json.loads((root / 'contract.json').read_text()) + output = args.output + output.mkdir(parents=True, exist_ok=True) + rows, revisions = [], [] + for revision in contract['revisions']: + cells = [] + for case in contract['cases']: + path = root / 'cells' / revision['sha'] / suite.Case(**case).key / 'complete.json' + if not path.exists() and args.allow_partial: + continue + row = json.loads(path.read_text()) + if row['case'] != case or row['revision'] != revision or row['anchor'] != contract['anchor']: + raise ValueError('cell provenance differs from campaign contract') + rows.append(summarize_cell(row, contract)) + cells.append(row) + if len(cells) == len(contract['cases']): + revisions.append((revision, cells)) + if not rows: + raise ValueError('no completed measurement cells') + with (output / 'cells.csv').open('w') as file: + writer = csv.DictWriter(file, fieldnames=list(rows[0])) + writer.writeheader() + writer.writerows(rows) + controls = [row for row in rows if row['binary_sha256'] == contract['anchor']['binary_sha256']] + noise = sorted(abs(math.log(row['historical_over_current'])) for row in controls) + summary = {'recipe': contract['recipe'], 'state': progress['state'], 'cells': len(rows), + 'complete_revisions': len(revisions), 'expected_revisions': len(contract['revisions']), + 'identical_binary_control_cells': len(controls), + 'control_p95_factor': math.exp(noise[min(len(noise) - 1, int(len(noise) * .95))]) if noise else None, + 'interval': '95% paired-round bootstrap geometric ratio; within-cell variability only', + 'contract_sha256': hashlib.sha256((root / 'contract.json').read_bytes()).hexdigest(), + 'endpoints': {str(revision['pr']): [row for row in rows if row['sha'] == revision['sha']] + for revision in (contract['revisions'][0], contract['revisions'][-1])}} + (output / 'summary.json').write_text(json.dumps(summary, indent=2) + '\n') + if args.renderer_js and revisions: + export_viewer(output, contract, revisions, args.renderer_js) + print(json.dumps({key: value for key, value in summary.items() if key != 'endpoints'}, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/tools/benchmark_extended_report_test.py b/tools/benchmark_extended_report_test.py new file mode 100644 index 00000000000..494ebc16c9c --- /dev/null +++ b/tools/benchmark_extended_report_test.py @@ -0,0 +1,67 @@ +# SPDX-FileCopyrightText: Copyright (c) M. Boerger, the MBO Works authors +# SPDX-License-Identifier: Apache-2.0 +"""Check historical ratios, paired uncertainty, and real-only renderer populations.""" + +import copy +import unittest + +import benchmark_extended_report as report + + +class BenchmarkExtendedReportTest(unittest.TestCase): + def row(self): + return {'case': {'name': 'archive-tar', 'shape': 'broad', 'files': 100, 'cpus': 1}, + 'revision': {'sha': 'old', 'pr': 1, 'binary_sha256': 'hash'}, 'expected_records': 50, + 'expected_sha256': 'oracle', 'cwd': '/fixture', + 'commands': {'xff': ['/old/xff'], 'anchor': ['/new/xff'], 'tar': ['/bin/tar']}, + 'samples': [dict(label=label, round=repetition, phase='measured' if repetition else 'warmup', + elapsed_seconds=seconds if repetition else 500, + exit_codes=[0], stderr_bytes=0, validated_records=50) + for repetition in range(4) for label, seconds in [('xff', 4), ('anchor', 2), ('tar', 8)]]} + + def contract(self): + return {'repetitions': 3, 'keep': 2, 'anchor': {'pr': 2}, 'recipe': 'extended-production-v1', + 'platform': 'Linux', 'cases': [self.row()['case']], 'affinity': [0, 1, 2]} + + def test_known_ratios_and_warmup_exclusion(self): + result = report.summarize_cell(self.row(), self.contract()) + self.assertEqual(result['xff_seconds'], 4) + self.assertEqual(result['historical_over_current'], 2) + self.assertEqual(result['reference_over_xff'], 2) + self.assertEqual(result['current_time_reduction_percent'], 50) + self.assertEqual(result['paired_ratio_ci_low'], 2) + self.assertEqual(result['paired_ratio_ci_high'], 2) + + def test_missing_duplicate_and_incorrect_samples_are_rejected(self): + row = self.row() + variants = [copy.deepcopy(row) for _ in range(3)] + variants[0]['samples'].pop() + variants[1]['samples'][-1]['round'] = 2 + variants[2]['samples'][-1]['validated_records'] = 49 + for variant in variants: + with self.assertRaises(ValueError): + report.summarize_cell(variant, self.contract()) + + def test_fastest_estimator_and_control_interval(self): + self.assertEqual(report.mean_fastest([{'elapsed_seconds': value} for value in (2, 5, 1)], 2), 1.5) + samples = [{'round': i, 'elapsed_seconds': value} for i, value in enumerate([1, 2, 3])] + self.assertEqual(report.paired_interval(samples, samples), [1, 1]) + with self.assertRaises(ValueError): + report.paired_interval(samples, [*samples, samples[-1]]) + + def test_renderer_adapter_does_not_invent_cells_or_mix_references(self): + for view, expected in [('traditional', {'xff', 'tar'}), ('anchor', {'xff', 'xff-at-2'})]: + adapted = report.as_report([self.row()], self.contract(), view) + self.assertEqual(len(adapted['tasks']), 1) + self.assertEqual(adapted['contract']['file_counts'], [100]) + self.assertEqual(adapted['contract']['suite'], 'extended-production-v1') + task = adapted['tasks'][0] + self.assertEqual(task['files'], 100) + self.assertEqual(task['dataset'], 'broad') + self.assertEqual(set(task['participants']), expected) + for participant in task['participants'].values(): + self.assertEqual(len(participant['samples']), 3) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/benchmark_extended_test.py b/tools/benchmark_extended_test.py new file mode 100644 index 00000000000..a0a0de1bcdb --- /dev/null +++ b/tools/benchmark_extended_test.py @@ -0,0 +1,106 @@ +# SPDX-FileCopyrightText: Copyright (c) M. Boerger, the MBO Works authors +# SPDX-License-Identifier: Apache-2.0 +"""Check fixture semantics and reject incorrect benchmark outputs.""" + +from pathlib import Path +import re +import tarfile +import tempfile +import unittest + +import benchmark_extended as suite + + +class BenchmarkExtendedTest(unittest.TestCase): + def test_case_grid_has_unique_cells_and_bounded_archive_sizes(self): + cases = suite.cases() + self.assertEqual(len(cases), 60) + self.assertEqual(len({case.key for case in cases}), len(cases)) + self.assertEqual({c.files for c in cases if c.name == 'archive-tar'}, {100, 1000, 10000}) + self.assertEqual({c.files for c in cases if c.name != 'archive-tar'}, {100, 10000, 100000}) + for name in suite.TASKS: + self.assertEqual({c.cpus for c in cases if c.name == name}, {1, 3}) + for values in [('unknown', 'broad', 1, 1), ('files-exact', 'wide', 1, 1), + ('files-exact', 'deep', 0, 1), ('files-exact', 'deep', 1, 0)]: + with self.assertRaises(ValueError): + suite.Case(*values) + + def test_content_fixture_matches_the_regex_and_preserves_nonmatches(self): + rows = list(suite.entries('broad', 100)) + self.assertEqual(len(rows), 100) + self.assertEqual({len(data) for _, data, _ in rows}, {256, 8192}) + actual = [name for name, data, _ in rows if re.search(suite.PATTERN.encode(), data)] + self.assertEqual(actual, [f'item_{i:06}.txt' if i % 2 == 0 else f'item_{i:06}.log' + for i in range(0, 100, 3)]) + + def test_oracles_have_explicit_paths_metadata_and_selections(self): + parent = Path('/fixture') + expectations = { + 'files-exact': [b'./item_000000.txt', b'./item_000001.log', b'./item_000002.txt'], + 'name-native': [b'/fixture/native/broad/3/item_000000.txt', b'/fixture/native/broad/3/item_000002.txt'], + 'metadata-time': [b'/fixture/native/broad/3/item_000000.txt\t8192\t2020-01-02', + b'/fixture/native/broad/3/item_000002.txt\t256\t2020-01-02'], + 'content-regex': [b'/fixture/native/broad/3/item_000000.txt'], + 'archive-tar': [b'fixture.tar/d0000/item_000000.txt', b'fixture.tar/d0000/item_000002.txt'], + } + for task, expected in expectations.items(): + with self.subTest(task=task): + self.assertEqual(suite.expected(suite.Case(task, 'broad', 3, 1), parent), expected) + + def test_materialized_native_and_archive_fixtures_match_recipe(self): + cases = [suite.Case(task, shape, 6, 1) for task in ('files-exact', 'archive-tar') for shape in ('broad', 'deep')] + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) / 'fixture' + suite.prepare(root, cases) + self.assertEqual(len(suite.verify(root, cases)['fixtures']), 4) + for shape in ('broad', 'deep'): + with tarfile.open(root / 'archive' / shape / '6/fixture.tar') as archive: + members = archive.getmembers() + self.assertEqual(len(members), 6) + for member, (name, data, _) in zip(members, suite.entries(shape, 6, True), strict=True): + self.assertEqual(member.name, name) + self.assertTrue(member.isfile()) + self.assertEqual(member.mtime, suite.MTIME) + self.assertEqual(archive.extractfile(member).read(), data) + with self.assertRaises(FileExistsError): + suite.prepare(root, cases) + + def test_fixture_changes_are_rejected(self): + case = suite.Case('files-exact', 'broad', 3, 1) + mutations = [lambda root: (root / 'native/broad/3/item_000000.txt').write_bytes(b'wrong'), + lambda root: (root / 'native/broad/3/item_000000.txt').chmod(0o600), + lambda root: (root / 'native/broad/3/extra').write_bytes(b'extra')] + for mutation in mutations: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) / 'fixture' + suite.prepare(root, [case]) + mutation(root) + with self.assertRaisesRegex(ValueError, 'changed'): + suite.verify(root, [case]) + + def test_validation_compares_multisets_and_checks_status_and_bytes(self): + sample = {'exit_codes': [0], 'stderr_bytes': 0, 'stderr': '', 'output': b'b\0a\0', 'stdout_bytes': 4} + self.assertEqual(len(suite.validate(sample, [b'a', b'b'], b'\0')), 64) + for changes in ({'output': b'a\0a\0'}, {'output': b'a\0', 'stdout_bytes': 2}, + {'output': b'b\0a'}, {'exit_codes': [1]}, {'stderr_bytes': 4, 'stderr': 'oops'}, + {'stdout_bytes': 5}): + with self.subTest(changes=changes), self.assertRaises(ValueError): + suite.validate(dict(sample, **changes), [b'a', b'b'], b'\0') + + def test_commands_keep_native_case_and_equivalent_archive_paths(self): + tools = {'find': '/bin/find', 'rg': '/bin/rg', 'tar': '/bin/tar'} + commands, _, separator = suite.commands(suite.Case('name-native', 'deep', 100, 3), + Path('/fixture'), '/bin/xff', tools) + self.assertNotIn('--exact', commands['xff']) + self.assertFalse(any(arg.startswith('--case=') for arg in commands['xff'])) + self.assertIn('--jobs=3', commands['xff']) + commands, _, separator = suite.commands(suite.Case('archive-tar', 'deep', 100, 1), + Path('/fixture'), '/bin/xff', tools) + self.assertEqual(separator, b'\n') + self.assertIn('--archive-separator=/', commands['xff']) + self.assertIn('--transform=s,^,fixture.tar/,', commands['tar']) + self.assertNotIn('-printf', commands['xff']) + + +if __name__ == '__main__': + unittest.main() From 376562d698d97bd8181542e69d80ae837b6732c1 Mon Sep 17 00:00:00 2001 From: helly25 <6420169+helly25@users.noreply.github.com> Date: Sat, 7 Nov 2026 13:42:33 +0000 Subject: [PATCH 02/20] Expose benchmark CPU costs and retain historical build identities --- docs/benchmark-extended-history-campaign.md | 30 +- .../extended-history-builds-20261107.json | 1231 +++++++++++++++++ tools/benchmark_extended_report.py | 92 +- tools/benchmark_extended_report_test.py | 48 + 4 files changed, 1388 insertions(+), 13 deletions(-) create mode 100644 docs/benchmarks/extended-history-builds-20261107.json diff --git a/docs/benchmark-extended-history-campaign.md b/docs/benchmark-extended-history-campaign.md index ee0c97e9d90..cdd9426da47 100644 --- a/docs/benchmark-extended-history-campaign.md +++ b/docs/benchmark-extended-history-campaign.md @@ -87,9 +87,16 @@ python3.13 tools/benchmark_extended_report.py \ ``` The report exports every cell to CSV, endpoint summaries/control noise to JSON, and two datasets -using the existing 3D history viewer: traditional tools and fixed-current XFF comparisons. Serve -the report directory over HTTP for JSON fetches. `--allow-partial` is for monitoring; the default -refuses incomplete campaigns. +using the existing 3D history viewer: traditional tools and fixed-current XFF comparisons. +The cell CSV includes user/kernel CPU, peak child RSS and first-output latency, taken from the +same samples selected by wall time. `history-by-task.csv` equally weights the shape/worker +combinations using geometric means at each task/size; it omits incomplete groups. These grouped +ratios supplement the individual measured cells rather than replacing them. +`current-versus-reference.csv` uses the fixed-current participant from every historical block +to describe the remaining reference-tool gap for each individual case. Its 10th/90th percentiles +describe the observed spread across those blocks, not confidence across independent machines. +Serve the report directory over HTTP for JSON fetches. `--allow-partial` is for monitoring; the +default refuses incomplete campaigns. The historical LLVM 22 linker on drogon requires ICU 70. System installation required interactive sudo authentication, so the official Ubuntu `libicu70_70.1-2ubuntu1_amd64.deb` was extracted into @@ -114,10 +121,21 @@ On `drogon.boerger.online`, the root is `/home/marcus/Documents/xff-chart-campai - `measurements/cells/.../attempts/`: warm-ups, samples and failure evidence. - `qualified/logs/build-campaign.log` and `logs/measurements.log`: progress logs. -The 240 endpoint functional checks and native-worker checks passed. Historical build/measurement -collection is in progress; these functional checks establish no performance improvement. +The 240 endpoint functional checks and native-worker checks passed. All 130 production builds +completed before timing collection. The +[build summary](benchmarks/extended-history-builds-20261107.json) records 77 distinct executable +hashes; 53 adjacent revision pairs have identical executable bytes. PRs #1128, #1129 and #1130 +also share the current executable hash, providing identical-binary controls in the campaign. + +Measurement collection is in progress. A separate endpoint repeat is queued after successful +completion: every one of the 60 predeclared cases at both endpoints, fresh tmpfs fixtures, +27 measured rounds retaining the fastest 21. It uses the same frozen production binaries and +does not select only favorable cases. The repeated data has its own contract and directory +(`confirmation/`) and must not be merged with the nine-round historical population. Before the +repeat, an independent pass rehashes all 130 retained binaries and their build/link evidence. Select CI workloads from completed results, retain the simple control, and report flat or -regressing cases alongside improvements. +regressing cases alongside improvements. A historical improvement alone does not establish that +XFF is competitive with its traditional reference. The [synthetic viewer check](benchmarks/extended-history-viewer-check-20261107.json) verifies both exported dataset views in Chromium. Both historical versions produce their exact expected diff --git a/docs/benchmarks/extended-history-builds-20261107.json b/docs/benchmarks/extended-history-builds-20261107.json new file mode 100644 index 00000000000..6b118c3c3a9 --- /dev/null +++ b/docs/benchmarks/extended-history-builds-20261107.json @@ -0,0 +1,1231 @@ +{ + "target": "//xff/cli:xff_full", + "configs": ["clang_release", "xff_full"], + "manifest_sha256": "759b4894bf37262898630815cdf827a0a290ecbe106d75d85e5d573564f8fe57", + "revision_count": 130, + "distinct_binary_hashes": 77, + "identical_adjacent_binaries": 53, + "revisions": [ + { + "pr": 977, + "sha": "21c7f3656b005b23113d936c1cd2ca0fd2221ab2", + "tree": "396bbbb94ae043cb84672d7abbcd5cdb7e7b9e09", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "400ada11d7122587013d2fcbefc9bd6fd7e6aa80878867ed7046f915f2d8087a", + "elapsed_seconds": 75.14972471701913 + }, + { + "pr": 981, + "sha": "c33efe99d0df0b4866a9f77fde71dde9959d3cdb", + "tree": "8b009345d5e4ac726f07835f6a8f5dc58761b2ba", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "856a3d3720b2275136c5e2278731e4570a1852edeffe98e68abf7c79f725cb3b", + "elapsed_seconds": 0.89143300591968 + }, + { + "pr": 982, + "sha": "103fbf65b22979f75f5adbac67a53f15cf74d03e", + "tree": "8469b6f66af9d3821ad59186cd6a99b3551d0e81", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "d3acf93daf4654871a2bac3dc179ad167caa365738a5dd47762ebc2b8eb7fe80", + "elapsed_seconds": 0.6069001959403977 + }, + { + "pr": 985, + "sha": "9210100af8007a2f17b22597a349714d9e6069e1", + "tree": "d76ccfa5a38cc30af8b71f2ada872fd0a8037ff7", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "e94d6646c7ea5de7fc2013ebd206d1bfc7ad52184dfc57ef18fc465697cd2d88", + "elapsed_seconds": 0.6095801409101114 + }, + { + "pr": 986, + "sha": "61ab1ce41300aa785d6beafb46c29b29dc832b8d", + "tree": "a0dce9fc2f1eeb67a3fd6e99d10534b8a5adc527", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "2dd7cd4ddd5bf7f15ed432bd393a46573bc39d99f18aa44dbea4f598bf531ede", + "elapsed_seconds": 0.5166276399977505 + }, + { + "pr": 987, + "sha": "4bce0bb39186d1dfbe122038f17ef660447599c6", + "tree": "73044eba04517e538b8f7bf8143eccb8a08bc702", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "4e2a1439ee3422d6311ad3b5fdcdb6fc607416a2dcebeddde0aebe582fb1ee52", + "elapsed_seconds": 0.5408426729263738 + }, + { + "pr": 988, + "sha": "fa41587198981a5619e408c41be80cb22b8dd439", + "tree": "bf7951eaac026e4fea79100253623ba5f02bd93f", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "e2af2a7f5f5176289967a5c4d3fb7363730adb43cb85da0d8970fbd6fa398189", + "elapsed_seconds": 0.5303708449937403 + }, + { + "pr": 989, + "sha": "772994ab7905be77915978f06ea90ae5934aaeef", + "tree": "8f797cae4320ba5cb497d580eb4b158f5eaf007b", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "b75271b5a7a3c29289770b7ab50519de29b046e3dcd4369a367a380433b6e216", + "elapsed_seconds": 0.5656200320227072 + }, + { + "pr": 990, + "sha": "4ea895f63106f05df7c90b629d20433ae1e03016", + "tree": "a56a093c3fdcb1af6c93fa4cb805cdad724b1707", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "4f3136d1fa6ac0d3f44cdd5a0017e6d01373fd25e372e8c9e9c6b1f898b0ad96", + "elapsed_seconds": 0.5688729950925335 + }, + { + "pr": 993, + "sha": "dac3747d63cad713def0b949a934dfe36f82da63", + "tree": "08ce5a524ac2af07dac04846fec69757cde99be4", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "aa78e865c8e8998d19597a7e13bccb7ee8579db9dbeeeaee2d9fd324a3a23d2a", + "elapsed_seconds": 0.547393971006386 + }, + { + "pr": 994, + "sha": "88d4facd15ebd00acf749222b3028de2e8916970", + "tree": "db9ef3cd231ef81fd50e1db276469648e70e7266", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "04f63a1e2776d59bf2a8ac152c7e8ab006b8d9643957fd2e4dd8430f78a21dc3", + "elapsed_seconds": 0.7202342130476609 + }, + { + "pr": 999, + "sha": "bbc0bf9376c7fc41fe75094998c3c7e74bd02e94", + "tree": "38d5ecc9e1789f0f0a187960c24daee1f7884da0", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "664892ae86605427fa7762ed9b387aaaecaf4097d86f38e6d393130438c28f0a", + "elapsed_seconds": 0.5682561640860513 + }, + { + "pr": 1003, + "sha": "b137c8a6800aa0c1d6f2d67342f291b25783747f", + "tree": "9d797c1330a4369394feb3fcbdb700b3c26557c4", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "abf111a85f39ab32c26aeb77f62382bd53a3e64c25f4d0c20849bb3e059417e2", + "elapsed_seconds": 0.5620602199342102 + }, + { + "pr": 1004, + "sha": "d73eea93ac97f401fe12ba2ba139eb6b8601ec19", + "tree": "2eadb23385811cad1adb6e428d9ecb58b0828247", + "binary_sha256": "f8577e4753dc90640bd926ac80ce7277be9791491bf4e15bfdcd1a3777ef8e47", + "bytes": 17651872, + "build_manifest_sha256": "f5adc29df05ba25b80e6079797e0175ad189f91677d8a113dc4eb8f0f1c67afe", + "elapsed_seconds": 5.435096765984781 + }, + { + "pr": 1006, + "sha": "20095dd53c31e510aac2256fc93d34026e4f463c", + "tree": "6d5d24ce2849ba5a16d028b0b83edc06bb2e41da", + "binary_sha256": "89c945084c20987f773222b9dd6411c5705ed5009f67f9514248b72bb9d48484", + "bytes": 17652128, + "build_manifest_sha256": "e31cb8c749292da02d2c6d150e9c89e216cf8b7f6ad134beb302cf0677bdcb7e", + "elapsed_seconds": 28.295815887046047 + }, + { + "pr": 1007, + "sha": "33a01e13d7cd27ee7f866802fc2f74998fdcaabb", + "tree": "1226bc110bb9a1004be74107e23fd194e9f30a0f", + "binary_sha256": "89c945084c20987f773222b9dd6411c5705ed5009f67f9514248b72bb9d48484", + "bytes": 17652128, + "build_manifest_sha256": "4b07329c072c1e0635d4e8ee87f62b8426b676eab581d8e292875269470a8a5c", + "elapsed_seconds": 4.9203253800515085 + }, + { + "pr": 1005, + "sha": "bfe77198c06bc1e4a23e23ea292ab47cb4b6a0e4", + "tree": "c8fb309f5863ef1ec06c94dd94d0b0af845932f4", + "binary_sha256": "89c945084c20987f773222b9dd6411c5705ed5009f67f9514248b72bb9d48484", + "bytes": 17652128, + "build_manifest_sha256": "c87d03c0711fcfe2d7dbc47dc7a924198e925d5fa2fdbc8b2035c6d55e6d540c", + "elapsed_seconds": 12.504761731019244 + }, + { + "pr": 1009, + "sha": "1f85d90e3441737304d9f3647523cfc408ca54a9", + "tree": "8eff6419aaace3b3d55ac13cf57e281e1f5f15f6", + "binary_sha256": "89c945084c20987f773222b9dd6411c5705ed5009f67f9514248b72bb9d48484", + "bytes": 17652128, + "build_manifest_sha256": "e87b6b7f07447603b44993f2277d8696e347958f085ca1e20837c6e32acba4ed", + "elapsed_seconds": 1.9633059169864282 + }, + { + "pr": 1010, + "sha": "a5f9c9ec07419101cfe73ec4b42c3c29c529edad", + "tree": "898b64ea26fd89182653fd004a846882ab26d47c", + "binary_sha256": "89c945084c20987f773222b9dd6411c5705ed5009f67f9514248b72bb9d48484", + "bytes": 17652128, + "build_manifest_sha256": "6ed629c53c8b923ca8e902681c0fbaaef4e3ecb7a3e2da7d4afe2d2737baf3a3", + "elapsed_seconds": 1.5160633369814605 + }, + { + "pr": 1008, + "sha": "a21ada79bbe9cad232a174cfdb4e8923ed891f2a", + "tree": "f6fa05e9d31fece19f10872b030bbc308d6ef7d1", + "binary_sha256": "89c945084c20987f773222b9dd6411c5705ed5009f67f9514248b72bb9d48484", + "bytes": 17652128, + "build_manifest_sha256": "2818f8b75beb79bc504e38c6f4aad8844228d1eba3033dada0c3dce95c299e90", + "elapsed_seconds": 159.1304149379721 + }, + { + "pr": 1012, + "sha": "ae62c828a3f3502a9bcf4805188913a1aaaf264c", + "tree": "1712ccb4b9857795a27ef4169a0695e2f6eddce9", + "binary_sha256": "89c945084c20987f773222b9dd6411c5705ed5009f67f9514248b72bb9d48484", + "bytes": 17652128, + "build_manifest_sha256": "e52174c74b60c06b958067cc78244bff348bf9b871c44436a89ecd246a5be000", + "elapsed_seconds": 0.7854754580184817 + }, + { + "pr": 1011, + "sha": "801087f3e9a8bf192928896c7f24c369003d1e7b", + "tree": "54e959ef24d61db598379da3e5ebf160bbef262e", + "binary_sha256": "ec53e6ebbb6d1dd4aa1a99d59404ae183d0edcac20df8f69f8228655db3e59ac", + "bytes": 17767888, + "build_manifest_sha256": "0f5039e09e342e5bc743196e38f58a751c665cec80b9144a811669cff40e5f39", + "elapsed_seconds": 76.2379414329771 + }, + { + "pr": 1013, + "sha": "3dbc47cc2a1d84c0e6b60f0a497c1d3ce160351f", + "tree": "994c60029718dc7123d60f41d88ba0048eefa4e2", + "binary_sha256": "ec53e6ebbb6d1dd4aa1a99d59404ae183d0edcac20df8f69f8228655db3e59ac", + "bytes": 17767888, + "build_manifest_sha256": "efbc7073dd4f30214e9ec249b56e44d424b663a39bfab7b38db0c223fcf6711d", + "elapsed_seconds": 1.1680861730128527 + }, + { + "pr": 1019, + "sha": "8e95f5546187b2a6f4ec165af9cf794af18ac4a1", + "tree": "b4ff119af9eb51555216200e080c843854ef6c92", + "binary_sha256": "7d2cbe55218fda321b6894717c6a5deeb1e679641b3c10db52af6a8a40f7e0d5", + "bytes": 17882880, + "build_manifest_sha256": "fbb3b922cc58cb0dea35c9d733b997ab828e3e64a4d42982454d1da7a5a5db56", + "elapsed_seconds": 18.508985477034003 + }, + { + "pr": 1021, + "sha": "1642f49d7b400596af3ed627f5b9f42cc24e4237", + "tree": "b5399eee33c2f3d23b862b3b48cc98fc7eddc4e5", + "binary_sha256": "7d2cbe55218fda321b6894717c6a5deeb1e679641b3c10db52af6a8a40f7e0d5", + "bytes": 17882880, + "build_manifest_sha256": "878980f78820a3ce9466dbc46888eef053203a31a5bd9472680556a6a6665fcd", + "elapsed_seconds": 0.5626644470030442 + }, + { + "pr": 1020, + "sha": "eaa034527a286ed87f1f74b8e88ba5b7007fb31a", + "tree": "babc8e9bc78da96ddd01ca71dd25185d02386127", + "binary_sha256": "7d2cbe55218fda321b6894717c6a5deeb1e679641b3c10db52af6a8a40f7e0d5", + "bytes": 17882880, + "build_manifest_sha256": "8acd12910fcfff1b9832b17664786104696e7beba45f9b86be8dce148548c024", + "elapsed_seconds": 0.5181690179742873 + }, + { + "pr": 1022, + "sha": "02292572cac61101036c032ece8e11675d580d7e", + "tree": "a85d7dc78c242955dca7dbc66a50200c7a2dbb13", + "binary_sha256": "0c78e33b6a3ea712686eea249d26ad02b422470531d1092b64b6721e2362fa8e", + "bytes": 17958792, + "build_manifest_sha256": "8f82230f43b43ff3c49a14a0349d1583606ac4ac035020db694c19c9bbdab6e4", + "elapsed_seconds": 11.223397571942769 + }, + { + "pr": 1023, + "sha": "b52571f81b8ecec116a4249f51b7d5e72175248c", + "tree": "ae7c43483a26f479eea45438aeda15e30ddd0572", + "binary_sha256": "18242300e2c72ebc3fc3221180245ff2ac4240cb4945610840165d63a13f48ed", + "bytes": 17942672, + "build_manifest_sha256": "969d7b9bb508b5cfb115647813c6ae6e305a54d2ed022c7d32ea511eb0c4ecc8", + "elapsed_seconds": 20.09151629707776 + }, + { + "pr": 1024, + "sha": "f0407980edd2bc2497dc0f406b2fed1977caaaea", + "tree": "7e8fdbddb1ea682d4db19a9a767077560135e52b", + "binary_sha256": "673fb8d4c626a9bcbb141b0629a92fdbec0a4b6bc3c968bd9328b6eb9a5143f6", + "bytes": 17968672, + "build_manifest_sha256": "c6278a5611fc124366ea3d85d5d028deb73796be176fec8f6970f23a6b53c56a", + "elapsed_seconds": 12.889048965997063 + }, + { + "pr": 1025, + "sha": "4c87962565391caf32b669c6a8a55d7495999921", + "tree": "a31583f93a3befa38dcc21facdf8b9a1be28d549", + "binary_sha256": "55e0cf69118d43d6ccfff0ae848edb0f1b4831acb0a7fc029ffc11fda7316d44", + "bytes": 17986200, + "build_manifest_sha256": "842dcd01d74b5755dff4e2bd8547a418f13af412cdf425d94747c530f5d5e789", + "elapsed_seconds": 12.295493853045627 + }, + { + "pr": 1026, + "sha": "b7fd2c2d0c5d50d8e5895f36fe39f802ac2dcb76", + "tree": "30471bc50f1e3a8ef4ae0919f1320e8161419b74", + "binary_sha256": "55e0cf69118d43d6ccfff0ae848edb0f1b4831acb0a7fc029ffc11fda7316d44", + "bytes": 17986200, + "build_manifest_sha256": "cd3830008cf166dc0f4f3ce007bea7d5cd5d2dde2773aecfa79f8f9840bf7e5b", + "elapsed_seconds": 0.5216331530828029 + }, + { + "pr": 1027, + "sha": "d406f4132d067d4e87a8df1426753a7d0203abd6", + "tree": "4bf27451fc57d54a3048bc8883d9036ca3c28382", + "binary_sha256": "87da17972facc51a726540367e0ab90d8eeb94a37bb0bb0e6454430f7d707198", + "bytes": 17985512, + "build_manifest_sha256": "64b14a53fe2d20d80f9d357708716cfe4a1ad97e5dc83e8ebaaf9ac255093fdb", + "elapsed_seconds": 10.479590691975318 + }, + { + "pr": 1028, + "sha": "d47b00bfeeb3b98606d806c4b21664870d3ddfaa", + "tree": "f60dfaeb147725edd27f4d1e22215fa42fb77e5d", + "binary_sha256": "c594249b32181aa2708081a51e3fd1d80876f87a1a1c14de5dc745192f74916c", + "bytes": 17993920, + "build_manifest_sha256": "6cc1c5ff26c7af96714448ad3fb8ed06d363b8c88cbe6a812332a908a43a2e11", + "elapsed_seconds": 6.61649262602441 + }, + { + "pr": 1029, + "sha": "3292b6f308ab92f61d8575c95ee2cef2c41e4205", + "tree": "02d6a9bef548a0d29d1fa27507ba55ddfa7f43ab", + "binary_sha256": "c594249b32181aa2708081a51e3fd1d80876f87a1a1c14de5dc745192f74916c", + "bytes": 17993920, + "build_manifest_sha256": "b7ae5e6aae8f4da83d914dd1cdfdae0cf34ac76bdfe546400470ebaf18319fe2", + "elapsed_seconds": 0.5411934440489858 + }, + { + "pr": 1030, + "sha": "96174bbdd64ab2325224f47bab43888fa224595b", + "tree": "7e14c5b2dc2a87bbdef99cf0f332a2a1683f1a9c", + "binary_sha256": "c594249b32181aa2708081a51e3fd1d80876f87a1a1c14de5dc745192f74916c", + "bytes": 17993920, + "build_manifest_sha256": "5db2eb61126c0b47756a0b3cc1021a29a865604dfed131511acc9010574f4943", + "elapsed_seconds": 0.5303470180369914 + }, + { + "pr": 1031, + "sha": "bfae14510a3e302f524b96719a695ca4bb07ffbd", + "tree": "af54e0265fcf695c3228b9fd03ad8d6a4c2f2205", + "binary_sha256": "c594249b32181aa2708081a51e3fd1d80876f87a1a1c14de5dc745192f74916c", + "bytes": 17993920, + "build_manifest_sha256": "3df309378fbb3b753cbda054c405a3b73f62f580b2965e42899beccd253c50af", + "elapsed_seconds": 0.56243567308411 + }, + { + "pr": 1032, + "sha": "3803544ef4a24e0a72e54a317ee5091638bc70ae", + "tree": "c678a8f9d5f9c2bd63f3bf2cb0063f9b5b9667f2", + "binary_sha256": "e993e32ff19aba045d4cc34c89b60d5525538e3eed56a21f44583b902e2d4b08", + "bytes": 17999936, + "build_manifest_sha256": "e5b5b901d344cb2e08e46409c54925fe3f25633517ba2937a78236b6de6ca4ec", + "elapsed_seconds": 5.533379688975401 + }, + { + "pr": 1033, + "sha": "a721b98a306dd9021d31bbc485ae4c7c82ceba00", + "tree": "37a1058547dd87ee790790c77add1956b658c8e5", + "binary_sha256": "e993e32ff19aba045d4cc34c89b60d5525538e3eed56a21f44583b902e2d4b08", + "bytes": 17999936, + "build_manifest_sha256": "3eddb404dc68ba2716a028b70eb638bcc9a1a2b114e914f04a900f93a6d2a5c2", + "elapsed_seconds": 3.488350010011345 + }, + { + "pr": 1034, + "sha": "974d137026818bba1c1deaf6cfc4fffe676b314e", + "tree": "cf0755b74daea7bfdec70a96f260f327c37af885", + "binary_sha256": "72bb65654ff68ef82f2af5526eddc66e2356dda8a1ced18776587bcbfea450ac", + "bytes": 17994032, + "build_manifest_sha256": "7c9a7aee3251bfc415fa218f3029010eaf6679c264f32d28db20a48aefa2a6ba", + "elapsed_seconds": 68.6122232839698 + }, + { + "pr": 1036, + "sha": "66302319f016c5f459b0260a2e727bd32073ed24", + "tree": "dc810d26cb1e36e113e9b56854f4ca95cf45c3ce", + "binary_sha256": "72bb65654ff68ef82f2af5526eddc66e2356dda8a1ced18776587bcbfea450ac", + "bytes": 17994032, + "build_manifest_sha256": "d1c6ba65c305f27a209837f8a838025bac7bbdaeb5b75c8e30d104b43003a2a6", + "elapsed_seconds": 0.5424148209858686 + }, + { + "pr": 1038, + "sha": "b68a9c3a58abd219a5043d5737e23f6ebe5ee26c", + "tree": "f681932162fcf64f4991341fd4bf7cf634dea218", + "binary_sha256": "72bb65654ff68ef82f2af5526eddc66e2356dda8a1ced18776587bcbfea450ac", + "bytes": 17994032, + "build_manifest_sha256": "336a0f8277cb195fe8641b3b5e32676fb394f5a7b695232463fd2a8272c6c9d5", + "elapsed_seconds": 0.5670382109237835 + }, + { + "pr": 1035, + "sha": "8ff28cde9c67bd498f9016935da01506ffb5845c", + "tree": "715ee9cb9b51df3fcbbe11a375ac1c7781dd49fa", + "binary_sha256": "72bb65654ff68ef82f2af5526eddc66e2356dda8a1ced18776587bcbfea450ac", + "bytes": 17994032, + "build_manifest_sha256": "98d4e512101cdf026af07ee6a6dd5dd3d03d4f3c1c8d060d1adf1f92b02fa670", + "elapsed_seconds": 0.7041487760143355 + }, + { + "pr": 1037, + "sha": "473f73452a6b47d7a3b522f2cc6128c4fafa86d8", + "tree": "6ec296c7c8786aa4006cefd6a965291e5db97b44", + "binary_sha256": "aea1c4b7d8f5480dfbd37ba01e9fab6071f73d4b768999a7d7e97a57152d0a0e", + "bytes": 17994456, + "build_manifest_sha256": "064a87023483103bc02e6c4e914ad22a39f2aac95e0f43476b19eee676e49fbe", + "elapsed_seconds": 11.155752036953345 + }, + { + "pr": 1039, + "sha": "7b72a5f0a52e838dfe0b199ea0386c8e6b3dcd39", + "tree": "68f10c304d6aedc71df92ccc469c1e202e9bb30b", + "binary_sha256": "5ad2508ca40ef3f190661110e4550a120e1b6e32520d57186050e092d4bc1119", + "bytes": 18007664, + "build_manifest_sha256": "a24bf2af15eb7f2f4fcf938b2e8dd62c1036434d34f3208a9ebfb7afcc40b803", + "elapsed_seconds": 5.7498900019563735 + }, + { + "pr": 1040, + "sha": "16e70cb97de93c7ab4ae8c9e990e1842d50cc528", + "tree": "42fb88ef117e2eaae6a8ea895b172fa39b51ecae", + "binary_sha256": "880d77f87179c4b26631c6a75f9678a2063e2b02aed79a9c5f66e3d54cd55118", + "bytes": 18007680, + "build_manifest_sha256": "cfda4127ee02255e6b6b80d4e62f4e5f85a4808330e32a1f2e899af395ca6a75", + "elapsed_seconds": 15.649529470014386 + }, + { + "pr": 1041, + "sha": "cf23601ab3533c2acb938acda1439dcd69091f61", + "tree": "28f1735cecbd92563d97215c03e568447edd7f47", + "binary_sha256": "817df8c863e331f6e6e94bf8545f0548d5a00d6a8dca3a3e98e2b97145a3a35c", + "bytes": 18008064, + "build_manifest_sha256": "81e7e5c31062c5160806d092d8e2faebbcc8b78adf695486199f237f7584f5dc", + "elapsed_seconds": 17.126204880070873 + }, + { + "pr": 1042, + "sha": "2b21790502fd6bf9b6e1afb53cc1444cf140f296", + "tree": "203c55ed0fa72c1b90a023e45c1f7f73714b2194", + "binary_sha256": "cddce69097f55e6f18f4086a9d0905f6e72b73c774e51e89d9bbaafa3eb9057b", + "bytes": 18021664, + "build_manifest_sha256": "4cc1eaab866c3001b92c260e9c8dd40c5add2914cbc5d10675983eac92e9121b", + "elapsed_seconds": 10.269586473936215 + }, + { + "pr": 1043, + "sha": "9e4338a6ea3b47431e612a1fa24b818b3269193d", + "tree": "3fdc698f88d9cd86a18f571240ba1d95deb48798", + "binary_sha256": "573dfb96a507651088d7e127b43fe836a6aa8d4ffe222bb4761ffaee52b48443", + "bytes": 18030080, + "build_manifest_sha256": "c39e412b8a5893a726958e064edf388fecbb7e5be788f9728c1eef864880a6d4", + "elapsed_seconds": 20.327275358955376 + }, + { + "pr": 1044, + "sha": "d546fcb3d864ed18776f642c1aa0fe904e9f8bfa", + "tree": "b1d2b95065e3480026687d3e625d36937382722f", + "binary_sha256": "9ba587a75ce9ed5df3b9f50d896812e552304649e11318fca02c0585840bb091", + "bytes": 18010352, + "build_manifest_sha256": "a74076df2b948baf56ebe15a1d41427c2c1391990c035bf02ad5debc342fa39c", + "elapsed_seconds": 8.525545189040713 + }, + { + "pr": 1045, + "sha": "35479b4fe8dec5a7a9400bca69f69516df5f56f0", + "tree": "012189800cc12490352e17898cb4a00e1ef52a2b", + "binary_sha256": "9ba587a75ce9ed5df3b9f50d896812e552304649e11318fca02c0585840bb091", + "bytes": 18010352, + "build_manifest_sha256": "3e8ae6d81382f98f379f974b1eee72934fe2552204fd8975b00193216b33172d", + "elapsed_seconds": 1.4121523729991168 + }, + { + "pr": 1046, + "sha": "7c0f507f7c815146a9b746e40269377dbc768b37", + "tree": "a4849e989e52f62de9fdababdebfd234890560bf", + "binary_sha256": "8a54a896cabb96d22d1f71337b6306ae91e751d626edf9737dd40ec236b0d2d5", + "bytes": 18010216, + "build_manifest_sha256": "755eeed74b0629fe6760f784edc5684cdb4af5fefc7c7a68254c0f65cf483fdd", + "elapsed_seconds": 7.990364472963847 + }, + { + "pr": 1047, + "sha": "c14d39cf281c084f8833bc877fca6999e2f9f810", + "tree": "886fbeee2a5dda370bdc9f3fe0ea258734af0e7d", + "binary_sha256": "088e5123ec23e4cf1534285f250e640eb34af3da1f62d86d434e1d949e1b2662", + "bytes": 18023808, + "build_manifest_sha256": "52afc491c64f78d4cc64e80f11e9d3abe4d553475230fbc4cdc1f169e03338be", + "elapsed_seconds": 38.43270433798898 + }, + { + "pr": 1048, + "sha": "7cf2a52441d626888b5840d09a4646d6dedca6b9", + "tree": "b381293e0070ed080653db6cc0845a5b990902c7", + "binary_sha256": "d324b15425ba0de73e08e1573ab43cf1005e22c51f7582df848e9235241cf292", + "bytes": 18009688, + "build_manifest_sha256": "b79238f4de2c21f43f394fad45c1c63485c1d3ab8c72e12c371c1d26327d9123", + "elapsed_seconds": 9.378784344065934 + }, + { + "pr": 1049, + "sha": "901c8fea916124f4d0e195c5385f2a977b44093d", + "tree": "67650cbee83feb346f32287a257c57eac4f63a01", + "binary_sha256": "dc0a69c21f79b5b5fa2f4bf2bd271bcc96f8559398a00bc2802f4c12661247d5", + "bytes": 18009056, + "build_manifest_sha256": "e43a147649b273fd1f0d6e780fbb5877ee1b54c677cd5ce26e2f86b0ad2a850b", + "elapsed_seconds": 13.595240822061896 + }, + { + "pr": 1050, + "sha": "2d615ea1e447e55c266a47799ad6cd64bd4e246d", + "tree": "86e30a4579b6af6c4c7669f7c8123af02d860399", + "binary_sha256": "93a5b3e92f7da7abd981867f2c42a6946b821be1138048466429775be2eb9c50", + "bytes": 18006744, + "build_manifest_sha256": "0c95422cf7c1d3356fe327c09034f56b38488f4905ea1fefe4bf22ca9eeb6900", + "elapsed_seconds": 15.034358096076176 + }, + { + "pr": 1051, + "sha": "d903ea98a98f4220d9372ab0404ee974eccb8690", + "tree": "321291bd065687458abeef7489dc164c0c47ef64", + "binary_sha256": "c79849b306fd1a6f83082e0436a5e66935221de9b0c5551a1bdd7a879f142d82", + "bytes": 18007024, + "build_manifest_sha256": "60ae9d102db973c82383e32b668a69747c17dcc5841de8a6cca416d1857f11ed", + "elapsed_seconds": 15.807729575084522 + }, + { + "pr": 1052, + "sha": "76cc22da343841f9786bc9f78e21e839084a780f", + "tree": "a8aea9ac22a2eec2eb46be737b24d6902d7cf805", + "binary_sha256": "c79849b306fd1a6f83082e0436a5e66935221de9b0c5551a1bdd7a879f142d82", + "bytes": 18007024, + "build_manifest_sha256": "5dc971338040936af662cfc4f64a7b65588c2bb4ce32600386c25f3dbaa93d68", + "elapsed_seconds": 1.3444180419901386 + }, + { + "pr": 1053, + "sha": "dc4e70237eff58916c4eb6990047904536397264", + "tree": "53aa9019b08dded62e1a4f46f556696c60367d32", + "binary_sha256": "76c114987266734b6373a2c95619b261dbc94c10136614f32668c7951a89afda", + "bytes": 18048744, + "build_manifest_sha256": "8737473b961432dbc964be1e0a1a700274192ff23a28af069c1f0b39f7ddec11", + "elapsed_seconds": 19.46090214990545 + }, + { + "pr": 1054, + "sha": "96fa46b86017dc2a79bc97624af9ac98401190ed", + "tree": "377278cb4c6a8c9f2ce2948870b56b4f6bad46df", + "binary_sha256": "e4900bd5e3c9a536c34f0e8ed8b266247fc8d6a5ce6160b30f0f34a3c98d10b3", + "bytes": 18051832, + "build_manifest_sha256": "e93e2ad3d05d503e9438aac04bfa5f1d72bd3229340b4ede22b92d4b4d6b1820", + "elapsed_seconds": 8.383137225988321 + }, + { + "pr": 1055, + "sha": "00d4f84df01e00f1ce2d7c83576ac38b2eb2fb7b", + "tree": "274966cbc41ffe71e5319c4240e89eff2676200c", + "binary_sha256": "6959b59ae033ba63bec93ac5888b1259c18a19079f4fa13f3124d054e0a22b30", + "bytes": 18074704, + "build_manifest_sha256": "d45237c506ca15d905e2ced08cad70960906adffabdfb2e662d4c3acece1df63", + "elapsed_seconds": 12.780953445006162 + }, + { + "pr": 1056, + "sha": "fc2cd316e81d7319aa44912e786e7aad4492cd0a", + "tree": "97a154cbb22375e90f20ff9a1ffee3d6d9445b27", + "binary_sha256": "864541384da6387a3739dbb68d3e2c6f4991577bd9121cc0a1e6b5cfb610095d", + "bytes": 18101888, + "build_manifest_sha256": "008c91153f66901cba3ad6a8057078ee7b8cb2d25f78e07d928306c002bb5308", + "elapsed_seconds": 6.9507035471033305 + }, + { + "pr": 1057, + "sha": "6bebe940ba36328a399461a19434bf627118bf75", + "tree": "8a40c3ee2d33b5a0dd8d21a8a3a574b8f8d8873a", + "binary_sha256": "09b5ef5656be28c6713ee4279b8727e1a69592c4b60a00c32729dae9a2a8ff5a", + "bytes": 18108104, + "build_manifest_sha256": "89b507110977aed0a1130d768178edf20f04aac81330e356a58c1f7aa3cbde11", + "elapsed_seconds": 10.420100728981197 + }, + { + "pr": 1058, + "sha": "c004bcc65f16df2a264fd5451e4bc7262fecd137", + "tree": "9b06c5f902ce99a874790636ae5563b673e5aa9f", + "binary_sha256": "09b5ef5656be28c6713ee4279b8727e1a69592c4b60a00c32729dae9a2a8ff5a", + "bytes": 18108104, + "build_manifest_sha256": "481934bd044c183e3d43cdea0c685ca6d92697b5f60fabb34b6f546e1264d7c7", + "elapsed_seconds": 0.5378182909917086 + }, + { + "pr": 1065, + "sha": "4b823112efb377658029a2a3d5c4c51594f03e25", + "tree": "449081960d5c525809cc9c09013a90247d0be304", + "binary_sha256": "0bca5ab00ae76832cc19a46f96081f3643bf9e0b273f1803c7b634de5d3301d1", + "bytes": 18133944, + "build_manifest_sha256": "e7aaf4253af38efc97354cc344e6f82590f4b47f819ded808df2a6057654b100", + "elapsed_seconds": 13.693071934976615 + }, + { + "pr": 1059, + "sha": "22702c34a0bcb261238af40f82818369fa46a4ab", + "tree": "51afbca10bd688df36a749077b545ea838f5f1f9", + "binary_sha256": "9a275ed5de577776d17bd899871d187096bd9755ce016a8b8cdfb92be2b94f9a", + "bytes": 18143840, + "build_manifest_sha256": "0c53656f76b32a9af9dccc7fc26fbe015373c94b60eadb9ac66d03278f72ef4e", + "elapsed_seconds": 7.3917549210600555 + }, + { + "pr": 1066, + "sha": "09e6bbfff3275ed36eba7b98052cf5d0877d94f7", + "tree": "d48ae72e7db0a536c723fae872f43ba6954b3cbd", + "binary_sha256": "c21c424a876f82db3ac4de2458c8f47b5161dd49271c1b739f2d1ac6ee0f689b", + "bytes": 18147504, + "build_manifest_sha256": "8b7989ed8faeb6502fa87d193aac84f602bc2a3c5a9a70bd9e71e6345b932414", + "elapsed_seconds": 2.699885717011057 + }, + { + "pr": 1067, + "sha": "fb726c946063d567320d76f2f3d706f0a0997e57", + "tree": "21d04649207d9a1c39c246110764377d06e40b2b", + "binary_sha256": "d865890df4bca87787098ee4f713046122dddb91687d4057eeb3943896b9ba00", + "bytes": 18146176, + "build_manifest_sha256": "4de16834f867b6fb9e49cc1b200d6d3a29fe6f1023bcd8b452798778bf36cdaf", + "elapsed_seconds": 13.449358890997246 + }, + { + "pr": 1068, + "sha": "58ba30eeb90499f50e98da480b8d965047352b1f", + "tree": "5b16cf4b70072e84a76e3a25db35c1badb69ad7f", + "binary_sha256": "59bc370e0204b140ae350340478b23d468cf01801368fc12995afe7d4ab5a294", + "bytes": 18148600, + "build_manifest_sha256": "43dcb049deb159ee276f050ed49b560979965d39d61415ec33483aae897b7c60", + "elapsed_seconds": 2.8365641069831327 + }, + { + "pr": 1069, + "sha": "6d6a2c9abf972ffffd064939381a1df2f40c2776", + "tree": "30a4efaaf6deeaebfde08d81204dfa7584a9e58a", + "binary_sha256": "25a7faf2cf280317b69710082ce7e4c136915f4569358338adf766da98e07bd9", + "bytes": 18159248, + "build_manifest_sha256": "bfe3eda2917bf39c3a84f519231da5a856b05f11c1129da2f1b087091d730a2b", + "elapsed_seconds": 2.8984912980813533 + }, + { + "pr": 1070, + "sha": "44e7e30102eb6c6ae122135189b6c62340c35bdb", + "tree": "08bcccc80d79b6f446256dd1baeb7a2e57158031", + "binary_sha256": "3a35204ebdb657a1ec5682614544f02a594fd0ecd95d92cbf59c88f5b5b81de8", + "bytes": 18155792, + "build_manifest_sha256": "6a9a91506f8058f10eb2c2bf5810548eff8bec64144c30bc34590bfea68ec742", + "elapsed_seconds": 13.00192386098206 + }, + { + "pr": 1071, + "sha": "79f8b371480551c70654e1e83712ebdb6539ca0a", + "tree": "a98abf82377afbd5b19186dc3f0124f0dac2f244", + "binary_sha256": "28d542f2fdd9fab3f0eac7fb8711f52fca8420ab5b92bf5a56481e0fdb821c01", + "bytes": 18162504, + "build_manifest_sha256": "cd6d683b78025ac153eb16472b2e065a2232245b9a17bb22a512c30acf728919", + "elapsed_seconds": 21.61491110199131 + }, + { + "pr": 1072, + "sha": "0fe856d76f6583c3a0023cf6f8f5654bf949bd40", + "tree": "5b0ad27942bad9f997abcf2fbfc2b81a37d1e1b5", + "binary_sha256": "359aa45d3671678d2dbdf721bb85a7ad4636439185b31da4a76106fd556d1e73", + "bytes": 18166976, + "build_manifest_sha256": "dcae803b3a6776e9afde500b6246430167711dabdf415227c3cb5140c0d0dc91", + "elapsed_seconds": 11.150577696040273 + }, + { + "pr": 1073, + "sha": "6db2de9e49f19107f49e257486b50694a764cf23", + "tree": "80a275db32e569e22e25753e890d11b0a1870d93", + "binary_sha256": "45b7e4b3fc457faaf59f6ff08a7d64ed7361e304ca2ae129b9143ab4081ffbb7", + "bytes": 18165496, + "build_manifest_sha256": "474c3f8a8e7e736379a2ca07c8fe2489a6aeb5627c51660710850f4872ad2fdc", + "elapsed_seconds": 11.49217546696309 + }, + { + "pr": 1074, + "sha": "7173ffcbc66063560d31e04fdd58fa4a1c6ebe8c", + "tree": "a53827903ac4ce358849affb6535e039fc704368", + "binary_sha256": "45b7e4b3fc457faaf59f6ff08a7d64ed7361e304ca2ae129b9143ab4081ffbb7", + "bytes": 18165496, + "build_manifest_sha256": "419bd7f6b0408c14e083adcb99a4533635bbfba896140826ecd11866e7a4793c", + "elapsed_seconds": 0.5873665800318122 + }, + { + "pr": 1075, + "sha": "62400cd3b12ec42c2b1aa7dec049c2510cbf456a", + "tree": "1f1d5419370d5e1700a63802523f46439c4b8001", + "binary_sha256": "b2aea9a648da6563748aaa9983276358afa680b6f38eef4a75e48bd64d7a5829", + "bytes": 18220984, + "build_manifest_sha256": "d4c47974a0c7261d23cd6283f5a9f390e95912687ead379e4e3c8915bcc7573e", + "elapsed_seconds": 14.046104717999697 + }, + { + "pr": 1076, + "sha": "653f5ed25b68e84e0b292afa9671289eade3b534", + "tree": "9c66b5e05a9c091dfe78c0d3b58ba01f0696fea2", + "binary_sha256": "c9bfb9fdcf30b1b41402032c785e243d3a602c229893b573ecc7d873dabce994", + "bytes": 18220928, + "build_manifest_sha256": "9706f6f2e5a979cc4c5d9eacdf548eb5dab28ce37cdbcf64a9e5f9e88b47bcb2", + "elapsed_seconds": 3.2822915519354865 + }, + { + "pr": 1077, + "sha": "35b810bb806aa169c075c01a449a408cd3758248", + "tree": "a6146c044af7cd1b39c7be5e31f84becd0f3a406", + "binary_sha256": "4996cc3367d09beeb73b1b8f048edf008dd44bdebbf6d6a0e9ba205dd53675d0", + "bytes": 18227152, + "build_manifest_sha256": "5f052d9c0c6c3aca1762b227ad7a02f772de140306ca3ce254e3dfc28e740572", + "elapsed_seconds": 3.243145783082582 + }, + { + "pr": 1078, + "sha": "76054b3a9c60baa72afd0452bbc3ac6bc2f79efd", + "tree": "0c9538167ba1badb64a5b59f708def754a3e3571", + "binary_sha256": "4996cc3367d09beeb73b1b8f048edf008dd44bdebbf6d6a0e9ba205dd53675d0", + "bytes": 18227152, + "build_manifest_sha256": "861bd7165727ea49dc11c0235885e2379b038bece177ba5febfcf2cf2524009c", + "elapsed_seconds": 0.59876661200542 + }, + { + "pr": 1079, + "sha": "01ace14aa38a87db7d2f1441043cd61cf0b3de49", + "tree": "9aad351fa68ff0bc4bd3d9b7929a28c64bdc477b", + "binary_sha256": "21a1d76b433bcb044ed68bdec87cff6bc6f5c6ed62a0b314af29eedffbcaf9b2", + "bytes": 18270232, + "build_manifest_sha256": "94df102f24904ca41e2b846bd27ff4539ae1970b69ef5f8f54559621e4d19e1c", + "elapsed_seconds": 12.942402977030724 + }, + { + "pr": 1081, + "sha": "0d64bb3974f4e70bc5dfc36ea8647e7e7db3cbf5", + "tree": "21538b2036e45f70f4ee19eb830b1795f1563db7", + "binary_sha256": "21a1d76b433bcb044ed68bdec87cff6bc6f5c6ed62a0b314af29eedffbcaf9b2", + "bytes": 18270232, + "build_manifest_sha256": "bbc552883d3d2c1cbc2d82fa628a247f179343e76523c942e1ea69e87eaf6d2e", + "elapsed_seconds": 0.7398356680059806 + }, + { + "pr": 1080, + "sha": "669f68a3e26303c06325c6beaee44019481bcaf9", + "tree": "3c7877e2726cf4a92a2ba7b1313a352c478b492b", + "binary_sha256": "2adb143197de9c962db58eebddb13ea7fccbd4b4f351d93c458f24fb19a05f0e", + "bytes": 18266440, + "build_manifest_sha256": "81def9ade126c6eefaadb7b1a46b4d586342a96160a20d8617188a23bff4f02a", + "elapsed_seconds": 7.668271848931909 + }, + { + "pr": 1082, + "sha": "6e6b25ffc8696d6d28867a1ee6ea2e9beb00a77d", + "tree": "7a6a2a483889a0d425f958058a4bea442867c646", + "binary_sha256": "7334900ac8c0b146a7a83085cd59dde8ca43d90c00d885ef5f05c8dbf18cc335", + "bytes": 18269920, + "build_manifest_sha256": "f74aeea6ebf27bffe78bd941ee6f4a3c3764d65b8ec330ea13592b4f7779c8c0", + "elapsed_seconds": 11.152501000091434 + }, + { + "pr": 1083, + "sha": "f9a73afa1497589b49f33c99c49248adf3a7b38e", + "tree": "638ab13f27de3cf6865c7299e0be2be303007402", + "binary_sha256": "55dcb5583dc8495c9c0cc6313b91633cfc39fb482fe958cced09fbf67cc2ae97", + "bytes": 18270952, + "build_manifest_sha256": "5c032399213404110dd883e337a3413f0dbffd31592bbb584ee18ae85ba9f056", + "elapsed_seconds": 3.0343299090163782 + }, + { + "pr": 1084, + "sha": "f06cea15f5b1b0b04be246501c894b79782eb0fd", + "tree": "09d97ff49a70b6749935f03db44c90a86c798339", + "binary_sha256": "b9e8a1324fd5b103a16b29db14b3ee7694ee5ca59bb77e24d468737daa8f8c0d", + "bytes": 18272872, + "build_manifest_sha256": "249f1d37279d4ccc9fcb8da2288f104c50bb9938586aa538f276e3a7c39001dc", + "elapsed_seconds": 28.99749979097396 + }, + { + "pr": 1085, + "sha": "790dd72d400f7ac3e8656ea48c7ba718b41badd2", + "tree": "bb6b3ad4ee5324e647adc13bb4f92573bb4b7ad4", + "binary_sha256": "463cc571bb34f28ba628a72f7adb72249e48cd97e0c85494bf28e536b38fdaf7", + "bytes": 18273560, + "build_manifest_sha256": "9824f260517cf157be7fc38ef16daf5ff17d1e2960597d003bd51ce51f7c70bf", + "elapsed_seconds": 10.145889680017717 + }, + { + "pr": 1086, + "sha": "ba9b2baaf8d7ed7a7ffdeac7a16bd63f43255071", + "tree": "05f2ef2df47d5062d39f257d541d5663a0fc33b5", + "binary_sha256": "c573b611d41d1e73bf0726798d90d2902a9b460b73c9c82f34709bd31a3a9074", + "bytes": 18276792, + "build_manifest_sha256": "ec92b520d3c11d2f512b5a4d422073ff211c045562b55bdd34a6006a1d5e8933", + "elapsed_seconds": 9.965236848918721 + }, + { + "pr": 1087, + "sha": "f7bdc5d248e76a54278aef5030c0a3468505bd2f", + "tree": "9bbcdac4026dbb5e13e70fa942650c8c715a81dd", + "binary_sha256": "9b365baca898a0ea1939d3f57ef13dd4318ce7451e367439ebd31da8253bb2d9", + "bytes": 18269792, + "build_manifest_sha256": "2722e9678ed89b79fbdfb5fe337b205f0873f602d3479838dd3ca0ac6df3f396", + "elapsed_seconds": 10.308180430089124 + }, + { + "pr": 1088, + "sha": "9bd70fc9b4607cd8a586615c630706f85416e62c", + "tree": "e35d6b499427c1183749171d17f91f36e9612bd2", + "binary_sha256": "8617cc1e3d88fb79351528c08539c3695877313da833148210142efe7100bdc6", + "bytes": 18322944, + "build_manifest_sha256": "96187eb27d6683a07b7eb0c6726fa5628075500d8d820119acd6d3d6b2f60790", + "elapsed_seconds": 11.333163599018008 + }, + { + "pr": 1089, + "sha": "bec36225c686b58914e8ab9792e822d56fe1ef07", + "tree": "980272b2bd286608ecd915e25903cfbb1a489f36", + "binary_sha256": "be23c1ba04f25e638ca47248f96c496ff66a5755873775a37c841f9253adb39a", + "bytes": 18318168, + "build_manifest_sha256": "e9c02514a718f2c640a43c62d9829fb6043d406a2a0e4e693b0541a9c23d1208", + "elapsed_seconds": 9.878176280995831 + }, + { + "pr": 1090, + "sha": "798c2c0a3b4f9c1acfa050f2eac1b8902ba89ae8", + "tree": "b2d91193364e7e28e97cc2987d2ffa6abaa4e76b", + "binary_sha256": "7a5ecad4dc6c7b556bfe5714816ab2951e7d54b4ec0cf7dc184af919f1270482", + "bytes": 18357984, + "build_manifest_sha256": "699a490192006c29df261db93d5ae26b3e4d64f33ac4e6060d87f0bdcc144a56", + "elapsed_seconds": 21.027587598073296 + }, + { + "pr": 1091, + "sha": "e66bdbe1097f4a051580dcbb68d17e745ec5e9ba", + "tree": "b0cb708273a7a80b36599f8de6caa01a6f209146", + "binary_sha256": "cd3e3a978cb76b9710061726e85257ad70a83ea614b70f8e7c41961f9dcecded", + "bytes": 18359008, + "build_manifest_sha256": "82f64f5c82cea971fcc613a02416ddfda6b8dd0f91ccc2cd2733dfb138443a66", + "elapsed_seconds": 21.734148474992253 + }, + { + "pr": 1092, + "sha": "a89459ed819af4fa6841a9ab7eca4e554949fd72", + "tree": "2705ce1ea2d779f292cd6f8c5f6706d1e5d809ec", + "binary_sha256": "5cbcac47a68ede4ebd8a08e416d7438390d85686b2148c7bc340cd2606fac466", + "bytes": 18370664, + "build_manifest_sha256": "2bd389d29b8c26961b2e85f052238e905d49ddf2b6f0fee6633d34f97b6bfa28", + "elapsed_seconds": 9.307812692015432 + }, + { + "pr": 1093, + "sha": "a7a6125a9358f1020fc914d6c91bbf8c6e66392f", + "tree": "f4da502d59284999ce58ca50a22bd015858fb371", + "binary_sha256": "5cbcac47a68ede4ebd8a08e416d7438390d85686b2148c7bc340cd2606fac466", + "bytes": 18370664, + "build_manifest_sha256": "4790a9fbebdc68148207018849bdc8a6c3dea62767c1ee3932649792a8f96d9b", + "elapsed_seconds": 0.5221935050794855 + }, + { + "pr": 1094, + "sha": "bb0185a0379075480eb8b1499f5bc5ff8cfafaa8", + "tree": "9080f091d6029b6afc54bd7d455108dddd98eee0", + "binary_sha256": "a0ee28a35b0fe2cc3a9fc0f8a476cc9629dc63557dfb14a5f98beae405d58a95", + "bytes": 18398856, + "build_manifest_sha256": "2868a55d4cf09515eacee2c14f3c8dfcc79eab921ccd177e2b5fe49954e35b6a", + "elapsed_seconds": 10.294123527011834 + }, + { + "pr": 1095, + "sha": "6792b5030de70a737dec2878673aebaa6ddc57af", + "tree": "826b394d04a0c709e5a67c46ef1f48bcf3c8bbd4", + "binary_sha256": "e5e8828e1e7211fbec191238e8dca34929c19c4060d20643ed60c939cb3d52bd", + "bytes": 18401176, + "build_manifest_sha256": "4f8b4a43efa2bf040a7acf5cf58ee6acbd00347ffd3b320a73f549b2f2612c12", + "elapsed_seconds": 5.489695476018824 + }, + { + "pr": 1096, + "sha": "39282994e036bb4dc43c2ca9ffdb2a2f498bb99d", + "tree": "400bdf2b0ac576947d8f5407615485d7a7c675c7", + "binary_sha256": "6d6a630237d8f7112838417b243f037cab992795c7ccc452ed38b9e102446e32", + "bytes": 18401048, + "build_manifest_sha256": "bfbaad5cc2c50eed8ded7530f01605f604beb2feeb20422262588bb15c8d7495", + "elapsed_seconds": 4.786088038003072 + }, + { + "pr": 1097, + "sha": "910e2a7bbae50a3562135784d56e2ba903e89e7c", + "tree": "1be2f889ab19f8f78fd8124c0744c78741c7936d", + "binary_sha256": "6d6a630237d8f7112838417b243f037cab992795c7ccc452ed38b9e102446e32", + "bytes": 18401048, + "build_manifest_sha256": "3068a9377292e0b19a4ebc5dc418366b4f0e20cb40f81c7f0b91f952f23c2f4b", + "elapsed_seconds": 0.4534852768993005 + }, + { + "pr": 1098, + "sha": "7c8cd64e02a84ce13f5a7d3b3dd37290307a40a9", + "tree": "1a4c9b6198d7d78e24c3578708421e31effa364e", + "binary_sha256": "ae9519a93d7479940339272dc57ce7491321fd41b8c6a9b5600bf34c3388df5f", + "bytes": 18404960, + "build_manifest_sha256": "e622ba75e2fc5e43a29b7ad20e709ff9d7365d9ab179a109be21e3a7eff8e47a", + "elapsed_seconds": 7.221381574985571 + }, + { + "pr": 1099, + "sha": "76185cb37fa2d4f6cb36876efde58b0ede0e753a", + "tree": "dc0498119edca8ea33c29f4ffea88bbe76cd18f5", + "binary_sha256": "ae9519a93d7479940339272dc57ce7491321fd41b8c6a9b5600bf34c3388df5f", + "bytes": 18404960, + "build_manifest_sha256": "9d8897519a83df75e53cc3849390825146bb059d31b5f56c6ac260dbdb893c66", + "elapsed_seconds": 0.5722937639802694 + }, + { + "pr": 1100, + "sha": "57e9287e675f180ef6a7b0cc5d4e883605b1bfdf", + "tree": "22fce681966d777fcc583edd6256bfd6e93be6a3", + "binary_sha256": "ad9fa9caf403c653c4101add1657b01bafc6d752949eb8c96245f7901376db54", + "bytes": 18431008, + "build_manifest_sha256": "23e9a06e9b99ca4d9e9582a95c9b3298b6783c335cac5d19de47442a39cf2e78", + "elapsed_seconds": 29.027532430016436 + }, + { + "pr": 1101, + "sha": "318edb2f60ce1a9a526fc94a15ea7cdad4c4d181", + "tree": "9fee73c833122f2635772d426c90bda4b0ebee32", + "binary_sha256": "f09cec12b0fe68fe2840295a050208557ce13955e8b9f6543331a07731867f33", + "bytes": 18430320, + "build_manifest_sha256": "522439242bdb33d5f1f0856596c8316819d2a09defd0f3f359a5759e5d30bd7a", + "elapsed_seconds": 25.26812796201557 + }, + { + "pr": 1102, + "sha": "55ea67e3f06e5055b43d8cb780661901731592f2", + "tree": "412786b2ddbfd24b3138891ae823f25748d03d76", + "binary_sha256": "f3601f70bafd458aa495ff187c2b9428694eb53085d1ae94348ba5b0ee7d455f", + "bytes": 18429056, + "build_manifest_sha256": "671f4a4c0fe749b7ef2df2224bbe1fe53cc403836fb7abb014db247b671e5e48", + "elapsed_seconds": 14.137501891935244 + }, + { + "pr": 1103, + "sha": "f3ec0faf7a1bb16ddb0b3b8bcee2c3e5bd970df2", + "tree": "8498213520d3cb2480484e33259b2eee3e075369", + "binary_sha256": "f3601f70bafd458aa495ff187c2b9428694eb53085d1ae94348ba5b0ee7d455f", + "bytes": 18429056, + "build_manifest_sha256": "932ef029851c333929566daae63cda2760acdd48641c7b925105c475df0a1f57", + "elapsed_seconds": 0.583538148086518 + }, + { + "pr": 1104, + "sha": "455dcd8eb5dd98b09f3117f5316136b6d43cfd8e", + "tree": "e0ede615f8ea55c7ed6177a34a1044d4413c3391", + "binary_sha256": "e913d4096deb6a52921716f847b5048c21ac1f9a13cb0fa0a2fbfc3d8ab8dbf1", + "bytes": 18429168, + "build_manifest_sha256": "24e303593556018b4f5d70c2e301fd73fd656063caf398936b2ff6fda1976ffb", + "elapsed_seconds": 3.9156571510247886 + }, + { + "pr": 1105, + "sha": "245e74ff6cbe6c0f84a074be669c60ac7cbc5e8f", + "tree": "2e172367b2730eae8c71ae99d357f21ed390c578", + "binary_sha256": "731d04a57027197083508232323dcc80dc8f106948335a30fc8b190edb495e69", + "bytes": 18430944, + "build_manifest_sha256": "136077d0e141c233e51cd7f6cabd53dd71e06e2074b01e36267e22c3f59cd61a", + "elapsed_seconds": 7.714408111991361 + }, + { + "pr": 1117, + "sha": "b60cf7a5a92609f9fadddd4759d3c55e755a69b6", + "tree": "14fe3d589243ffb7405d3c0fc7efff1db2d73890", + "binary_sha256": "731d04a57027197083508232323dcc80dc8f106948335a30fc8b190edb495e69", + "bytes": 18430944, + "build_manifest_sha256": "5757ca29d9ddc5f9d3db48df51f84f25493d9b1937ca784751a7a5d0e46b4975", + "elapsed_seconds": 1.3547864980064332 + }, + { + "pr": 1106, + "sha": "e7e42d01e0678590fc06bd90b9143682a84aef7d", + "tree": "9e90c6675a556ece1a98d4c983c9b3a24fb12b21", + "binary_sha256": "731d04a57027197083508232323dcc80dc8f106948335a30fc8b190edb495e69", + "bytes": 18430944, + "build_manifest_sha256": "235a9669c198f97f5aa97333855f0146cdb40a2838a05c3fc145be4d9f9688a5", + "elapsed_seconds": 1.3107601060764864 + }, + { + "pr": 1107, + "sha": "ccb1f0a202ed59b30246c14e424a400e47acc447", + "tree": "4ee726582ba06ca39e33a1307d6242f1a99680a8", + "binary_sha256": "3191e15d43978dbf7602e3e350592fae8d72539e620baf069ad5daa3052f5512", + "bytes": 18431464, + "build_manifest_sha256": "d7b04083a5303a566608cba562d2474f1a602727f8e3d0f58e31207844a4a961", + "elapsed_seconds": 4.062736371997744 + }, + { + "pr": 1108, + "sha": "adae6c9cd98bdd4b15f7b2867d08b1bfe12e1fad", + "tree": "3825f364cfe423e6612d859f23a0a928bb59a843", + "binary_sha256": "735cd1d468c2fdedcb2ad66d206aafa76b5ea1acc05ac2850a455f54362dfe37", + "bytes": 18435008, + "build_manifest_sha256": "a4efc9b13e3b94b14b0a36b74f54ff95a4f8a00e1ab8afbff78b1080799ef484", + "elapsed_seconds": 8.316323721082881 + }, + { + "pr": 1109, + "sha": "a1ff80a81c1ff2c4fd93898aeaf07dc2fc5764ff", + "tree": "a6d0ede96193f3807d07c8c301cf48007daf2b1b", + "binary_sha256": "735cd1d468c2fdedcb2ad66d206aafa76b5ea1acc05ac2850a455f54362dfe37", + "bytes": 18435008, + "build_manifest_sha256": "cebd9d16fc0732155a688b3437cc96df383403928ea9c23609ce825c9e5d7998", + "elapsed_seconds": 3.6257614200003445 + }, + { + "pr": 1110, + "sha": "e9bebfa5bfd85137de756047795887d45248ec18", + "tree": "30f9b479d62fca27aa43268f86ede8ac074e9317", + "binary_sha256": "735cd1d468c2fdedcb2ad66d206aafa76b5ea1acc05ac2850a455f54362dfe37", + "bytes": 18435008, + "build_manifest_sha256": "ba5d25828a8e21fb9a29608137f57cdc0ec5b61d81c61fc2c183f33272498732", + "elapsed_seconds": 1.1849576289532706 + }, + { + "pr": 1111, + "sha": "5cade08b6701417b07343b12ac86331ed0c3b941", + "tree": "0730bfa094800b4ee8c660f177a947dc70e27ca6", + "binary_sha256": "735cd1d468c2fdedcb2ad66d206aafa76b5ea1acc05ac2850a455f54362dfe37", + "bytes": 18435008, + "build_manifest_sha256": "d7a4a10e04d7d9ae9cbe7c424c43901fb79b549f603de8e1c895e2c854e75002", + "elapsed_seconds": 1.1666911960346624 + }, + { + "pr": 1112, + "sha": "852539d084ca1c4bb1756b0f83eb4b50b2b19b85", + "tree": "39c37ea306fe0a715df186e7c913f33e9b9bec45", + "binary_sha256": "735cd1d468c2fdedcb2ad66d206aafa76b5ea1acc05ac2850a455f54362dfe37", + "bytes": 18435008, + "build_manifest_sha256": "18b03082518571a51aecd919934d21adc524b99a1c3625b75e3ef00d230db929", + "elapsed_seconds": 1.3060865430161357 + }, + { + "pr": 1113, + "sha": "5729026a8482a2bc331058ee658017f9aba74298", + "tree": "770f724c2288249321b02a59e5e8ba6916e2ba07", + "binary_sha256": "63403a74dca040a3d9a2485eb9888cb73e523929ff70b27d91b7591fd9ffa616", + "bytes": 18437376, + "build_manifest_sha256": "562e22d915e9180e541b93784576a7638eabd489851683f253f43cb009d9e41c", + "elapsed_seconds": 15.421961409971118 + }, + { + "pr": 1114, + "sha": "713abe5fa302c9ff78e7df769304f90379566c83", + "tree": "6d576d684c72aaa9980f7c837ff226bc1a64eaa9", + "binary_sha256": "63403a74dca040a3d9a2485eb9888cb73e523929ff70b27d91b7591fd9ffa616", + "bytes": 18437376, + "build_manifest_sha256": "7f1263f976023f0e4740d500efa1dc56991b13ac143887e69acf32514b46585c", + "elapsed_seconds": 0.5478180759819224 + }, + { + "pr": 1115, + "sha": "ab909839da7d1ae34ea63eab75ec83dc62fd33fb", + "tree": "b658839bb7578d24067f614682ef477b81278750", + "binary_sha256": "63403a74dca040a3d9a2485eb9888cb73e523929ff70b27d91b7591fd9ffa616", + "bytes": 18437376, + "build_manifest_sha256": "e05d97e79261e2e7e40b28480557a6516efc047470bad84f900450bbaf5df8dc", + "elapsed_seconds": 0.5984248570166528 + }, + { + "pr": 1116, + "sha": "f4cee33eeb6b6cf00c1b39003b11fafbb262f79b", + "tree": "683b31abb1e355df334aaab2b7c952885429b319", + "binary_sha256": "98a854db9dd1ba23ffdf19206ac4fbe513d07247a258d43bf00f69b958472c9b", + "bytes": 18437472, + "build_manifest_sha256": "feaf4cec506e02a4cfabd658b87f3bc5c7401b3d5c712675da0ac299740b030a", + "elapsed_seconds": 4.054585766978562 + }, + { + "pr": 1118, + "sha": "c7bb70cc6f3e6441ff25c999667d76f48ffe9acb", + "tree": "5eb723ea3b680fbf265c86f38704cb80faa6344c", + "binary_sha256": "c819fcc39a0f5546f014c74cbd82e9acc3f86ae5b5828096166d6d8c03ab95d8", + "bytes": 18433032, + "build_manifest_sha256": "caa706b8f27b60f35bc963720459ecc042ec5a1564d2600110f90309cce771ce", + "elapsed_seconds": 7.176634239964187 + }, + { + "pr": 1120, + "sha": "2487927cc6b1de326ea3c6c058dc493214354bec", + "tree": "60f195e5486e3dea1c6e19656ec7d860eca81fa6", + "binary_sha256": "15d7ad5ca6686d5cdf5442619624eb3850ce67ff0e5cea810610f5ff97b3a986", + "bytes": 18433920, + "build_manifest_sha256": "497deabd0953226c60624def54d2435d6ba0ce51e8fdbccee2f7a726b2a86c8f", + "elapsed_seconds": 7.691392004024237 + }, + { + "pr": 1121, + "sha": "d9bf84b04784daf1d457a213f2dba277ba32ed2e", + "tree": "65b2ace97b2602c67311449144201b0b5760913a", + "binary_sha256": "b662c1321a36ea45ad4207c98c3ed12621ecfe900a9060dde15c20cc5b327f61", + "bytes": 18434440, + "build_manifest_sha256": "211b9e61bfcb48a73cc54856a2f688c4296b6829a932079c991bc68f85ea0331", + "elapsed_seconds": 4.223810734925792 + }, + { + "pr": 1122, + "sha": "0e95e191ba7d7ee3769217e7fbf82a825ff9b90d", + "tree": "ac81b90e6759936f944137f074a6592a93c602d8", + "binary_sha256": "e158875175cb7ad64747911d69836842ac1079ac907412270a15b3f090eaf0cc", + "bytes": 18433048, + "build_manifest_sha256": "40593e8322693a4374bb6a18131372e2d4fc10dcfeaa879f565c02953e118167", + "elapsed_seconds": 33.68569688498974 + }, + { + "pr": 1123, + "sha": "83657b9dfe35adda2a4cede5a1ae71db2f2b870d", + "tree": "8757d218ddd469cf8d6da0412aaded21eea89842", + "binary_sha256": "a0679789c7e76a09fca6efe356fa541a2bb87f174d76b3bb64217b2065d55360", + "bytes": 18443440, + "build_manifest_sha256": "0848c12c804894c8e9f812b8b5005f9b619734af425c7548a6e8ed83cdd3b06c", + "elapsed_seconds": 14.271701524965465 + }, + { + "pr": 1124, + "sha": "de2fa3557d69e9c3eb1c52bb2b0300566f960fea", + "tree": "0372118af04c8b28e400ac2c42e7770a8284f1ba", + "binary_sha256": "a0679789c7e76a09fca6efe356fa541a2bb87f174d76b3bb64217b2065d55360", + "bytes": 18443440, + "build_manifest_sha256": "812f145bf64b9ae4b6b4bfd612a78608535e616aaa0360d62c41cd82a9882ff8", + "elapsed_seconds": 1.279053537058644 + }, + { + "pr": 1119, + "sha": "c95140674254c371844f1fab27a64951a80dac55", + "tree": "0c84c52edb72e1a8643e95d3f8d9c36cfb9c2b28", + "binary_sha256": "ba18f774e9f8d8f6cfd94efe211de305bd260f474e42ad3bbcd1a785aec0d296", + "bytes": 18443224, + "build_manifest_sha256": "2a5da319876b666b4e6abd29de17927963e52e975749ffa3d6ad958e64e35c0f", + "elapsed_seconds": 17.982304272940382 + }, + { + "pr": 1125, + "sha": "9bf1aad510d843d1d6338fbdf23107a30d339730", + "tree": "6773b29582bfd9a3cfa725d38334b845e6fb1884", + "binary_sha256": "ba18f774e9f8d8f6cfd94efe211de305bd260f474e42ad3bbcd1a785aec0d296", + "bytes": 18443224, + "build_manifest_sha256": "b19b7865be68e8d41fe93d4ce9edb25bd81e6526227fb52f637091b0ae154232", + "elapsed_seconds": 0.7968119849683717 + }, + { + "pr": 1126, + "sha": "d8cf61cccd4b0efed5058bf6fa45228e47162b48", + "tree": "d107bd98d9654a1d3697eb7908c3c76eed4b6233", + "binary_sha256": "ba18f774e9f8d8f6cfd94efe211de305bd260f474e42ad3bbcd1a785aec0d296", + "bytes": 18443224, + "build_manifest_sha256": "92f3ba8fcef0231e5f99b7690b916e436f60d0fb859e7f18ae0228750976d307", + "elapsed_seconds": 0.48625714995432645 + }, + { + "pr": 1127, + "sha": "1786340680499f50b08dee5b1ceffbc20fd7b533", + "tree": "456fc02247f3cf07dc393d61e59f70fc1c1dc977", + "binary_sha256": "69e80167ac5c8b2dbdfa9b7d6bf5299f6cc80c3278d3ead8d43fd6e228fb52c2", + "bytes": 18454496, + "build_manifest_sha256": "cf3c58c13b21e11b3c9f9d6cac493b712eca4a66ecd1353530ebc3375e435fc2", + "elapsed_seconds": 5.283866641926579 + }, + { + "pr": 1128, + "sha": "1278c8943a6abd236a2f20e3937cc8e23a0f95a7", + "tree": "26930342e34ce0b0899fcb3f1be0ac24511a5d58", + "binary_sha256": "c47c904b693c8c114bb87284497b98a10e4925f25afdc3f5ec4f26896ad1a2e1", + "bytes": 18454184, + "build_manifest_sha256": "0aba68b2924a9ab2343f943039469103b365265276db98ad0a6857a9217f6b45", + "elapsed_seconds": 0.529834948014468 + }, + { + "pr": 1129, + "sha": "77aa9ef9bc9475adcbdd37cf3004143a96f03060", + "tree": "2c38d1117a95c987657d8deec8e67a932b35c896", + "binary_sha256": "c47c904b693c8c114bb87284497b98a10e4925f25afdc3f5ec4f26896ad1a2e1", + "bytes": 18454184, + "build_manifest_sha256": "22231534e596a4049a656363d74312b667deb66b061e58998e06ee366c26726a", + "elapsed_seconds": 0.43361345201265067 + }, + { + "pr": 1130, + "sha": "ae8c5af3eb11dc8571f11db9b307b0db948f78c6", + "tree": "3950c87709136624ce54188a8d9afb38d48854f7", + "binary_sha256": "c47c904b693c8c114bb87284497b98a10e4925f25afdc3f5ec4f26896ad1a2e1", + "bytes": 18454184, + "build_manifest_sha256": "b2047fd05cf98338b40681258b1b48bcc8c5b109865247cd7b92b45b37467008", + "elapsed_seconds": 109.87988504196983 + } + ], + "accounting_launcher": { + "source_revision": "ae8c5af3eb11dc8571f11db9b307b0db948f78c6", + "command": [ + "bazel", + "--nosystem_rc", + "--nohome_rc", + "build", + "//tools:process_resources_native", + "--config=clang_opt", + "--jobs=6", + "--disk_cache=/home/marcus/.cache/bazel-disk", + "--action_env=LD_LIBRARY_PATH=/home/marcus/Documents/xff-chart-campaign-20261107/compat/usr/lib/x86_64-linux-gnu" + ], + "query": [ + "bazel", + "--nosystem_rc", + "--nohome_rc", + "cquery", + "config(//tools:process_resources_native, target)", + "--config=clang_opt", + "--jobs=6", + "--disk_cache=/home/marcus/.cache/bazel-disk", + "--action_env=LD_LIBRARY_PATH=/home/marcus/Documents/xff-chart-campaign-20261107/compat/usr/lib/x86_64-linux-gnu", + "--output=starlark", + "--starlark:expr=target.files_to_run.executable.path" + ], + "artifact": "bazel-out/k8-opt/bin/tools/process_resources_native", + "sha256": "c8822009aa8b2eb0505a6c883d452c1834efab732b1104b58ab67b998b246df2", + "source_sha256": "0b72ffc7b767682dca724bb6d8de8b5f2ccaae532b5b99c9e14f68505769a010" + }, + "installed_dependencies": { + "status": "installed locally", + "package": "/home/marcus/Documents/xff-chart-campaign-20261107/libicu70_70.1-2ubuntu1_amd64.deb", + "url": "https://archive.ubuntu.com/ubuntu/pool/main/i/icu/libicu70_70.1-2ubuntu1_amd64.deb", + "sha256": "223c1e6cebf2a6748637303227d8b84337c14a2d30eacbc46a68d02557dcff3e", + "library_path": "/home/marcus/Documents/xff-chart-campaign-20261107/compat/usr/lib/x86_64-linux-gnu", + "libraries": { + "libicudata.so.70": "68b1442c7bc043896934153e81b40f3b9154628f441739b3590eeae1654495ae", + "libicudata.so.70.1": "68b1442c7bc043896934153e81b40f3b9154628f441739b3590eeae1654495ae", + "libicuio.so.70.1": "b56a951d1cb3379e1129750c8728fc4cea72ed1f48d50a332c38b3fe929a030b", + "libicuio.so.70": "b56a951d1cb3379e1129750c8728fc4cea72ed1f48d50a332c38b3fe929a030b", + "libicutest.so.70": "adb32cde4fc5764fc9d67b9538434ecee9cdabfd8bf51179afe2b8bf4023156a", + "libicutu.so.70": "d2c53127b32b637cb088077d9dfa9e4ce283b1d1d78db5f394fa1b218bd39a9d", + "libicutest.so.70.1": "adb32cde4fc5764fc9d67b9538434ecee9cdabfd8bf51179afe2b8bf4023156a", + "libicui18n.so.70.1": "400b4ac2b04121b9f0b8bd5549086491a3d72435d3217190f8767b4fb0080e3d", + "libicutu.so.70.1": "d2c53127b32b637cb088077d9dfa9e4ce283b1d1d78db5f394fa1b218bd39a9d", + "libicuuc.so.70.1": "b62ce27b7f7036d6bee15086f569271239fe5d46ef5da7535acf32e5e5e80b7b", + "libicui18n.so.70": "400b4ac2b04121b9f0b8bd5549086491a3d72435d3217190f8767b4fb0080e3d", + "libicuuc.so.70": "b62ce27b7f7036d6bee15086f569271239fe5d46ef5da7535acf32e5e5e80b7b" + } + } +} diff --git a/tools/benchmark_extended_report.py b/tools/benchmark_extended_report.py index 6eb5f00dd40..ce8f7396840 100644 --- a/tools/benchmark_extended_report.py +++ b/tools/benchmark_extended_report.py @@ -60,13 +60,74 @@ def summarize_cell(row, contract): raise ValueError('expected one traditional reference') reference = references.pop() lower, upper = paired_interval(participants['xff'], participants['anchor']) + resources = {} + for label, prefix in [('xff', 'xff'), ('anchor', 'anchor'), (reference, 'reference')]: + selected = sorted(participants[label], key=lambda sample: sample['elapsed_seconds'])[:contract['keep']] + resources[prefix + '_cpu_seconds'] = statistics.fmean( + sample['user_cpu_seconds'] + sample['system_cpu_seconds'] for sample in selected) + for kind in ('user', 'system'): + resources[prefix + '_' + kind + '_cpu_seconds'] = statistics.fmean( + sample[kind + '_cpu_seconds'] for sample in selected) + resources[prefix + '_rss_bytes'] = statistics.fmean(sample['peak_child_rss_bytes'] for sample in selected) + resources[prefix + '_first_stdout_seconds'] = statistics.fmean(sample['first_stdout_seconds'] for sample in selected) return dict(row['case'], sha=row['revision']['sha'], pr=row['revision']['pr'], binary_sha256=row['revision']['binary_sha256'], reference=reference, xff_seconds=means['xff'], anchor_seconds=means['anchor'], reference_seconds=means[reference], reference_over_xff=means[reference] / means['xff'], historical_over_current=means['xff'] / means['anchor'], current_time_reduction_percent=100 * (1 - means['anchor'] / means['xff']), - paired_ratio_ci_low=lower, paired_ratio_ci_high=upper) + paired_ratio_ci_low=lower, paired_ratio_ci_high=upper, **resources) + + +def task_summaries(rows, contract): + """Equally weight the measured shape/worker combinations at each task and size.""" + populations = defaultdict(list) + for row in rows: + populations[(row['sha'], row['name'], row['files'])].append(row) + expected = defaultdict(set) + for case in contract['cases']: + expected[(case['name'], case['files'])].add((case['shape'], case['cpus'])) + summaries = [] + for (sha, name, files), group in populations.items(): + if {(row['shape'], row['cpus']) for row in group} != expected[(name, files)]: + continue + if len(group) != len(expected[(name, files)]): + raise ValueError('duplicate shape/worker measurements in task summary') + summaries.append({'sha': sha, 'pr': group[0]['pr'], 'name': name, 'files': files, + 'cells': len(group), 'binary_sha256': group[0]['binary_sha256'], + 'historical_over_current_geomean': statistics.geometric_mean( + row['historical_over_current'] for row in group), + 'xff_over_reference_geomean': statistics.geometric_mean( + 1 / row['reference_over_xff'] for row in group), + 'xff_over_reference_cpu_geomean': statistics.geometric_mean( + row['xff_cpu_seconds'] / row['reference_cpu_seconds'] for row in group)}) + return summaries + + +def current_reference_summaries(rows): + """Describe the repeated fixed-current/reference pairs across historical blocks. + + The spread is an observed distribution, not a confidence interval over machines. + Historical timings do not enter these ratios. + """ + populations = defaultdict(list) + for row in rows: + populations[(row['name'], row['shape'], row['files'], row['cpus'])].append(row) + summaries = [] + for (name, shape, files, cpus), group in populations.items(): + if len({row['sha'] for row in group}) != len(group): + raise ValueError('duplicate historical context in current/reference summary') + ratios = sorted(row['anchor_seconds'] / row['reference_seconds'] for row in group) + deciles = statistics.quantiles(ratios, n=10, method='inclusive') if len(ratios) > 1 else ratios * 9 + summaries.append({'name': name, 'shape': shape, 'files': files, 'cpus': cpus, + 'historical_contexts': len(group), 'reference': group[0]['reference'], + 'current_over_reference_geomean': statistics.geometric_mean(ratios), + 'current_over_reference_median': statistics.median(ratios), + 'current_over_reference_p10': deciles[0], + 'current_over_reference_p90': deciles[8], + 'current_over_reference_cpu_geomean': statistics.geometric_mean( + row['anchor_cpu_seconds'] / row['reference_cpu_seconds'] for row in group)}) + return summaries def as_report(rows, contract, view): @@ -96,12 +157,12 @@ def as_report(rows, contract, view): 'estimator': 'mean-fastest'}, 'tasks': tasks} -def export_viewer(output, contract, revisions, renderer): +def export_viewer(output, contract, revisions, renderer, incomplete=False): assets = output / 'assets' assets.mkdir(exist_ok=True) shutil.copyfile(renderer, assets / 'three-landscape.js') catalog = [] - for view, title in [('traditional', 'Traditional tools'), ('anchor', f'Fixed XFF at PR #{contract["anchor"]["pr"]}')]: + for view, title in [('traditional', 'Traditional tools'), ('anchor', f'XFF history (fixed PR #{contract["anchor"]["pr"]})')]: reports = [(revision, rows, as_report(rows, contract, view)) for revision, rows in revisions] order = landscape.common_task_order([matrix.relative_results(report) for _, _, report in reports]) for revision, rows, report in reports: @@ -125,12 +186,16 @@ def export_viewer(output, contract, revisions, renderer): 'reason': 'Clean historical source, configured production ThinLTO build, frozen executable hash checked before and after collection.'}, 'identity': 'Drogon Linux extended qualification', 'platform_details': contract['platform']}) (output / 'catalog.json').write_text(json.dumps(catalog, indent=2) + '\n') + status = 'Collection in progress. Only complete revisions are shown.
' if incomplete else '' intro = ('Independent extended suite; production full binaries on Linux tmpfs. ' + '
Independent extended suite; production full binaries on Linux tmpfs. ' 'Each historical run is interleaved with the fixed current binary and a traditional tool. ' - f'{len(revisions)} complete revisions are shown, including regressions and unchanged controls.
') - (output / 'index.html').write_text(intro + landscape.history_panel(catalog) + '') + f'{len(revisions)} complete revisions are shown, including regressions and unchanged controls.' + 'The XFF history dataset compares the selected historical binary with the fixed current one. ' + 'Its current revision is an identical-binary control and should be near zero.
') + panel = landscape.history_panel(catalog).replace('', '') + (output / 'index.html').write_text(intro + panel + '