23790efe33021ccd1691bf5f4262c1396a1f6e9d braney Fri May 1 12:49:13 2026 -0700 quickLiftBench: phase_asserts mechanism + parallel-fetch regression case phase_asserts is a per-case schema in cases.yaml that declares regex matches against the per-iteration timing spans, with optional required/min_median_ms/max_median_ms bounds. When a case declares phase_asserts, the runner captures phase data automatically and runs the asserts after iterations complete; any failure prints to stderr and exits non-zero. The new regress_quickLift_parallel case uses this to assert that the "Waiting for parallel..." span fires for the lifted multi-track session Brianraney/benchQuickPara with a median between 500 and 15000 ms -- discriminating the working sandbox build from a pre-fix hgwdev where only non-quickLift tracks parallelize at ~50 ms. refs #37488, #37470 diff --git src/utils/qa/quickLiftBench/cases.yaml src/utils/qa/quickLiftBench/cases.yaml index b3dadb4f194..d0fb7ae939c 100644 --- src/utils/qa/quickLiftBench/cases.yaml +++ src/utils/qa/quickLiftBench/cases.yaml @@ -1,63 +1,88 @@ # quickLiftBench cases.yaml # # Each case names two (or more) variants, where each variant is a saved-session # reference of the form `user/sessionName`. Both variants render on the same # server (set `server:` per case). The runner does (warmup + iterations) # requests per variant and writes per-iteration rows to results.tsv plus a # per-case summary with median/p90 and pairwise ratios. # # Each session renders at the position it was saved with -- the runner does # NOT override `position`. A native session and its quickLifted counterpart # live on different assemblies, so identical chr:start-end ranges would not # be biologically equivalent. To benchmark multiple regions, save additional # session pairs and add them as separate cases. # # The headline metric is `total_ms`, taken from the "Overall total time" timing # span emitted by hgTracks. `load_ms_sum` and `draw_ms_sum` are summed across # all visible tracks from the printTrackTiming() table; use them when you want # to attribute time to per-track work vs. CGI startup / cart processing. defaults: iterations: 25 warmup: 1 timeout: 60 servers: hgwdev: https://hgwdev.gi.ucsc.edu sandbox: https://hgwdev-braney.gi.ucsc.edu beta: https://hgwbeta.soe.ucsc.edu rr: https://genome.ucsc.edu cases: # -------- Smoke test: one session, no comparison -------- - id: smoke_session description: | Smoke: load one saved session on hgwdev. Confirms the runner loads sessions and extracts Overall total time + per-track timings from a live response. server: hgwdev variants: base: Braney/hg38 # -------- Bench pair 1: native vs quickLifted (hgwdev) -------- - id: bench1_hgwdev description: | First benchmark pair on hgwdev: native vs quickLifted view of an equivalent track set. Each session renders at its own saved region. server: hgwdev variants: native: Brianraney/benchQuickNative1 lifted: Brianraney/benchQuickList1 compare: - [native, lifted] # -------- Bench pair 1: same sessions on the public RR -------- - id: bench1_rr description: | Same session pair as bench1_hgwdev, run against genome.ucsc.edu. server: rr variants: native: Brianraney/benchQuickNative1 lifted: Brianraney/benchQuickList1 compare: - [native, lifted] + + # -------- Regression: parallel-fetch tripwire (refs #37488, #37470) -------- + # phase_asserts make this case fail-fast if the parallel pool stops + # firing for quickLift tracks (e.g. a regression in isTrackForParallelLoad + # or customFactoryParallelLoad). Runs against the sandbox until the fix + # lands on hgwdev. + - id: regress_quickLift_parallel + description: | + Regression tripwire: a quickLifted multi-track session must + spawn the parallel-fetch worker pool. Asserts the + "Waiting for parallel..." span is emitted in every iteration. + server: sandbox + variants: + base: Brianraney/benchQuickPara + phase_asserts: + # Required + min_median together: catch a regression that drops the + # quickLift tracks back to serial. With the fix in place the median + # parallel wait is several seconds; without it (only non-quickLift + # tracks parallelize) the wait is ~50 ms, so 500 ms cleanly separates + # the working and broken cases. + - variant: base + phase: 'Waiting for parallel \(\d+ threads for \d+ tracks\) remote data fetch' + required: true + min_median_ms: 500 + max_median_ms: 15000