Skip to content

refactor(lifecycle): walk the overlays of a stage once - #50

Merged
clhodapp merged 3 commits into
mainfrom
perf/walk-once-per-stage
Oct 16, 2026
Merged

clhodapp merged 3 commits into
mainfrom
perf/walk-once-per-stage

Conversation

@clhodapp

@clhodapp clhodapp commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

What changes

A library is built in stages, and each stage composes its overlays with the manifest overlay after them. withManifests rebuilds a stage the same way with more phase manifests filled in, and every module evaluation rebuilds the lib it runs on. So each evaluation resolved the imports of every overlay and walked the entry graph again, although only the manifest overlay differs between builds. mkLib also builds three libraries from the same lib overlays (the one its modules, configs and pkgOverlays functions receive, the one pkgSets receives, and the finished lib), and the list of entries in the manifest came from a fourth walk of them.

compose applies the keyed entries first, in the order its walk finds, and then the keyless entries, in list order. The manifest overlay has no key and is the last entry of a stage's list, so it is always the last overlay applied, and the walk of the other overlays is the same with any manifest overlay. This change reuses that walk:

  • compose returns appendKeyless, which composes its entries with more keyless entries that import nothing applied after them. It reuses the walk of the entries and applies the overlays again. An appended entry with a key or with imports is refused.
  • stage takes its overlays already ordered and builds each version with appendKeyless. The three libraries and the manifest's list of entries share one ordering of the lib overlays mkLib composes.

What a library holds and its layers are unchanged.

Why now

nix-caisson/caisson is adding the two disko integrations. Each added integration is two more entries in every walk, so the integrations put caisson's eval-weight scenario over its ceiling. With this change the scenario is under it again, without raising the baseline.

Measurements

The minimal consumer of caisson's eval-weight scenario, by bytes allocated:

caisson caisson-core main this branch
main 47.17 MB 46.79 MB
with the disko integrations 47.57 MB 47.13 MB

Tests

  • A test checks that appendKeyless gives the lib, the order, the keyless count and the number of layers that composing both lists gives, and that it refuses an entry with a key and an entry with imports.
  • The suite passes (nix eval -f tests summary: 127 tests), and every file parses.

🤖 Generated with Claude Code

A stage composed its overlays with the manifest overlay after them, and
`withManifests` rebuilt the stage the same way. A module evaluation
rebuilds the lib it runs on, so every evaluation resolved the imports of
every overlay and walked the entry graph again, although only the
manifest overlay differs between the builds. The bootstrap, registered
and full stages, and the manifest's `entries`, each walked the same
selection as well.

`compose` now returns `appendKeyless`, the composition of its entries
with keyless entries that import nothing applied after them, which is
where such an entry goes whatever the entries are. A stage takes its
overlays composed and applies them again with each manifest overlay,
and the stages over the selection share one walk.

In caisson's eval-weight scenario the minimal consumer allocates
0.38 MB less (47.17 MB to 46.79 MB).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
clhodapp and others added 2 commits October 16, 2026 00:59
The comments on `stage` and `compose` now give the order compose applies entries in, keyed entries in walk order and then keyless entries in list order, which is why the manifest overlay is always applied last and the walk of the other overlays can be reused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lays is

The comment names the overlays, the three libraries mkLib builds from them and what receives each, in place of "the selection" and "stages".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@clhodapp
clhodapp merged commit dd14868 into main Oct 16, 2026
2 checks passed
clhodapp added a commit to nix-caisson/caisson that referenced this pull request Oct 16, 2026
nix-caisson/caisson-core#50 is merged; the locks move from its branch commit to its merge on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant