Skip to content

Commit 7648a03

Browse files
karthiknadigCopilot
andcommitted
test: compare manager probe builds on one macOS host (Refs #530)
Temporary manual-only diagnostic branch for PR #555; not intended for merge. Counterbalance exact base/head binaries with one shared harness and exact inventory fingerprints. No production changes or budget adjustments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2f0ba2b commit 7648a03

1 file changed

Lines changed: 121 additions & 164 deletions

File tree

‎.github/workflows/perf-tests.yml‎

Lines changed: 121 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,196 +1,153 @@
1-
name: Performance Tests
1+
name: Manager Probe Matched Control
22

33
on:
4-
pull_request:
5-
branches:
6-
- main
7-
- release*
8-
- release/*
9-
- release-*
104
workflow_dispatch:
115

126
permissions:
13-
actions: read
147
contents: read
15-
pull-requests: write
168

179
jobs:
18-
performance:
19-
name: E2E Performance Tests
20-
runs-on: ${{ matrix.os }}
21-
strategy:
22-
fail-fast: false
23-
matrix:
24-
include:
25-
- os: windows-latest
26-
target: x86_64-pc-windows-msvc
27-
platform: Windows
28-
comment_header: perf-windows
29-
- os: ubuntu-latest
30-
target: x86_64-unknown-linux-musl
31-
platform: Linux
32-
comment_header: perf-linux
33-
- os: macos-latest
34-
target: x86_64-apple-darwin
35-
platform: macOS
36-
comment_header: perf-macos
10+
matched-control:
11+
runs-on: macos-latest
12+
timeout-minutes: 35
3713
steps:
38-
- name: Checkout
14+
- name: Checkout exact PR head
3915
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
40-
41-
- name: Post In-Progress Comment
42-
if: >-
43-
github.event_name == 'pull_request' &&
44-
github.event.pull_request.head.repo.full_name == github.repository
45-
continue-on-error: true
46-
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
4716
with:
48-
header: ${{ matrix.comment_header }}
49-
message: |
50-
## Performance Report (${{ matrix.platform }}) :hourglass_flowing_sand:
17+
ref: 2f0ba2b07d8a0632f3f39d2116fb702240539bbb
5118

52-
Running performance tests against baseline `${{ github.event.pull_request.base.sha }}`.
19+
- name: Initialize evidence
20+
shell: bash
21+
run: mkdir "$RUNNER_TEMP/manager-matched-control"
5322

5423
- name: Set Python to PATH
5524
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
5625
with:
5726
python-version: "3.12"
5827

59-
- name: Validate Snapshot Comparator
60-
run: python -m unittest discover -s scripts/tests -p 'test_*.py' -v
61-
shell: bash
62-
63-
- name: Add Conda to PATH (Windows)
64-
if: startsWith(matrix.os, 'windows')
65-
run: |
66-
$path = $env:PATH + ";" + $env:CONDA + "\condabin"
67-
echo "PATH=$path" >> $env:GITHUB_ENV
68-
69-
- name: Add Conda to PATH (Ubuntu)
70-
if: startsWith(matrix.os, 'ubuntu')
71-
run: echo "PATH=$PATH:$CONDA/condabin" >> $GITHUB_ENV
28+
- name: Install Conda and create the standard workload
7229
shell: bash
73-
74-
- name: Install Conda + add to PATH (macOS)
75-
if: startsWith(matrix.os, 'macos')
7630
run: |
77-
curl -o ~/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
78-
bash ~/miniconda.sh -b -p ~/miniconda
79-
echo "PATH=$PATH:$HOME/miniconda/bin" >> $GITHUB_ENV
80-
echo "CONDA=$HOME/miniconda" >> $GITHUB_ENV
81-
shell: bash
82-
83-
- name: Create test Conda environment
84-
run: conda create -n perf-test-env python=3.12 -y
85-
86-
- name: Create test venv
87-
run: python -m venv .venv
88-
shell: bash
89-
90-
- name: Rust Tool Chain setup
91-
uses: dtolnay/rust-toolchain@stable
31+
curl --fail --location -o "$RUNNER_TEMP/miniconda.sh" https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
32+
shasum -a 256 "$RUNNER_TEMP/miniconda.sh" > "$RUNNER_TEMP/manager-matched-control/installer-sha256.txt"
33+
bash "$RUNNER_TEMP/miniconda.sh" -b -p "$HOME/miniconda"
34+
echo "PATH=$PATH:$HOME/miniconda/bin" >> "$GITHUB_ENV"
35+
echo "CONDA=$HOME/miniconda" >> "$GITHUB_ENV"
36+
"$HOME/miniconda/bin/conda" create -n perf-test-env python=3.12 -y
37+
python -m venv .venv
38+
39+
- name: Rust toolchain
40+
uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable
9241
with:
93-
toolchain: stable
94-
targets: ${{ matrix.target }}
42+
toolchain: 1.98.1
43+
targets: x86_64-apple-darwin
9544

96-
- name: Cargo Fetch
97-
run: cargo fetch
45+
- name: Instrument only the shared test harness after its measured passes
9846
shell: bash
99-
100-
- name: Build Release
101-
run: cargo build --release --target ${{ matrix.target }}
47+
run: |
48+
python - <<'PY'
49+
from pathlib import Path
50+
path = Path("crates/pet/tests/e2e_performance.rs")
51+
source = path.read_text()
52+
for name in ["EnvironmentIdentity", "ManagerIdentity", "Inventory"]:
53+
marker = f"struct {name} {{"
54+
assert source.count(marker) == 1
55+
source = source.replace(marker, "#[derive(serde::Serialize)]\n" + marker)
56+
marker = 'expected_inventory.expect("Performance summary must run at least one iteration");'
57+
assert source.count(marker) == 1
58+
source = source.replace(marker, marker + '\n'
59+
' if let Some(path) = std::env::var_os("PET_DIAGNOSTIC_INVENTORY") {\n'
60+
' std::fs::write(path, serde_json::to_vec(&expected_inventory).unwrap()).unwrap();\n'
61+
' }\n')
62+
path.write_text(source)
63+
PY
64+
65+
- name: Build exact base and head
10266
shell: bash
103-
104-
- name: Run Performance Tests
105-
id: benchmark
10667
run: |
107-
set -o pipefail
108-
cargo test --release --features ci-perf --target ${{ matrix.target }} --test e2e_performance test_performance_summary -- --nocapture 2>&1 | tee perf-output.txt
68+
git fetch --no-tags --depth=1 origin 39c67104c4193fca0c14067ff0fb69d24fc92396
69+
git worktree add --detach "$RUNNER_TEMP/pet-base" 39c67104c4193fca0c14067ff0fb69d24fc92396
70+
cargo build --locked --release --target x86_64-apple-darwin --bin pet --manifest-path "$RUNNER_TEMP/pet-base/Cargo.toml" --target-dir "$RUNNER_TEMP/pet-base-target"
71+
cp "$RUNNER_TEMP/pet-base-target/x86_64-apple-darwin/release/pet" "$RUNNER_TEMP/pet-base-exe"
72+
cargo build --locked --release --target x86_64-apple-darwin --bin pet
73+
cp target/x86_64-apple-darwin/release/pet "$RUNNER_TEMP/pet-head-exe"
74+
cargo test --locked --release --features ci-perf --target x86_64-apple-darwin --test e2e_performance --no-run --message-format=json > "$RUNNER_TEMP/pet-test-build.jsonl"
75+
test "$(git rev-parse HEAD)" = 2f0ba2b07d8a0632f3f39d2116fb702240539bbb
76+
test "$(git -C "$RUNNER_TEMP/pet-base" rev-parse HEAD)" = 39c67104c4193fca0c14067ff0fb69d24fc92396
77+
{
78+
git rev-parse HEAD
79+
git -C "$RUNNER_TEMP/pet-base" rev-parse HEAD
80+
shasum -a 256 "$RUNNER_TEMP/pet-base-exe" "$RUNNER_TEMP/pet-head-exe"
81+
shasum -a 256 crates/pet/tests/e2e_performance.rs
82+
rustc -Vv
83+
uname -a
84+
sysctl -n machdep.cpu.brand_string
85+
} > "$RUNNER_TEMP/manager-matched-control/provenance.txt"
86+
87+
- name: Counterbalanced same-host measurements
88+
shell: bash
10989
env:
11090
RUST_BACKTRACE: 1
11191
RUST_LOG: warn
112-
shell: bash
113-
114-
- name: Extract Performance Metrics
115-
if: steps.benchmark.outcome == 'success'
11692
run: |
117-
if ! grep -q "JSON metrics:" perf-output.txt; then
118-
echo "Performance test produced no JSON metrics" >&2
119-
exit 1
120-
fi
121-
sed -n '/JSON metrics:/,/^}/p' perf-output.txt | tail -n +2 > metrics.json
122-
python -m json.tool metrics.json > /dev/null
123-
cat metrics.json
124-
shell: bash
125-
126-
- name: Wait for Exact PR Base Performance
127-
id: wait_for_base_performance
128-
if: always() && github.event_name == 'pull_request'
129-
run: >-
130-
python scripts/wait_for_baseline.py
131-
--repository "${{ github.repository }}"
132-
--workflow perf-baseline.yml
133-
--commit "${{ github.event.pull_request.base.sha }}"
134-
--artifact "perf-baseline-${{ matrix.os }}"
135-
--timeout-seconds 1200
136-
--poll-seconds 20
137-
env:
138-
GITHUB_TOKEN: ${{ github.token }}
139-
shell: bash
140-
141-
- name: Download Exact PR Base Performance
142-
if: >-
143-
always() && github.event_name == 'pull_request' &&
144-
steps.wait_for_base_performance.outcome == 'success'
145-
uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
146-
with:
147-
workflow: perf-baseline.yml
148-
commit: ${{ github.event.pull_request.base.sha }}
149-
workflow_conclusion: success
150-
name: perf-baseline-${{ matrix.os }}
151-
path: baseline-perf
152-
check_artifacts: true
153-
search_artifacts: true
154-
155-
- name: Download Main Performance for Manual Run
156-
if: always() && github.event_name == 'workflow_dispatch'
157-
uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
158-
with:
159-
workflow: perf-baseline.yml
160-
branch: main
161-
workflow_conclusion: success
162-
name: perf-baseline-${{ matrix.os }}
163-
path: baseline-perf
164-
check_artifacts: true
165-
search_artifacts: true
166-
167-
- name: Compare Performance Snapshot
168-
if: always()
169-
run: >-
170-
python scripts/quality_snapshot.py performance
171-
--current metrics.json
172-
--baseline baseline-perf/metrics.json
173-
--platform "${{ matrix.platform }}"
174-
--report performance-report.md
175-
--summary "$GITHUB_STEP_SUMMARY"
176-
shell: bash
177-
178-
- name: Upload PR Performance Results
93+
python - <<'PY'
94+
import hashlib
95+
import json
96+
import os
97+
from pathlib import Path
98+
import shutil
99+
import subprocess
100+
101+
temp = Path(os.environ["RUNNER_TEMP"])
102+
workspace = Path(os.environ["GITHUB_WORKSPACE"])
103+
artifacts = temp / "manager-matched-control"
104+
artifacts.mkdir(exist_ok=True)
105+
messages = [json.loads(line) for line in (temp / "pet-test-build.jsonl").read_text().splitlines()]
106+
tests = [m["executable"] for m in messages if m.get("reason") == "compiler-artifact"
107+
and m["target"]["name"] == "e2e_performance" and m.get("executable")]
108+
if len(tests) != 1:
109+
raise RuntimeError(f"Expected one benchmark executable, got {tests!r}")
110+
executable = workspace / "target/x86_64-apple-darwin/release/pet"
111+
revisions = {"base": "39c67104c4193fca0c14067ff0fb69d24fc92396",
112+
"head": "2f0ba2b07d8a0632f3f39d2116fb702240539bbb"}
113+
order = ["base", "head", "head", "base", "head", "base", "base", "head"]
114+
summary = []
115+
for index, label in enumerate(order, 1):
116+
source = temp / f"pet-{label}-exe"
117+
shutil.copy2(source, executable)
118+
digest = hashlib.sha256(executable.read_bytes()).hexdigest()
119+
if digest != hashlib.sha256(source.read_bytes()).hexdigest():
120+
raise RuntimeError("Benchmark executable copy did not match source")
121+
inventory = temp / f"pet-inventory-{index}.json"
122+
environment = dict(os.environ, PET_DIAGNOSTIC_INVENTORY=str(inventory))
123+
log = artifacts / f"{index}-{label}.log"
124+
with log.open("w") as output:
125+
subprocess.run([tests[0], "test_performance_summary", "--exact", "--nocapture"],
126+
cwd=workspace, stdout=output, stderr=subprocess.STDOUT,
127+
check=True, timeout=180, env=environment)
128+
inventory_digest = hashlib.sha256(inventory.read_bytes()).hexdigest()
129+
inventory.unlink()
130+
text = log.read_text()
131+
metrics, _ = json.JSONDecoder().raw_decode(text.split("JSON metrics:\n", 1)[1])
132+
(artifacts / f"{index}-{label}.json").write_text(json.dumps(metrics, indent=2) + "\n")
133+
result = {"iteration": index, "label": label, "revision": revisions[label], "sha256": digest,
134+
"inventory_sha256": inventory_digest,
135+
"environments_count": metrics["environments_count"],
136+
"managers_count": metrics["managers_count"],
137+
"stats": metrics["stats"], "locators": metrics["locators"], "phases": metrics["phases"]}
138+
summary.append(result)
139+
(artifacts / "summary.json").write_text(json.dumps(summary, indent=2) + "\n")
140+
print(json.dumps({"iteration": index, "label": label, "revision": revisions[label],
141+
"sha256": digest, "refresh": metrics["stats"]["refresh_round_trip"],
142+
"startup": metrics["stats"]["server_startup"]}), flush=True)
143+
if len({v["inventory_sha256"] for v in summary}) != 1:
144+
raise RuntimeError("Exact inventory identities differ between base and head workloads")
145+
PY
146+
147+
- name: Preserve matched control evidence
179148
if: always()
180149
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
181150
with:
182-
name: perf-pr-${{ matrix.os }}
183-
path: |
184-
metrics.json
185-
performance-report.md
186-
if-no-files-found: ignore
187-
188-
- name: Post Performance Comment
189-
if: >-
190-
always() && github.event_name == 'pull_request' &&
191-
github.event.pull_request.head.repo.full_name == github.repository
192-
continue-on-error: true
193-
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
194-
with:
195-
header: ${{ matrix.comment_header }}
196-
path: performance-report.md
151+
name: manager-530-matched-macos
152+
path: ${{ runner.temp }}/manager-matched-control
153+
if-no-files-found: error

0 commit comments

Comments
 (0)