Compile module init files in background to increase startup speed#2144
Open
TrevorBurnham wants to merge 1 commit into
Open
Compile module init files in background to increase startup speed#2144TrevorBurnham wants to merge 1 commit into
TrevorBurnham wants to merge 1 commit into
Conversation
Extends the existing zlogin zcompdump pattern to also precompile the top-level init.zsh and every loaded module's init.zsh (or .plugin.zsh, matching pmodload's resolution order). Subsequent shells source wordcode instead of reparsing. Current shell pays no cost (backgrounded via &!) and does not benefit from its own compile. Reuses the mkdir-based lock from the zcompdump block (commit e50b93c) to serialize concurrent compiles across simultaneous login shells. Both lock sites now sweep lock dirs older than 5 minutes before attempting mkdir, so a killed shell (SIGKILL, OOM, power loss) can no longer permanently disable recompilation. Gated by zstyle ':prezto:load' zcompile, default on via zstyle -T. Modules are enumerated under modules/, contrib/, and any pmodule-dirs; compilation is restricted to entries with loaded=yes (set by pmodload on successful source). Measured on a typical config: pmodload total 81.5ms -> 55.1ms (-32%), compinit 7.2ms -> 3.7ms (-49%). Partially addresses sorin-ionescu#1418.
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 #1418
This PR uses
zompileto precompile the top-levelinit.zshand every loaded module'sinit.zsh(or<module>.plugin.zsh).Context
#1418 asked for
zcompilesupport in Prezto. PR #2028 partially addressed it by compiling thecompinitdump. The remaining parse cost sits inpmodloadsourcinginit.zshfiles. Zsh auto-prefers a.zwcwhen newer than the source, sosourcecalls transparently upgrade to wordcode loads once the files exist.Benchmarks
zprof(averaged across multiple runs) with the modulesenvironment,syntax-highlighting,history-substring-search,osx,autosuggestions,completion,directory,history,prompt(pure theme),spectrum,terminal:pmodloadtotalpmodloadselfcompinitChanges
runcoms/zloginto precompile init modules in the background, alongside the existing zcompdump compile..zwc.lockdirectories (older than 5 minutes) beforemkdir, in both the existing zcompdump block and the new module-compile block, so a killed shell can no longer permanently disable recompilation.runcoms/zpreztorc:zstyle ':prezto:load' zcompile 'no'to opt out. Default is on (zstyle -T).Design notes
Where: a second
{ ... } &!block appended after the existing zcompdump compile inruncoms/zlogin. Login-shell cadence is right — these files only change onzprezto-update/git pull, not between shells. Integrating intopmodloadwould paystat+ lock cost on every interactive shell includingexec zsh; the zlogin placement doesn't.What gets compiled:
$ZPREZTODIR/init.zshmodules/,contrib/, and any userpmodule-dirswherezstyle -t ":prezto:module:$name" loaded 'yes'succeeds (set bypmodloadon successful source,init.zsh:136): the module'sinit.zsh, falling back to<module>.plugin.zsh— same resolution order aspmodload.external/directories are skipped; third-party submodules are not Prezto's to compile.Concurrency: per-target
command mkdir "${target}.zwc.lock"/rmdir, matching the existing zcompdump pattern (commite50b93c, PR #2028). Verified with 8 parallel login shells: all.zwcfiles produced, zero leftover locks.Stale-lock recovery: both blocks now sweep
.zwc.lock(N/mm+5)— any lock directory older than 5 minutes isrmdir'd before themkdirattempt. Without this, a SIGKILL / OOM / power loss betweenmkdirandrmdirwould leave a lock dir that permanently blocks future compilation (silently — no error, no retry). The sweep is applied to the existing zcompdump block too since the hazard exists there as well.Correctness details:
[[ ! -s "${t}.zwc" || "$t" -nt "${t}.zwc" ]]triggers regeneration whenever the source is newer.git pullupdates mtimes, so upgrades invalidate correctly.zstyle -Ttreats unset as true, giving default-on behavior without forcing users to touch.zpreztorc.$0/${0:h}still resolve to the original source path whensourcereads a sibling.zwc—ZPREZTODIR=${0:h}atinit.zsh:168continues to work. Verified.completion/init.zshexiting onTERM=dumb) compile correctly — the early return is expressed in the bytecode.zcompilestderr is not suppressed; parse errors surface on the first post-update login so users can diagnose them, rather than silently never-producing a.zwc.Verification
Tested on macOS 15.4 / zsh 5.9. All scenarios pass:
rmall.zwc, log in, new shell produces 14.zwcfiles (1 top-level + 13 module wrappers including transitive deps). No leftover locks.touch modules/history/init.zsh, log in twice,.zwcmtime refreshed to match source.zstyle ':prezto:load' zcompile 'no', log in, no.zwccreated..zwc.lockdated 10 minutes ago, log in, lock is swept and.zwcproduced. (A fresh lock is correctly respected.)chmod -wa module dir, log in, shell init completes cleanly;zcompilefailure is visible in the terminal (user can diagnose) but does not block startup..plugin.zshfallback — synthetic contrib module with only a.plugin.zshis correctly compiled.