Skip to content

Commit 7ac944c

Browse files
authored
feat: merge-train/spartan (#24911)
BEGIN_COMMIT_OVERRIDE fix(bench): grant helm-sa logging.viewer for scraper log reads (#24908) feat(bench): publish block-capacity benchmark to the custom dashboard pipeline (#24913) feat(bench): publish real-proving benchmark to the custom dashboard pipeline (#24914) END_COMMIT_OVERRIDE
2 parents 91e0e4b + e0bbbcc commit 7ac944c

9 files changed

Lines changed: 166 additions & 4 deletions

File tree

.github/workflows/nightly-spartan-bench.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,12 @@ jobs:
349349
AWS_SHUTDOWN_TIME: 180
350350
NO_SPOT: 1
351351
SKIP_NETWORK_DEPLOY: "1"
352+
# Publishes to the custom network-dashboard pipeline (GCS). Fake/fixed-delay
353+
# proving, so it's tagged simulated-proving (distinct from the weekly
354+
# real-proving run).
355+
BENCH_SWEEP_ID: simulated-proving-${{ github.run_id }}
356+
BENCH_SWEEP_LABEL: simulated-proving
357+
BENCH_BENCHMARK_TYPE: simulated-proving
352358
run: |
353359
./.github/ci3.sh network-proving-bench prove-n-tps-fake prove-n-tps-fake "${{ needs.select-image.outputs.docker_image }}"
354360
@@ -527,6 +533,11 @@ jobs:
527533
AWS_SHUTDOWN_TIME: 240
528534
NO_SPOT: 1
529535
SKIP_NETWORK_DEPLOY: "1"
536+
# Publishes to the custom network-dashboard pipeline (GCS) tagged as the
537+
# block-capacity benchmark, grouped as one sweep per run.
538+
BENCH_SWEEP_ID: block-capacity-${{ github.run_id }}
539+
BENCH_SWEEP_LABEL: block-capacity
540+
BENCH_BENCHMARK_TYPE: block-capacity
530541
run: |
531542
./.github/ci3.sh network-block-capacity-bench block-capacity nightly-block-capacity "${{ needs.select-image.outputs.docker_image }}"
532543

.github/workflows/weekly-proving-bench.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ jobs:
133133
AWS_SHUTDOWN_TIME: 180
134134
NO_SPOT: 1
135135
SKIP_NETWORK_DEPLOY: "1"
136+
# Publishes to the custom network-dashboard pipeline (GCS) tagged as the
137+
# real-proving benchmark, grouped as one sweep per run.
138+
BENCH_SWEEP_ID: real-proving-${{ github.run_id }}
139+
BENCH_SWEEP_LABEL: real-proving
140+
BENCH_BENCHMARK_TYPE: real-proving
136141
run: |
137142
./.github/ci3.sh network-proving-bench prove-n-tps-real prove-n-tps-real
138143

ci.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ case "$cmd" in
353353
export INSTANCE_POSTFIX="n-proving-bench"
354354
skip_network_deploy=0
355355
[ "${SKIP_NETWORK_DEPLOY:-0}" = "1" ] && skip_network_deploy=1
356-
bootstrap_ec2 "SKIP_NETWORK_DEPLOY=$skip_network_deploy ./bootstrap.sh ci-network-proving-bench $*"
356+
bootstrap_ec2 "BENCH_SWEEP_ID=${BENCH_SWEEP_ID:-} BENCH_SWEEP_LABEL=${BENCH_SWEEP_LABEL:-} BENCH_BENCHMARK_TYPE=${BENCH_BENCHMARK_TYPE:-} SKIP_NETWORK_DEPLOY=$skip_network_deploy ./bootstrap.sh ci-network-proving-bench $*"
357357
;;
358358
network-block-capacity-bench)
359359
# Args: <scenario> <namespace> [docker_image]
@@ -363,7 +363,7 @@ case "$cmd" in
363363
export INSTANCE_POSTFIX="n-block-cap-bench"
364364
skip_network_deploy=0
365365
[ "${SKIP_NETWORK_DEPLOY:-0}" = "1" ] && skip_network_deploy=1
366-
bootstrap_ec2 "SKIP_NETWORK_DEPLOY=$skip_network_deploy ./bootstrap.sh ci-network-block-capacity-bench $*"
366+
bootstrap_ec2 "BENCH_SWEEP_ID=${BENCH_SWEEP_ID:-} BENCH_SWEEP_LABEL=${BENCH_SWEEP_LABEL:-block-capacity} BENCH_BENCHMARK_TYPE=${BENCH_BENCHMARK_TYPE:-block-capacity} SKIP_NETWORK_DEPLOY=$skip_network_deploy ./bootstrap.sh ci-network-block-capacity-bench $*"
367367
;;
368368
network-bench-10tps)
369369
# Args: <scenario> <namespace> [docker_image]

