perf(nix): cache nix version info on disk by mikeland73 · Pull Request #3020 · jetify-com/devbox · GitHub
Skip to content

perf(nix): cache nix version info on disk - #3020

Merged
mikeland73 merged 2 commits into
mainfrom
mikeland73/perf-nix-version-cache
Oct 26, 2026
Merged

mikeland73 merged 2 commits into
mainfrom
mikeland73/perf-nix-version-cache

Conversation

@mikeland73

Copy link
Copy Markdown
Collaborator

Summary

Implements item 1 of specs/perf-improvements.md.

Every devbox command calls nix.Info() (via EnsureNixInstalled, nix.System(), telemetry, etc.), which runs nix --version --debug (~90ms). The result was only cached per process. This persists the parsed Info under $XDG_CACHE_HOME/devbox/nix-info/ using the existing filecache helper.

Cache key: resolved nix binary path (symlinks followed, usually an immutable /nix/store/... path) + command args (incl. ExtraArgs) + env vars that affect Nix's config (NIX_CONF_DIR, NIX_CONFIG, NIX_USER_CONF_FILES, XDG_CONFIG_HOME, XDG_CONFIG_DIRS, HOME, NIX_STORE_DIR, ...).

Invalidation: each entry stamps (mtime + size) the nix binary and every config file --debug reports — the system nix.conf and every user config path, including ones that don't exist yet, so creating one invalidates too. Entries also expire after 24h as a backstop for changes the stamps can't see (e.g. files pulled in by include in nix.conf). Failures are never cached, and the in-process infoOnce is unchanged.

Also: Package.IsEnabledOnPlatform now returns true early when a package sets neither platforms nor excluded_platforms, so the common case never looks up nix.System().

Timing

devbox global shellenv with the project already up to date, DO_NOT_TRACK=1, 15 runs each:

binary median
main 85.8ms
this PR 16.2ms

Apart from the debug timer lines, the output matched main exactly.

Testing

  • New nix/infocache_test.go uses a fake nix script and checks: a cache hit skips nix, editing nix.conf invalidates, creating a previously missing user config invalidates, changing NIX_CONFIG changes the key, and failures aren't cached.
  • go test -race ./nix/... ./internal/nix/... ./internal/devconfig/... pass
  • golangci-lint reports 0 issues and gofumpt -extra is clean

🤖 Generated with Claude Code

Every devbox command runs `nix --version --debug` (~90ms) to get the Nix
version and system, and the result was only cached per process. Persist
the parsed Info under the XDG cache dir so later commands can skip it.

The cache key is the resolved nix binary path, the command arguments,
and the environment variables that affect Nix's config. The entry also
stamps (mtime + size) the nix binary and every nix.conf that --debug
reports, including ones that don't exist yet, so editing or creating a
config invalidates it. Entries expire after 24h as a backstop for
changes the stamps can't see (e.g. nix.conf include directives).
Failures aren't cached.

Also skip the nix.System() lookup in IsEnabledOnPlatform when a package
doesn't restrict its platforms.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikeland73

Copy link
Copy Markdown
Collaborator Author

@claude ptal

@claude

claude Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikeland73
mikeland73 merged commit 30b2b60 into main Oct 26, 2026
28 checks passed
@mikeland73
mikeland73 deleted the mikeland73/perf-nix-version-cache branch October 26, 2026 00:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant