Replies: 2 comments
|
Thanks for the detailed writeup and the benchmarks — but I think the numbers are measuring the wrong thing, and the design has a correctness problem I don't see a way around. Please redo the benchmarks with the precompiled binariesYou're on a Homebrew build. Homebrew compiles mise separately from the official release binaries and does not use our optimized profile — the release builds use LTO and
and
The tell is in your own table: The correctness problemA shell can be started inside an environment mise built for something other than A bash-side guard looking at "same directory, same You could try to catch this by fingerprinting That's the structural issue underneath all of this. Activation gets eval'd into a long-lived shell. Today, when I fix a bug in the fast path, every running shell picks it up on its next spawn, because the decision lives in the binary. A shell-side guard freezes that logic into whatever shell you activated a week ago — multiplied by bash, zsh, fish, pwsh, nu, elvish and xonsh, each hand-written and each subtly different. And the failure mode is a silently wrong environment, which is the worst kind of bug to have in this code path. In the meantimeFor the slow-filesystem cases you linked (#2164, #4327), I'll still consider a PR — but start with the re-benchmark on the official binary, and it needs a concrete answer for the nested-shell case above. If the real number turns out to be small, the right fix is to make process startup cheaper for everyone rather than to avoid the process in seven different shell dialects. AI-assisted — Tool: Claude Code; model: anthropic/claude-opus-5; version: unavailable. |
|
Thanks for the detailed review. You were right on both counts. On the benchmarks: re-ran everything against the official On the design: I agree the shell-side guard isn't viable as proposed. After trying several variants, prompt-exact file-change detection in shell code is only possible by either duplicating invalidation rules into seven dialects (the watch-list protocol from my prototype — exactly the frozen-logic problem you described) or accepting TTL-bounded staleness, which trades correctness for latency in the hottest path. Neither is acceptable, so I'm dropping that direction entirely. The one alternative I could get working: since the cost is process startup rather than detection, ship change-detection as its own tiny dependency-free binary (
So it lands within ~0.5ms of the bare fork/exec floor and saves ~2.9ms/prompt here — but honestly, that's a modest win on already-fast hardware, and it costs a second shipped artifact plus a format to keep in lockstep. Given your point about maintenance and complexity, I lean toward agreeing it's not worth it unless you see value in it for the slower end (Windows/NFS/deep trees where full runs are far more expensive). Happy to share the prototype if useful either way — otherwise closing this out as won't-fix absent interest. AI-assisted — Tool: pi; model: opencode/x-preview-f-free; version: unavailable. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Skip the mise spawn on prompts where nothing changed
Problem
With shell activation, every prompt redraw runs
mise hook-env, even when nothing has changed since the previous one. That's ~13ms per command on an M4 (35ms for full runs; slower disks and system load make it worse). Every machine with mise installed pays this on every interactive command, and in case it's enabled for non interactive shells coding agents pay it on every command they execute — roughly 13 seconds of pure overhead per 1,000 commands.The change detection inside mise is already nearly free. An idle run costs about the same as bare startup:
/bin/truemise --versionhook-env, nothing changedhook-env, full runNearly all of that cost is process startup: loading a 134MB binary to conclude "nothing changed." This lines up with existing reports: #3658 (slow prompt refresh), #6279 (shell startup overhead), #2164 (NFS), #4327 (deep directories).
Environment: macOS 26.6.2, Apple M4, bash 5.3.15, mise 2026.8.10 (Homebrew), hyperfine 1.20.0.
Proposal
Let bash answer "did anything change?" itself and only invoke mise when needed.
After each full run, mise records a few plain shell variables: which directory it configured, when it ran (an mtime stamp file), everything the environment depends on (active configs, templates, tool/trust/data dirs), and a snapshot of all
MISE_*variables. When the hook fires, bash checks those with builtins — same directory, files untouched, env vars unchanged — and skips mise entirely when everything matches. Otherwise it spawns exactly as it does today.flowchart TD H[hook fires] --> G{guard state present} G -->|no| SP[spawn hook-env] G -->|yes| P{same directory as last run} P -->|no| SP P -->|yes| C{anything changed<br>since last run} C -->|no| Z[skip spawn entirely] C -->|yes| SP SP --> R[apply env and record what mise saw]This requires no daemon or watcher process — just one opt-in setting. Detection covers everything the current fast path checks: config edits, trust changes, tool installs, new configs up the tree, manual
MISE_*mutations. Directory changes always get a full run, and missing or oversized state falls back to spawning as it does now.I prototyped this as
hook_env.shell_guardfor bash. Idle prompts went from ~6.6ms to ~0.09ms (~70x faster), with zero spawns across 5,000 consecutive same-directory prompts. Full-run behavior is unchanged.Feedback
Would this be useful as an opt-in while it proves out in bash? And if it holds up, should it become the default? I'm happy to port zsh and fish next if there's interest.
AI-assisted — Tool: pi; model: opencode/x-preview-f-free; version: unavailable.
All reactions