spartan/bootstrap.sh

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,40 @@ function proving_bench {
208208
gcp_auth
209209
export_admin_api_key
210210
export K8S_ENRICHER=${K8S_ENRICHER:-1}
211-
proving_bench_cmds | parallelize 1
211+
export BENCH_RUN_ID="${BENCH_RUN_ID:-$(date -u +%Y%m%d)-proving-${COMMIT_HASH:0:10}}"
212+
# real proving (prove-n-tps-real, REAL_VERIFIER=true) vs fake/simulated timings.
213+
local benchmark_type="${BENCH_BENCHMARK_TYPE:-$([ "${REAL_VERIFIER:-}" = "true" ] && echo real-proving || echo simulated-proving)}"
214+
215+
local test_rc=0
216+
proving_bench_cmds | parallelize 1 || test_rc=$?
217+
if [[ "$test_rc" -ne 0 ]]; then
218+
echo "[proving_bench] test exited ${test_rc}; scraping captured data anyway"
219+
fi
220+
221+
# Publish to the custom pipeline (GCS -> network-dashboard) alongside the
222+
# legacy github-action-benchmark output the workflow still uploads.
223+
local metadata="/tmp/n_tps_prove_timing_data.json"
224+
local run_json="bench-out/bench-${benchmark_type}-${BENCH_RUN_ID}.json"
225+
if [[ -f "$metadata" ]]; then
226+
local started=$(jq -r .startedAt < "$metadata")
227+
local ended=$(jq -r .endedAt < "$metadata")
228+
echo "Scraping ${benchmark_type} run ${BENCH_RUN_ID} (started=${started} ended=${ended})"
229+
NAMESPACE="$NAMESPACE" GCP_PROJECT_ID="${GCP_PROJECT_ID:-}" ./scripts/bench_10tps/bench_scrape.ts \
230+
--run-id "$BENCH_RUN_ID" \
231+
--started "$started" \
232+
--ended "$ended" \
233+
--target-tps "${TARGET_TPS:-1}" \
234+
--sweep-id "${BENCH_SWEEP_ID:-$BENCH_RUN_ID}" \
235+
--sweep-label "${BENCH_SWEEP_LABEL:-$benchmark_type}" \
236+
--benchmark-type "$benchmark_type" \
237+
--output "$run_json" \
238+
|| echo "[proving_bench] scraper failed (non-fatal)"
239+
network_bench_upload "$run_json" || echo "[network_bench] upload failed (non-fatal)"
240+
else
241+
echo "[proving_bench] no timing metadata at ${metadata}; skipping custom-pipeline scrape"
242+
fi
243+
244+
return "$test_rc"
212245
}
213246

