scope: the read of what a plan's checks read walks 436,000 verdict rows (17.6 s) and times out in bursts of 11 to 16 after every restart; askers of the same checks should share one read #56
Open
opened 2026-11-13 06:18:20 +00:00 by xemmerling
·
0 comments
No Branch/Tag specified
main
dev/schema-step-order
t-join-release
t-work-booking
t-ahead-deadlock-wip
t-hotfix-9ae
t-width-work
t-id-token-renew
t-claim-unkept
t-resume-live
t-run-record
t-all-lockfiles
t-relay-offset
t-blame-event
t-freer-links
t-load-tests
t-jobserver2
t-starved-timeout
t-client-pack
t-offline-config
t-test-plan
t-told-resume2
t-jobserver
t-told-resume
t-outbound2
t-crash-open-bench
t-told-once
guest-never-below-given
admit-page-cache-active
pooled-admission
driver-give-back
no-sizes
one-driver-per-check
archive/vm-root-share
archive/build-out-kept
archive/cargo-perf
archive/virtiofs-readdir-alloc
archive/vm-outputs-stream
archive/stable-verify-priority
archive/agents-1
archive/stack-parallel
archive/cpu-admission
archive/narrow-from-every-log
archive/old-t
archive/worker-store-gc
archive/failing-builds-kept
archive/vm-cargo-home
archive/lifecycle
archive/bench-own-cores
archive/place-test-binaries-nocopy
archive/vm-net-upload-stall
archive/booking-current-use
archive/archive-dep-out-dirs
archive/any-arch-shards
archive/prepare-stall-progress-ns20
archive/s2
archive/next-set-20
archive/store-full-waits
archive/fetch-caps-by-node
archive/vm-step-phases
archive/arm-only-for-arm
archive/deploy-all-workers
archive/lifecycle-staging
archive/lifecycle-1-wire
archive/fast-gate
archive/cargo-key-narrow
archive/log-leads-followup
archive/gate-limit
archive/prepare-stall-vm-bytes
archive/lifecycle-2-ends
archive/cache-hits-bind
archive/failing-reused
archive/oci-archive-direct
archive/prepare-stall-progress
archive/test-quarantine
archive/crash-safe-on-18
archive/build-script-etxtbsy
archive/old-release
archive/next-set-19c
archive/wait-reasons
archive/cache-put-best-effort
archive/hang-not-t-time
archive/shard-test-results
archive/vm-carry-on-17
archive/check-test-filter
archive/artifact-path-beneath
archive/stall-room-xfs
archive/build-dir-no-recopy
archive/cache-hits-link
archive/outputs-no-follow-on-copy
archive/outputs-no-follow
archive/next-set-19
archive/hang-detect
archive/stable-verify-stable-plan
archive/freer-target-only
archive/lease-pricing-narrow
archive/vm-outputs-once
archive/queue-place-starved
archive/publish-reads
archive/disk-warning-scratch
archive/outputs-no-copy
archive/wd-probe-3min
archive/watchdog-on-d65
archive/log-leads-with-excerpt
archive/queue-place
archive/prep-watchdog-progress
archive/cache-put-stack-room
archive/cache-put-stack
archive/place-by-pace
archive/nested-sync-helper
archive/next-set-18y
archive/archive-bins-by-env-19
archive/next-set-18
archive/disk-want-held
archive/young-booking-back
archive/flaky-tests-1027b
archive/next-set-17
archive/prep-start-at-close
archive/unpack-error-on-17
archive/server-memory-high
archive/vm-start-held
archive/vm-carry-on-14
archive/space-trim-registry-room
archive/file-cache-ns16
archive/unpack-error-final
archive/crash-safe-worker
archive/server-space-trim
archive/status-big-runs
archive/nested-tmp-volatile
archive/publish-refresh
archive/gc-cache-quiet-reads
archive/next-set-16
archive/vm14-proof
archive/csw-node-kill
archive/unpack-link
archive/vm-tests-15
archive/seccomp-allow-field
archive/flaky-tests-1027-ns15
archive/shard-fail-fast
archive/server-node-check
archive/live-log-restart
archive/unpack-no-orphans
archive/flaky-tests-1027
archive/fetch-share-images
archive/fetch-images-red4
archive/forget-cached
archive/put-file-once-ns15
archive/recheck-rank-15
archive/fetch-images-red3
archive/unpack-no-orphans-red2
archive/fetch-io-pass-followups
archive/sandbox-no-fallback-ns15
archive/unpack-no-orphans-red
archive/archive-bins-by-env-ns15
archive/ns15-proof
archive/next-set-15
archive/archive-bins-by-env
archive/vm-guest-panic-15
archive/sandbox-no-fallback
archive/recheck-rank
archive/placement-ahead-bound
archive/carry-keeps-listing
archive/registry-parallel-pull
archive/sandbox-tests-15
archive/attempt-log-live-15
archive/follow-progress-16
archive/follow-progress-15
archive/ns15-archive-base
archive/fetch-io-max-on-13
archive/fetch-images-red2
archive/transient-build-fail-15
archive/test-ended-early-15
archive/archive-keep-cleanup
archive/main-merge-14
archive/sandbox-clone3-fallback
archive/vm-carry-on-13
archive/fetch-io-sweep-15
archive/vm-root-disk-fixes
archive/vm-guest-panic
archive/follow-progress-14
archive/archive-keep-on-demand
archive/vm-exit-unseen
archive/file-cache-share
archive/bwrap-root-userns
archive/transient-build-fail
archive/fetch-io-max
archive/file-cache-guard-11
archive/fetch-io-sweep
archive/archive-build-dir-skip
archive/next-set-14
archive/wrapper-one-read
archive/archive-tmp-links
archive/attempt-log-live
archive/fetch-share-and-order
archive/vm-hang-io-wait
archive/vm-carry-fixes
archive/image-cancel
archive/test-ended-early
archive/sim-on-train3-bundle
archive/hits-layer-wip
archive/t-old-putfile
archive/archive-links
archive/stall-on-13
archive/carried-prep-completes
archive/put-file-once
archive/preview-14
archive/follow-progress
archive/gc-reads-dont-protect
archive/admission-replay-people
archive/people-pickup
archive/gc-pass-visible
archive/hits-layer
archive/own-build-priced
archive/compact-stamps-followup
archive/prepare-timing
archive/sim-on-train3
archive/next-set-13
archive/next-set-12b
archive/sim-on-next-set-12
archive/deploy-doc-no-kill
archive/next-set-12
archive/attempt-logs-real
archive/sim-tests-green
archive/shard-label-index
archive/young-booking
archive/next-set-11
archive/data-dir-config-env
archive/vm-sync-not-host-store
archive/attempt-logs
archive/wrapper-ro
archive/tests-wait-on-events
archive/blame-git-optional-needs
archive/job-file-headroom-impl
archive/next-set-10
archive/blame-verdict-fresh-parent
archive/compact-touched-stamps
archive/interactive-incremental-off
archive/follow-lost-lines-counted
archive/evict-test
archive/next-set-trial
archive/keys-cover-output-bytes
archive/file-cache-guard
archive/blame-after-parent
archive/test-filter-matching-nothing-fails
archive/s1-on-d96
archive/draining-node-queues
archive/tprev-checks-prod-next
archive/s1-dead
archive/follow-live-run
archive/guard-stopped-setup-text
archive/io-error-cause
archive/source-layer-whole
archive/clippy-groups
archive/worker-silence-grace
archive/price-touched
archive/prod-next
archive/batch1
archive/s1-on-prod-next
archive/vmcache/sandbox-copyup-pin
archive/s1-xfs-store
archive/warm-script-builds
archive/vmcache/setup-tag-digest
archive/vmcache/setup-should-fixes
archive/vmcache/setup-any-arch
archive/guard-livelock
archive/host-budget
archive/wire-format-test
archive/admission-replay
archive/switch-safe
archive/stall-window
archive/upgrade-carries-preparing
archive/static-init
archive/switch-proof-b
archive/carry-tokens
archive/seals-together
archive/switch-safe-storage
archive/switch-safe-worker
archive/batch-b-prev
archive/vmcache/batch-b
archive/carry-vm-helpers
archive/small-llvm-args-failed-log
archive/batch-a
archive/stall-hotfix
archive/prev-pacing
archive/u-try-wip
archive/u-try
archive/u-try-wip2
archive/flatten-verify
archive/poll-free
archive/flatten-tiers
archive/hotfix-cross
archive/pool-stall
archive/disk-pacing
archive/u-builds-from-graph
archive/mac-idle
archive/ship-direct
archive/vmcache/shards
archive/soft-margin
archive/behind-no-target
archive/filtered-binaries
archive/vmcache/setup-layers
archive/direct-off-prev
archive/probe-budget
archive/vm-helper-exit
archive/jobs-soft-bound
archive/vmcache/vm-disks
archive/vmcache/failure-outputs
archive/narrowed-not-verdict
archive/scratch-direct-off
archive/handover-holds
archive/memory-lines
archive/drain-destroys
archive/pool-size
archive/drain-own-frees
archive/test-schema-drop
archive/deploy-disk
archive/deploy-disk-lines
archive/clone-aware-freeing
archive/absolute-headroom
archive/zfs-pool-size
archive/u-int5
archive/u-load
archive/u-warn
archive/u-steer
archive/revert-stall-once
archive/guard-headroom
archive/u-int3
archive/u-readsets
archive/u-hermetic
archive/mem-virtio
archive/u-buildjobs
archive/u-waits
archive/u-three
archive/u-zfs-stall
archive/u-config
archive/u-lean
archive/u-e2e
archive/u-integrate2
archive/u-jobenv
archive/u-cache-blobs
archive/u-observe2
archive/u-sched-nospread
archive/u-node-bound
archive/u-sched-oom
archive/u-review-store
archive/u-observe
archive/u-review-engine
archive/u-review-srv
archive/u-review-node
archive/u-review-sched
archive/preempt-measured
archive/u-integrate
archive/u-eng
archive/lock-off-runtime
archive/u-vm
archive/u-gone
archive/u-offline
archive/ready-starve
archive/u-notices
archive/heads-never-superseded
archive/u-learn
archive/int
archive/u-graph
archive/u-umount
archive/supersede-followed
archive/preparing-booking
archive/u-xdev
archive/u-env
archive/u-poll
archive/u-wrap
archive/u-room
archive/u-wrap-try
archive/u-fixed
archive/unstall
archive/u-fix3
archive/u-cwd
archive/resume-supersedes
archive/server-heap
archive/u-harness
archive/u-macos
archive/u-node
archive/u-eng2
archive/u-leader
archive/u-cutover
archive/u-cache
archive/u-sched
archive/u-engine
archive/chore/agpl-license
archive/note-x86-disk-room
archive/pass-cost
archive/prod-defects
archive/clippy-false-greens
archive/t-pace-variance-prototype
archive/outputs-reattach
archive/fix-retry-needs
archive/no-supersede-uncached
archive/fix/promoted-view-mtime
archive/rb-merge
archive/ft-sched
archive/ft-node
archive/ft-engine
archive/fx-sim
archive/fx2-mem
archive/fx2-store
archive/fx2-ci
archive/fx-work
archive/fx-ci
archive/fx-sched
archive/fx-req
archive/fx-store
archive/fx-cache
archive/rb-storage
archive/rb-scheduling
archive/rb-sweep
archive/rb-tracking
archive/rb-workers
archive/rb-client
archive/rb-profiles
archive/rebuild
archive/batch-deploy
archive/fix-roll
archive/work
archive/fix-busy
archive/fix-perf
archive/fix-suite
archive/fix-spread
archive/fix-sig
archive/fix-wait
archive/fix-init
archive/sizing
archive/fix-drift
archive/delivery
archive/fix-snap
archive/fix-own
archive/fix-rollout
archive/fix-hang
archive/fix-tree
archive/images
archive/fill
archive/sched-gate-preparing-after
archive/takeover-sim
archive/image-d244b22
archive/image-ce8a09e
archive/image-c9ff4f7
archive/image-489bec9
archive/image-7e07ffb
archive/image-583ea93
archive/image-8e1cd2c
archive/image-fbf0a9c
archive/image-6924e11
archive/image-29cabc3
archive/image-97ebb0e
archive/image-d0e23ac
archive/image-319fce9
archive/image-4f689e1
archive/image-feacbcd
archive/image-d5d9446
archive/image-6b86940
archive/fix/dedup-priority-promotion
archive/image-a5b0fe3
archive/image-462afb1
archive/image-f39d42c
archive/image-6e71fb4
archive/image-0c62329
archive/resources
archive/image-112b6a6
archive/image-8b06530
archive/image-5ae7cd8
archive/fmt-fix-in-t-toml
archive/image-arm64
Labels
Clear labels
No items
No labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
tilo/t#56
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Update 13:36Z 2026-11-13: one hour on
f06bfdc3; from my side this issue is answered bye1a2ecbb.8210a6d7)f06bfdc3pg_stat_activitysamplescheck_readsactive or waiting for a lockerrorby="unit") against servable (outside)The pause in head verdicts is the cold wave of unit graphs (#58) and the clippy builds run once more under their new keys. Left to watch, not this issue's: server memory 38.6 GB at one hour (35.8 GB before), and the scheduler's passes over a second, 3.3 to 3.8 s until 13:10Z and 1.85 s by 13:30Z (#53).
Update 12:52Z 2026-11-13:
f06bfdc3is on production since 12:32:20Z (your promote); the take-over read clean. Readings to 12:50Z:8210a6d7)f06bfdc3)pg_stat_activitysamples 5 s apartcheck_readsactive or waiting for a lock, same sampleserror, 18 mincheck_readsheld 11,586 rows over 2,637 checks a minute after the start. I leave this issue open for the one-hour reading.One thing the restart did show is in #58: the cold wave of unit graphs under parse version 9 passed the resolver's 120 s limit for 66 graphs on their first try.
Update 12:24Z 2026-11-13: I am not promoting at 12:30Z.
f06bfdc3landed on main at 12:11Z and its image is building on testing, so the batch is yours and still moving. I read both commits and have no objection. e1a2ecbb's locks: a verdict takes its keys' locks, then its checks', and retention takes only checks' in the same order, so I see no cycle; production told 7,231 verdicts over 1,201 check names in the hour to 12:12Z, the most told name 56 times, so two recorders of one check rarely meet.f06bfdc3: a harness's check must be one of the graph's roots, which is what--all-targetsbuilds.Before readings on
8210a6d7, 12:12 to 12:14Z, to compare after the promote: database 1.01 cores and throttled in 20% of its periods over 30 minutes; server 2.77 cores, 35.8 GB; the old scope read active in 2 of 12pg_stat_activitysamples five seconds apart.What the restart will cost, from earlier readings: about four seconds for the fill, and every unit graph resolved again once under parse version 9 (after
91b2c84d430 graphs were wanted at once, 9 passed 120 s, all resolved within about seven minutes).If main's head is green on testing and nobody has promoted it or landed more by 13:00Z, I promote it and read the restart here.
Update 12:11Z 2026-11-13: the step's fill measured on production: 4.1 s. Its SELECT, run once read-only with EXPLAIN ANALYZE and the INSERT left out: a parallel hash join of
entries(1,207,993 rows, 3,073 MB) withresult_latest(740,169 rows, 785 MB), 34,029 distinct sets, 11,511 rows after the newest eight per check.migrateruns it under its own statement timeout before the lead, so a promote of main's head adds about four seconds to that restart. Main is green (ebf9fb40, t's board: no known failure) and production is on8210a6d7, where the database is still throttled in 14 to 19% of its CPU periods (56 to 85% before8210a6d7). If nobody has promoted main's head by about 12:30Z I will, and read the restart, lock waits oncheck_readsand the database's CPU here.Update 11:46Z 2026-11-13: the red test is fixed on main as
11715002. Nobody had claimed it on t's board, so I did (11:37Z). The change is the test's last assertion only: it acceptsrows=9600.00 loops=1besiderows=9600 loops=1, both still withloops=1, so the planner's estimate cannot satisfy it. On testing with the fix: that test forced 3 of 3 passed (4 of 4 failed without), the whole check set 8 passed, none cached.e1a2ecbbitself is untouched.Update 11:37Z 2026-11-13:
e1a2ecbbfails its own new test in t's CI on testing, every time. Head runr3c72383e4fthere: 14 passed,test/tfailed onjobs::cache::read_sets::tests::what_checks_read_is_read_from_its_own_rows; run alone from a clean checkout ofe1a2ecbb, forced, it failed 4 of 4. The plan is the one the test wants (onlycheck_readsis read, 9,600 rows). What fails is the last assertion's text match: it looks forrows=9600 loops=1, and this PostgreSQL prints the actual rows with decimals,rows=9600.00 loops=1(read_sets.rs:805; the panic's plan line readsSeq Scan on check_reads ... (actual time=0.029..3.770 rows=9600.00 loops=1)). Matching the row count without the trailingloops=1, or both spellings, would make it hold on both versions. Main's head is red in t's own CI until then; production stays on8210a6d7.Update 11:30Z 2026-11-13:
e1a2ecbbon main answers the read's own cost. It keeps what a check read with its verdict incheck_readsand reads a scope by the check's name, so no call scansentriesany more; the shared read for askers of the same checks fromebbad1e3stays in it. Not on production yet (8210a6d7is). When it is promoted I will read the one-off fill at the schema step, scope reads cancelled after restarts, and deadlocks on the new table, and note them here.Live, 2026-11-13 07:07Z. Production serves
ebbad1e3since 07:04:46Z (promoted by me). 29 people's runs were open at that restart, 20 of them with a base and no ad-hoc command, each asking the scope again. The database's log from 07:04:30Z to 07:06:14Z holds no error at all: none of these statements cancelled by the timeout, where the restarts of 02:42Z, 04:44Z and 06:01Z had 16, 11 and 15. One restart, so one observation. The read's own cost stands as the open question.Update, 2026-11-13 06:54Z. The sharing is on main as
ebbad1e3("scope: askers of the same checks at once share one read of what they read").reads_of_checkskeeps the reads under way by their ids, sorted and deduplicated; the first asker starts the read as a task of its own and every asker of the same checks meanwhile is given its answer or its error (over the read's own chain, sodb::transientstill tells a transient one). An asker that goes away leaves the read to the others; the entry goes as the read ends, whichever way; nothing is kept past it. Five tests in src/jobs/cache/read_sets.rs; with the sharing off, 16 askers made 16 reads. The whole check set ran green on testing (run re55d186d3c). Not on production yet; after it is, the count to watch is these statements cancelled by the timeout in the database's log in the minute after a restart.The design question at the end, the read's own cost, stands as written.
Seen on t.tilo.so on 2026-11-13. A measurement and a first, exact relief; the read's own cost is left open at the end.
What the database's log says
The statement of
CacheServer::reads_of_checks(src/jobs/cache/read_sets.rs),was cancelled by the 30 s statement timeout 42 times between 02:42Z and 06:02Z, all of them in three bursts about 40 s after a restart of the server: 16 from 02:42:53Z, 11 from 04:45:01Z, 15 from 06:01:56Z. The server logged no warning for any of them.
What it walks, for the 582 checks of one tilo plan (run once by hand at 06:14Z, 17.6 s on a database with nine other active sessions):
result_latest(740,000 in all)entriesby keyBy the verdict rows' age: under a day 53,664 (44,055 with an entry); one to three days 92,156 (17,699); three to seven days 130,418 (none); over a week 161,819 (none). So two thirds of the probes are of verdicts whose entries are long gone. The planner expects 3,698 rows.
Who asks
runs::scope::changed_against, for a baret testpicking its checks, fort scopeandt suggest, and for every person's run with a base and no ad-hoc command, which asks at its start what opt-in checks its change leaves (opt_in_left, a task of its own). 110 such runs were created in the last hour. At a take-over every open one of them asks again at once: the bursts are 11 to 16 copies of one 17-second statement over the same checks, started together on a database that is at its busiest, and all of them run past 30 s. That is also what the two baret testruns of #54 ran into.What I do (a developer of mine)
Askers of the same checks at the same time share one read: one statement in flight per list of checks, its answer or its error given to every asker waiting on it, nothing kept once it has answered. Fifteen statements at a take-over become one, and nothing an asker is told changes.
Left open, for a design that I would rather agree than impose
The read itself: 17.6 s and 436,000 rows to learn 26,000 pairs of check and read set, on every such run. Bounding it by the verdicts' age is not exact from what the tables say (the oldest stored entry is 106 h old, though no verdict older than three days has one), and each check's newest 200 verdicts reach 98% of the pairs, not all. What would make it cheap and exact is the pairs kept where verdicts are recorded and entries removed, or a memo per check filled once and extended by the verdicts recorded since. Either changes what
t testalone may select if it is wrong, so it wants a proof or a comparison kept beside the old read first.