Skip to content

ci(nvim): measure wall-clock time around the startup benchmark - #44

Merged
potsrevennil merged 4 commits into
masterfrom
ci/nvim-startup-wall-clock
Aug 14, 2026
Merged

potsrevennil merged 4 commits into
masterfrom
ci/nvim-startup-wall-clock

Conversation

@potsrevennil

Copy link
Copy Markdown
Owner

Summary

Follow-up to #41. The CI benchmark reported dramatically higher numbers than the same builds run locally (e.g. macos-14 median ~300ms, up to 544ms, vs. ~25ms locally for the identical nix-built package). nvim --startuptime only instruments Lua/vimscript execution — it can't see process spawn, dynamic-linker resolution of nvim's own .dylib/.so dependencies, or macOS Gatekeeper/AMFI scanning freshly-downloaded nix-built (unsigned/ad-hoc-signed) binaries on a runner that's never seen them before. That's the leading hypothesis for the gap, but it needs to actually be measured on the CI hardware to confirm.

This adds:

  • An outer wall-clock timer (time) around the whole 10-run benchmark, printed alongside nvim's own internal mean, so we can see if the gap is pre-Lua process-launch overhead.
  • Per-run timings (not just aggregate min/median/mean/max), to see whether the cost is front-loaded (cold-start/Gatekeeper tax that amortizes across the 10 runs within a job) or uniform every run.

No change to what's being measured for the config itself — purely diagnostic, to decide what (if anything) is actually actionable here vs. CI-environment noise.

Test plan

  • nix develop .#ci lint suite passes
  • nix flake check --all-systems passes
  • Verified TIMEFORMAT/time wrapping and per-run output locally
  • Check the next CI run's summary: is wall-clock >> nvim's internal mean? Is per-run time front-loaded or uniform?

🤖 Generated with Claude Code

nvim's own --startuptime only instruments Lua/vimscript execution, so
it can't explain why CI's numbers (up to 500ms+ on macos-14) are far
higher than the same builds run locally (~25ms) -- that gap has to be
happening before Lua even starts: process spawn, dynamic linker
resolving nvim's own dylib/so deps, or macOS Gatekeeper/AMFI verifying
freshly-downloaded nix-built binaries on a runner that's never seen
them before.

Wrap the benchmark with the shell's `time` builtin for an outside-in
wall-clock figure to compare against nvim's internal mean, and print
each run's individual time (not just aggregate stats) to see whether
the cost is front-loaded (cold-start/Gatekeeper tax amortizing across
the 10 runs) or uniform across every run.
Without a cache, "Restore plugins" does a full network git clone of
all ~40 plugins on every single run, so the benchmark that follows
always starts from a cold filesystem. Cache ~/.local/share/nvim/lazy
keyed on runs-on (native build output like telescope-fzf-native's is
arch-specific) and lazy-lock.json's hash, so a cache hit skips the
clone entirely.

Also corrects the comment above the benchmark step: the wall-clock
measurement added in the previous commit shows the pre-Lua gap is
small (~5-40ms/run) on both platforms, not the dominant factor -- the
100-600ms CI readings are real Lua/vimscript execution time, most
likely from lazy.nvim's spec-resolution work getting hit by
contention on weak/shared runners (worst on macos-14), evidenced by
erratic non-monotonic per-run timings rather than a clean cold-cache
warm-up curve.
…rmed

Verified on a real pull_request-scoped run: caching lazy.nvim plugins
alone took every matrix entry from 100-600ms down to ~20-27ms, matching
local numbers almost exactly, with the erratic per-run spread gone too.
That confirms the actual cause was cold disk reads for freshly-cloned
plugin files landing inside nvim's own require()/sourcing timings --
not CPU contention on shared runners, which was our working theory
before this data came in.
@potsrevennil
potsrevennil marked this pull request as ready for review August 14, 2026 09:27
@potsrevennil
potsrevennil merged commit 1a622a9 into master Aug 14, 2026
5 checks passed
@potsrevennil
potsrevennil deleted the ci/nvim-startup-wall-clock branch August 14, 2026 09:28
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