fix(build): speed up build preparation before workers start - #367
Merged
Merged
Conversation
Digest calculation reads every user stage checksum repeatedly, once per image and platform, and each read hashed the whole command list again. On a configuration with hundreds of stapel images this dominated stage determination. The builder now caches a stage checksum after the first read and snapshots the shell configuration it was built from, so a later mutation of the caller's config cannot make execution and the cached checksum diverge. Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
Every remote git mapping materialized a worktree to read the commit, paying a full checkout per commit even though only object reads follow. A worktree is needed solely to resolve submodules, so a commit without submodules now gets a handle backed by the repository objects directly; commits with submodules keep the previous path, including worktree reuse. Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
The ls-remote tag cache held one global lock for the whole map, so a slow lookup against one remote blocked tag resolution for every other remote. The lock is now per cache key: map access stays global and brief, while the network call holds only the entry it fills, and cache refresh behavior is unchanged. Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
Graph calculation prepared git repositories per image and platform: a shallow local clone was checked and unshallowed again for every image, and remote repositories were cloned and fetched strictly one after another. Unshallowing now happens once per graph calculation, and selected remote repositories are prefetched with at most four concurrent tasks, bounded further by --parallel-tasks-limit and disabled without --parallel. Repositories sharing a mirror or reached through a URL alias are fetched once. Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
Collaborator
Author
Verification
Review focus
|
Collaborator
Author
|
The same change is open upstream as werf#7928, where all checks are green (unit, lint, e2e_simple/extra/complex, integration_git/main, all build matrix entries). This branch carries two fork-only differences: the shell config snapshot also clones |
Prefetching selected one ref per storage mirror, so a repository used at several refs had all but the first fetched serially during graph calculation, after the concurrent window had closed. Refs are now grouped by mirror and the whole group is prefetched in one task: refs sharing a mirror stay serialized, as the mirror lock requires anyway, while different mirrors proceed concurrently. Tasks are handed out dynamically, so a worker that finishes a small mirror picks up the next one instead of idling on its static share. Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
The handle constructor for a commit without submodules took a context it never used, and the comment on mirror grouping claimed more than GetClonePath actually collapses. Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
Collaborator
Author
alexey-igrychev
marked this pull request as ready for review
September 27, 2026 08:13
alexey-igrychev
added a commit
that referenced
this pull request
Sep 28, 2026
🤖 I have created a release *beep* *boop* --- ## [3.6.1-dk.1](v3.6.0-dk.1...v3.6.1-dk.1) (2026-09-28) ### Features * **sbom:** expose the ISPRAS checker options in sbom validate ([#375](#375)) ([8fe11f0](8fe11f0)) ### Bug Fixes * **build, git:** reuse one ssh connection for git requests ([#368](#368)) ([708a660](708a660)) * **build, git:** reuse one ssh connection for git requests ([werf#7930](https://github.com/deckhouse/delivery-kit/issues/7930)) ([6bf8313](6bf8313)) * **build:** resolve content anchors concurrently in parallel builds ([#369](#369)) ([26d9ae6](26d9ae6)) * **build:** resolve content anchors concurrently in parallel builds ([werf#7931](https://github.com/deckhouse/delivery-kit/issues/7931)) ([39f664f](39f664f)) * **build:** speed up build preparation before workers start ([#367](#367)) ([4e39f88](4e39f88)) * **build:** speed up build preparation before workers start ([werf#7928](https://github.com/deckhouse/delivery-kit/issues/7928)) ([7a188c2](7a188c2)) * **build:** stop per-digest local image scans before image workers start ([werf#7929](https://github.com/deckhouse/delivery-kit/issues/7929)) ([20d74b6](20d74b6)) * **git:** keep a healthy cached worktree on canceled builds ([#374](#374)) ([ed3e5fa](ed3e5fa)) * **git:** keep a healthy cached worktree on canceled builds ([werf#7935](https://github.com/deckhouse/delivery-kit/issues/7935)) ([ad187a4](ad187a4)) * **git:** keep local submodule reuse for nested submodule names ([#371](#371)) ([0e82710](0e82710)) * **git:** keep local submodule reuse for nested submodule names ([werf#7933](https://github.com/deckhouse/delivery-kit/issues/7933)) ([196df14](196df14)) * **git:** rebuild a broken cached worktree instead of failing ([#370](#370)) ([967c83d](967c83d)) * **git:** rebuild a broken cached worktree instead of failing ([werf#7932](https://github.com/deckhouse/delivery-kit/issues/7932)) ([c89fdb6](c89fdb6)) * **sbom:** keep long sbom validate checker messages on one line ([#376](#376)) ([5ec87d4](5ec87d4)) * **storage:** avoid repeated local image scans before builds ([#366](#366)) ([88bf86f](88bf86f)) * **storage:** reuse recent tags listings for stage lookups on cache misses ([#372](#372)) ([fad4fea](fad4fea)) * **storage:** reuse recent tags listings for stage lookups on cache misses ([werf#7934](https://github.com/deckhouse/delivery-kit/issues/7934)) ([d3d0c41](d3d0c41)) ### Miscellaneous Chores * force release 3.6.1-dk.1 ([30bdf77](30bdf77)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
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.
Summary
Most of the time before the first build worker starts went into re-preparing git repositories and re-hashing stapel stage checksums once per image and platform. On a Deckhouse configuration (1122 content-based tag stages, 188 remote repositories) that phase dropped from 26:33 to 4:58 with warm git mirrors; with an empty git cache, remote prefetching takes it from 22:26 to 13:09, and 8:22 together with werf#7930 and werf#7931. Stage digests are unchanged.
What
Fetching originblocks become 1.gitWorktree.forceShallowClone,gitWorktree.allowUnshallowand theshallow git clone is not allowederror are unchanged.--parallel, remote repositories are prefetched before graph calculation with at most 4 concurrent tasks, bounded further by--parallel-tasks-limit;--parallel=falseor a limit of 1 keeps the previous serial order. VERIFIED: git trace2 shows a peak of 4 concurrentfetch/ls-remoteprocesses over 316 started.git ls-remote --tagsagainst one remote no longer blocks tag resolution for other remotes; cache refresh behavior is unchanged.werf.yamlsurface, and nothing changes after workers start.Why
Preparation was scoped per image and per platform instead of per build: every image re-checked and re-unshallowed the same local repository, remote repositories were cloned and fetched serially at the moment their first mapping was generated, and every remote commit read went through a full worktree checkout that only submodule resolution actually needs. On a configuration with over a thousand stages this made preparation longer than the builds it precedes, and the cost grows with the number of images, not with the amount of work to build. A persistent on-disk cache of prepared state was rejected: it would hide the duplicated work behind an invalidation problem instead of removing it.