214247
function block_capacity_bench {
@@ -222,7 +255,39 @@ function block_capacity_bench {
222255
gcp_auth
223256
export_admin_api_key
224257
export K8S_ENRICHER=${K8S_ENRICHER:-1}
225-
block_capacity_bench_cmds | parallelize 1
258+
export BENCH_RUN_ID="${BENCH_RUN_ID:-$(date -u +%Y%m%d)-block-capacity-${COMMIT_HASH:0:10}}"
259+
260+
# Capture the test exit code but don't abort: even a partial run produced blocks
261+
# worth scraping. We scrape below, then re-surface the failure at the end.
262+
local test_rc=0
263+
block_capacity_bench_cmds | parallelize 1 || test_rc=$?
264+
if [[ "$test_rc" -ne 0 ]]; then
265+
echo "[block_capacity_bench] test exited ${test_rc}; scraping captured data anyway"
266+
fi
267+
268+
# Publish to the custom pipeline (GCS -> network-dashboard) alongside the
269+
# legacy github-action-benchmark output the workflow still uploads.
270+
local metadata="/tmp/block_capacity_timing_data.json"
271+
local run_json="bench-out/bench-block-capacity-${BENCH_RUN_ID}.json"
272+
if [[ -f "$metadata" ]]; then
273+
local started=$(jq -r .startedAt < "$metadata")
274+
local ended=$(jq -r .endedAt < "$metadata")
275+
echo "Scraping block-capacity run ${BENCH_RUN_ID} (started=${started} ended=${ended})"
276+
NAMESPACE="$NAMESPACE" GCP_PROJECT_ID="${GCP_PROJECT_ID:-}" ./scripts/bench_10tps/bench_scrape.ts \
277+
--run-id "$BENCH_RUN_ID" \
278+
--started "$started" \
279+
--ended "$ended" \
280+
--sweep-id "${BENCH_SWEEP_ID:-$BENCH_RUN_ID}" \
281+
--sweep-label "${BENCH_SWEEP_LABEL:-block-capacity}" \
282+
--benchmark-type "${BENCH_BENCHMARK_TYPE:-block-capacity}" \
283+
--output "$run_json" \
284+
|| echo "[block_capacity_bench] scraper failed (non-fatal)"
285+
network_bench_upload "$run_json" || echo "[network_bench] upload failed (non-fatal)"
286+
else
287+
echo "[block_capacity_bench] no timing metadata at ${metadata}; skipping custom-pipeline scrape"
288+
fi
289+
290+
return "$test_rc"
226291
}
227292

228293
# One point of the inclusion sweep: a fixed 1 TPS of high-value txs (the

spartan/scripts/bench_10tps/bench_output.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,11 @@
682682
"type": "number",
683683
"minimum": 0
684684
},
685+
"manaPerSec": {
686+
"type": "number",
687+
"minimum": 0,
688+
"description": "Mana consumed per second while building this block (totalManaUsed / buildDuration), from the l2-block-built log. The headline throughput signal for the block-capacity benchmark. Optional; absent when the block-built log was not captured."
689+
},
685690
"totalPublicGas": {
686691
"type": "object",
687692
"additionalProperties": false,

spartan/scripts/bench_10tps/bench_scrape.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,32 @@ const PROVING_INFRA_DEFS: Record<string, TimeSeriesDef> = {
840840
unit: "count",
841841
query: queueRateByJobType("aztec_proving_queue_resolved_jobs_count"),
842842
},
843+
// Epoch proving: how long the prover node takes to prove a job (epoch) and how
844+
// much it has proven. The headline real-proving signal — compare against the
845+
// epoch wall-clock (AZTEC_PROOF_SUBMISSION_EPOCHS * epoch duration).
846+
epochProvingDurationP50: {
847+
metric: "aztec_prover_node_job_duration",
848+
unit: "s",
849+
query: proverNodeHist(0.5, "aztec_prover_node_job_duration_seconds_bucket"),
850+
},
851+
epochProvingDurationP99: {
852+
metric: "aztec_prover_node_job_duration",
853+
unit: "s",
854+
query: proverNodeHist(
855+
0.99,
856+
"aztec_prover_node_job_duration_seconds_bucket",
857+
),
858+
},
859+
provenBlocks: {
860+
metric: "aztec_prover_node_job_blocks",
861+
unit: "count",
862+
query: `sum(aztec_prover_node_job_blocks${NS})`,
863+
},
864+
provenTransactions: {
865+
metric: "aztec_prover_node_job_transactions",
866+
unit: "count",
867+
query: `sum(aztec_prover_node_job_transactions${NS})`,
868+
},
843869
};
844870

