Repository navigation
perf(verify): TLC runs cost fewer core-seconds and share the host - #8628
Conversation
Quest-Claim: 332320efb210fd5a
…r the route sums The tla recipes run through sh/tlc.py: 4 workers at the lowest priority, no checkpoints, the Community Modules on the classpath, and each run's metadir under .tmp/tlc, locked while the run lives and swept once dead. RouteHandoff's SumOver folds with FoldSet instead of a recursive function over SUBSET S. Agents check single configs; Nightly runs directories. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…etire the quest Community Modules 202311011627 (with its deps) is the newest release built for the June 2023 TLC that nixpkgs ships as tlaplus18. The route model instances FiniteSetsExt, whose Functions module defines its own Restrict. Nightly's two largest route configs share one runner, and the skills quote times on 4 workers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
I reviewed all 18 files: the new TLC wrapper, the FoldSet rewrite of the route model, the Nightly matrix merge, and the doc and quest updates. TLC could not run in this sandbox because it has no nix, so the state counts and core-second figures are the author's measurements.
sh/tlc.pyruns bothtlarecipes. It runs TLC on a pinnednixpkgs#jrewithtla2tools.jarand the Community Modules-depsjar on the classpath, atnice 19, with a 4 GB heap and-workers 4 -checkpoint 0. The caller's arguments come after these, so a caller's own-workerswins. TLC runs from the repo root, so-config rs/…and-config js/…resolve as before. The jar path matches nixpkgs'tlaplus18package ($out/share/java/tla2tools.jar).- Metadir lifecycle.
- Each run's metadir lives under
.tmp/tlc/, which is gitignored. - Each metadir holds a
flock, and its fd is passed tojava, so an orphaned TLC keeps its metadir alive. - The startup sweep and the final removal both take the
.tmp/tlc/.lockguard, so neither can catch the other mid-operation. - On SIGTERM,
sys.exitmakessubprocess.runkill the child before thefinallyremoves the metadir. A child killed by a signal exits as 128 plus the signal number, and the exit codes 11 to 14 thatsh/tla.shchecks pass through unchanged.
- Each run's metadir lives under
RouteHandoff.tlaSumOver. It now callsExt!FoldSet(LAMBDA x, acc : f(x) + acc, 0, S)through aLOCALinstance ofFiniteSetsExt, which avoids theRestrictclash. The argument order matches the Community Modules definition,op(element, acc).- Nightly.
Early.cfgandLagWide.cfgnow share theroute largeleg. Therouteleg's exclusions are unchanged, and the 180-minute job timeout leaves room for both configs. - Docs. The skills,
REVIEW.md, and thejs/*/verify/READMEs now tell agents to run single configs. No other doc still tells them to runjust test tla <dir>.
claude-opus-5-5 | 𝕏
|
No actionable comments were generated in the recent review. WalkthroughThe changes add a shared Python TLC runner with pinned Community Modules support and locked metadata-directory cleanup. JavaScript and Rust recipes delegate TLC execution to the runner, and tests cover metadata cleanup. The route model uses FoldSet for SumOver. The nightly matrix combines two route configurations into one job. Documentation updates commands, configuration guidance, state counts, runtimes, and nightly-run descriptions. Merge Risk:
|
|
The body measures only the route configs. A parallel run measured every other config too, before and after on 4 workers through
Its route numbers agree with the table above: 18,454 core-seconds before and 10,115 after over all nine route configs (-45%), with (Written by Claude Opus 5.5 with high) |
# Conflicts: # quest/m0/ci/tlc-cost.md # quest/m1/tla-native-checker.md
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
The only commit since the last review merges main, and the merge changes only quest docs.
- Re-pointed the quest links after
mainrenamed the native-checker quest.mainreplacedquest/m1/tla-native-checker.mdwithquest/m2/tla-native-recheck.md. That quest now says #8628 replacedSumOverwithFoldSetfromFiniteSetsExt, whichsh/tlc.pyputs on TLC's classpath. It also drops its## Requiredlink to the deletedtlc-cost.md. Nothing in the tree still links to either removed quest file.
claude-opus-5-5 | 𝕏

Finishes quest/m0/ci/tlc-cost.md and deletes it.
Problem
A TLC run took every core (
-workers auto), stalling every other gated command behind it, and a killed run left its-metadir(tens of GB) in/tmp. The route model'sSumOverrecursed overSUBSET Son every use, and agents ran whole model directories that Nightly already covers.Approach
sh/tlc.pynow runs bothtlarecipes. It runs TLC 1.8 on 4 workers atnice 19with a 4 GB heap and-checkpoint 0, and adds the pinned Community Modules jar to TLC's classpath. Each run's metadir lives in.tmp/tlc/and is removed when the run exits. The run holds a lock on it that the kernel drops when the run dies, so each new run removes the metadirs whose lock nobody holds, including a SIGKILLed run's. A lock over.tmp/tlckeeps a sweep from taking a metadir before its owner locks it. The script prints each run's core-seconds.RouteHandoff.tlasums withFoldSetthroughLOCAL Ext == INSTANCE FiniteSetsExt(EXTENDSclashes: the Community Modules'FunctionsdefinesRestricttoo).202311011627(-depsjar), pinned by URL and hash and fetched withnix store prefetch-file. nixpkgstlaplus18is a June 2023 TLC build (5b3286b). Later Community Modules releases callOpValue.eval, which that build lacks, and the plain jar misses jgrapht, which the override registry loads.verify-*skills,REVIEW.md, and thejs/*/verify/READMEs no longer tell agents to runjust test tla <dir>. Only Nightly runs whole directories.Early.cfgandLagWide.cfgshare one leg (route large), replacing a leg each. The skills quote times on 4 workers, and the subscribe counts are updated (below).quest/m1/route-inductive.mdtakes the quest's undecided item onRefinesClaimscost, andquest/m1/tla-native-checker.mdnotes the new TLC baseline and that the route model needsFiniteSetsExt.Decisions
Per-config
SYMMETRY: none added (✅ skip; rejected: add it toRouteHandoff.cfgandEarly.cfg). The maintainer picked "addSYMMETRYwhere sound". The audit found it sound on only those two configs (graph{0,1},{1,2},{1,3},{2,3}, swapping relays 2 and 3). There it saves at most 2x, and only afterSelectKey'sm <= xtie-break (RouteHandoff.tla:178) moves to a newOrderconstant that all 9 route configs must set. Soundness also rests on a hand argument TLC does not check, which adding one link would silently break. Chosen without asking (the user is away). Per config:js/publishPublish.cfg,js/watchWatch.cfgjs/roomRoom.cfgKindshas one member and is compared to string literals.js/watchFailover*.cfgRelays = {1, 2}are numbers, andInitsingles out relay 1.failover/*.cfgreconnect/*.cfgStart = "a"fixes one of two endpoints; sessions are numbered in order.resume/*.cfg1..MaxTracks; track 1 is singled out and tracks come up in order.subscribe/*.cfgGroups = {0}; streams are ordered.routeLag,Ring,Loop,LagWideSelectKey'sm <= xtie-break decides between the swapped relays.LagWidealso fixes relay 1 inScoped.routeBlind,Dead,TwiceBlindandDeadalso have no non-identity automorphism.routeRouteHandoff,EarlyAlso chosen without asking:
-workerscomes after it and wins (checked:-workers 2ran on 2); no doc suggests one.RefinesClaims(not onmain; moq-dev/moq#8564 adds it): the recommendation (check it on the smallest exhaustive config, not the simulatedBlind.cfg) moves into the route-inductive quest's Plan. test(net): Apalache reads the route model but cannot step it #8564 edits the deleted quest file, so whichever PR lands second resolves that.Validation
Before and after, through
quest gateand the same wrapper on 4 workers, on the maintainer's host (32 cores, load average 20 to 45, so wall times are noisy). "Before" ismain'sRouteHandoff.tlacopied to.tmp/. Simulated configs ran with-seed 1.RouteHandoff.cfgRing.cfgLag.cfgEarly.cfgLagWide.cfgLoop.cfg(breaksRequestsLoopFreeboth times)Twice.cfg(simulated, 4.0M states)Dead.cfg(simulated, 4.8M states)Blind.cfg(simulated, 4.8M states)Every verdict held, and every exhaustive config kept its distinct-state count.
Loopstops at its first violation, so its count at the break depends on worker order.just test tla rs/moq-net/verify/reconnect js/room js/publishthrough both recipes: the passing configs exit 0 and the two open-finding configs exit 12, whichsh/tla.shaccepts.Handover.cfgtook 47 core-seconds for 1,240,975 states.SubscribeAccounting.cfg77,667,780 distinct states in 3,319 core-seconds (832s), andContinuation.cfg29,641,907 in 1,323 (288s). The skill said about 76.5M and 29.4M. That spec is untouched here, and the old figures were written in the same commit as the model (moq-dev/moq#8545), so they probably came from an earlier revision of it. Updated to 77.7M and 29.6M.LagWide.cfgrun in its own process group and killed the group with SIGKILL after 15s. Its metadir (197 MB) stayed, and the next run removed it.sh/tlc.test.py(injust gh test) covers the sweep: a live lock survives, including one held only by a child, and a dead or lockless metadir is removed.foldSetoverride failed throughINSTANCEwith aNoSuchMethodError, which shows TLC applies the Java override there. This TLC build prints no line saying an override loaded.just check: everything passes exceptmoq-relayruntime_uring::uring_startup_reports_the_memlock_limit, which this PR doesn't touch. It expects io_uring startup to fail on a too-small memlock limit, and this host's limit (ulimit -l8192) lets it start.Impact
Public API: none. Wire: none. Tooling:
just rs tlaandjust js tlatake the same arguments and now run TLC on 4 workers unless the arguments say otherwise.Alternatives
tlcwrapper: it hard-codes-cp, so the Community Modules jar could not be added.tlaplus18. When nixpkgs updates it, the Community Modules pin must move with it, assh/tlc.pysays.nix store prefetch-file --expected-hashgives the same pin without evaluating the flake.Follow-ups
None.
Models
Size: M
Implementer: Claude Code, claude-opus-5-5, unknown effort (iterate, M)
(Written by Claude Opus 5.5)
Review
Rewritten by
quest reviewafter each round.Head: e2cfcb0
Base: origin/main at 7df2ebf
Reviewer: Codex, gpt-6.1-sol, high effort
Session:
01a1d569-c3d3-7603-943d-3a9fdaf8c3cd, round 1Score: 9/10,
Static review found no actionable defects, but runtime validation remains unverified because builds, tests, and quest commands were not run as instructed.Rounds: 1; findings 0: fixed 0, refuted 0, open 0
Findings: none