Repository navigation
Conversation
add_variables_from_file compiled every variable file again for each new system, so each system got new code objects for the same source. Coverage's sys.monitoring core keeps every code object alive, so it retained every system a process built. Each file is now compiled once per version (path, mtime, size) and the code object runs in each system's own module, so systems keep their own modules, classes, functions and globals. Fixes #607 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r file Review of ef07ed6: a cache keyed by path, mtime and size served stale code after an edit that kept both (or a symlink retargeted to a file with the same metadata); two threads missing at once could publish different code objects; and old versions were never evicted. The cache now maps each absolute path to the SHA-256 of the source it compiled and the code, filled under a lock and compiled from the bytes it hashed (about 0.07 s of CPU for all 1,110 policyengine-uk variable files, once per process). The changelog no longer implies the variable modules stop being retained (#520). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ests Opus delta review of db9182b: - Code compiled with the caller's spelling of the path, so a relative path gave relative co_filename and error file names (exec_module uses the loader's absolute path), and the cache kept whichever spelling came first. The read, key and compile now all use the loader's absolute path. - A child forked while another thread held the lock would deadlock; the lock is re-created after fork. - The thread test passed when every load raised and could not see a missing lock under the GIL. It now uses a loader that counts and sleeps in each compile, collects thread errors, and asserts one compilation. - The eviction assertion could not fail; it now checks the stored digest and that the old code object is gone. - New Hypothesis test (own file, importorskip like the repo's other property tests): any sequence of writes and loads returns the current content's code under the absolute path, the same object until the next write, and only the latest version is cached. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… fork reset Opus confirmation review of ba633db (approved) left nits: the counting loader's class counter wasn't reset, so a rerun of the thread test failed; the property test leaked cache entries when an example failed; nothing tested the lock's reset after fork (a POSIX test now forks while holding it and checks the child's lock is free); and the comment now says the path is absolute and normalized rather than as exec_module spells it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
So an error in the child can never return it to pytest to run the rest of the suite while the parent waits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
October 11, 2026 21:45
Contributor
Author
|
Hand-off to the US + core hub (session "Cut peak memory of pe-uk CI test shards").
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #607
Change
add_variables_from_fileusedspec.loader.exec_module, which compiles (or unmarshals from.pyc) every variable file again for each new system. It now runs a code object from a module-level cache in the new system's own module. The cache is keyed by the file's absolute path (the loader's path, asexec_moduleuses) and holds the SHA-256 of the source it compiled and the code object. It is filled under a lock, from the same bytes that were hashed (loader.source_to_code).sys.modules, and its own classes, functions and globals. Only the immutable code object is shared.Why: coverage's
sys.monitoringcore (coverage's default on Python 3.14) keeps every code object it has seen alive. So it held a new copy of every variable file's code for each system a process built. In policyengine-uk's test shards that grew the four workers to 15.3 of 15.6 GiB (PolicyEngine/policyengine-uk#2330). PolicyEngine/policyengine-uk#2331 works around it in the tests until this ships.Cost
Measured on the 1,110 policyengine-uk variable files (1.2 MB), loader work only, CPU medians. The Opus review measured these on a loaded host.
.pycfiles.pycfiles.pycfiles.pycfilesSo a process that builds one system pays about 0.07 s more CPU at start-up, because variable files'
.pycfiles are no longer used. A process that builds several pays less per later system.My earlier figure of "0.180 s instead of 0.289 s per UK system" was measured with
PYTHONDONTWRITEBYTECODE=1in a checkout with no__pycache__for the variable files, so it is the no-.pyccase.This doesn't change #520: the variable modules still stay in
sys.modules.Invariants (tests)
In
tests/core/test_variable_code_sharing.py:compile()of its current source, under its absolute path (co_filenamechecked separately, since code equality ignores it).In
tests/core/test_variable_code_sharing_property.py, a Hypothesis test: for any sequence of writes and loads, every load returns the current content's code under the absolute path, the same object until the next write, and only the latest version is cached.Review
GPT-6.1 Sol reviewed ef07ed6 and requested changes (4 findings); db9182b fixed them.
An Opus 5.5 delta review confirmed those fixes and requested 5 smaller changes:
co_filenamespelling;ba633db makes all five.
An Opus confirmation review approved ba633db (
review-core-608-opus-final-out.md). Its nits are in f52aefa: the counter reset, the property test'sfinally, a fork test, and the comment wording.The same reviewer approved f52aefa (
review-core-608-opus-f52-out.md) and asked for one hardening: the forked child exits in afinally, as intest_data_storage_dir.py. That is 847fe46, which the reviewer said keeps the approval.Reviews are in
~/reviews/uk-ci-test-memory-2026-10-11/review-core-608-*.Checks
uv run --with hypothesis pytest tests: 2,509 passed, 5 skipped, 3 xfailed (Python 3.14t, local, on master 8fdf59e).policyengine-core test policyengine_core/country_template/tests -c policyengine_core.country_template: 39 passed.ruff format --check .: clean.axiom: n/a: core infrastructure
🤖 Generated with Claude Code