845871
// Scrape a map of slug -> PromQL def via query_range. One failing query emits an
@@ -1218,6 +1244,7 @@ type BlockRecord = {
12181244
silentlySkippedCount: number;
12191245
silentlySkippedDurationMs: number;
12201246
buildDurationSeconds: number;
1247+
manaPerSec?: number;
12211248
totalPublicGas?: { daGas: number; l2Gas: number };
12221249
totalSizeInBytes?: number;
12231250
source: "log";
@@ -1313,6 +1340,9 @@ async function scrapeBlocks(
13131340
? finiteOrZero(numberPayloadField(processorPayload ?? {}, "duration"))
13141341
: finiteOrZero(numberPayloadField(built.jsonPayload, "duration")) /
13151342
1000,
1343+
manaPerSec: numberOrUndefined(
1344+
numberPayloadField(built?.jsonPayload ?? {}, "manaPerSec"),
1345+
),
13161346
totalPublicGas: processorPayload?.totalPublicGas as
13171347
| { daGas: number; l2Gas: number }
13181348
| undefined,

spartan/terraform/gke-cluster/iam.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ resource "google_project_iam_member" "helm_sa_roles" {
5050
member = "serviceAccount:${google_service_account.helm_sa.email}"
5151
}
5252

53+
# helm-sa is the CI deploy identity (GitHub Actions secret GCP_SA_KEY). The bench
54+
# scraper runs `gcloud logging read` as this account to collect block/event/
55+
# sequencer-state records (l2-block-handled / l2-block-built / public-processor
56+
# logs); without logging read the reads are permission-denied and the scraper
57+
# silently emits empty block data (null totalTxsMined, empty build/validator
58+
# fields). Prometheus metrics use a kube port-forward and are unaffected.
59+
resource "google_project_iam_member" "helm_sa_logging_viewer" {
60+
project = var.project
61+
role = "roles/logging.viewer"
62+
member = "serviceAccount:${google_service_account.helm_sa.email}"
63+
}
64+
5365
# Create a service account for CI
5466
resource "google_service_account" "ci" {
5567
account_id = var.ci_service_account_id

yarn-project/end-to-end/src/spartan/block_capacity.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,12 @@ describe('block capacity benchmark', () => {
6767
let aztecNode: AztecNode;
6868
let originalSequencerConfig: Awaited<ReturnType<typeof getSequencersConfig>> | undefined;
6969
const benchmarkData: Array<{ name: string; unit: string; value: number }> = [];
70+
// Window handed to bench_scrape.ts so the custom pipeline can scrape this run's
71+
// blocks/metrics (see spartan/bootstrap.sh block_capacity_bench).
72+
let benchStartedAt: string | undefined;
7073

7174
beforeAll(async () => {
75+
benchStartedAt = new Date().toISOString();
7276
logger.info('Setting up block capacity benchmark', {
7377
numWallets: NUM_WALLETS,
7478
txRealProofs,
@@ -140,6 +144,19 @@ describe('block capacity benchmark', () => {
140144
logger.info('Wrote benchmark output', { path: process.env.BENCH_OUTPUT, entries: finalData.length });
141145
}
142146

147+
// Hand the run window to the custom-pipeline scraper (bench_scrape.ts), which
148+
// reads this file to bound its Prometheus/log queries for the block-capacity run.
149+
const timingMetadataPath = '/tmp/block_capacity_timing_data.json';
150+
await writeFile(
151+
timingMetadataPath,
152+
JSON.stringify({
153+
startedAt: benchStartedAt ?? new Date().toISOString(),
154+
endedAt: new Date().toISOString(),
155+
runId: process.env.BENCH_RUN_ID,
156+
}),
157+
);
158+
logger.info('Wrote block-capacity timing metadata', { path: timingMetadataPath });
159+
143160
// Restore original sequencer config
144161
if (originalSequencerConfig?.[0]) {
145162
logger.info('Restoring original sequencer config');

yarn-project/end-to-end/src/spartan/n_tps_prove.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ describe(`prove ${TARGET_TPS}TPS test`, () => {
133133
let rollupCheatCodes: RollupCheatCodes;
134134
let ethEndpoint: ServiceEndpoint | undefined;
135135
let metricsStartSnapshot: MetricsSnapshot | undefined;
136+
// Window handed to bench_scrape.ts so the custom pipeline can scrape this run's
137+
// proving-infra series (see spartan/bootstrap.sh proving_bench).
138+
let benchStartedAt: string | undefined;
136139

137140
afterAll(async () => {
138141
if (process.env.BENCH_OUTPUT && metrics && metricsStartSnapshot) {
@@ -212,6 +215,19 @@ describe(`prove ${TARGET_TPS}TPS test`, () => {
212215
await writeFile(process.env.BENCH_OUTPUT, JSON.stringify(metrics.toGithubActionBenchmarkJSON()));
213216
}
214217

218+
// Hand the run window to the custom-pipeline scraper (bench_scrape.ts), which
219+
// reads this file to bound its Prometheus queries for the proving run.
220+
const timingMetadataPath = '/tmp/n_tps_prove_timing_data.json';
221+
await writeFile(
222+
timingMetadataPath,
223+
JSON.stringify({
224+
startedAt: benchStartedAt ?? new Date().toISOString(),
225+
endedAt: new Date().toISOString(),
226+
runId: process.env.BENCH_RUN_ID,
227+
}),
228+
);
229+
logger.info('Wrote proving-bench timing metadata', { path: timingMetadataPath });
230+
215231
if (testWallets) {
216232
for (const tw of testWallets) {
217233
await tw.cleanup();
@@ -247,6 +263,7 @@ describe(`prove ${TARGET_TPS}TPS test`, () => {
247263
server: new URL(`http://127.0.0.1:${promPortForward.port}`),
248264
});
249265
metricsStartSnapshot = await captureMetricsSnapshot(prometheusClient, logger);
266+
benchStartedAt = new Date().toISOString();
250267
promPortForward.process.kill();
251268
logger.info('Metrics snapshot captured');
252269

0 commit comments

Comments
 (0)