`~/.vite-plus/env` costs 85-315 ms per shell start on long PATHs (super-linear `${var#*pattern}` in the dedupe loop)
Los mantenedores suelen responder en 1 día
@jonatankruszewski ya está trabajando en esto.
Desde el 6/10/2026.
- #2905 de @jonatankruszewski — abierto
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 82/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Área
- cli, developer-experience, performance, tooling
Línea de trabajo
La plantilla de entorno POSIX es ENV_TEMPLATE_POSIX en crates/vp_global_cli/src/commands/env/setup.rs. Reemplaza el bucle de deduplicación ${__vp_tmp#*":${__vp_dir}:"} por la reconstrucción con división por IFS indicada en la issue para que el PATH se mantenga lineal en zsh, bash y dash. Inserta la reescritura en el snapshot runner existente de #2494 (sh, bash, zsh) y confirma que el ~/.vite-plus/env generado sigue produciendo el mismo PATH.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
The PATH dedupe loop in the POSIX env script (ENV_TEMPLATE_POSIX in crates/vp_global_cli/src/commands/env/setup.rs, introduced by #2494, shipped as ~/.vite-plus/env) runs
__vp_after="${__vp_tmp#*":${__vp_dir}:"}"
once per occurrence of each vp dir in PATH. ${var#*X} (shortest-prefix removal with a leading *) is super-linear in the offset of X on every POSIX shell I tested. With a PATH of ~8 KB (147 entries, which is what mise activate produces for a user with ~110 globally installed tools) each expansion takes 50-260 ms depending on the shell, and the loop runs twice (bin and fallback-bin).
Because the installer puts . "$HOME/.vite-plus/env" into ~/.zshenv, this is paid by every zsh process on the machine, interactive or not: zsh -c true goes from 0 ms to 180 ms. Every #!/usr/bin/env zsh script, every zsh -c from a tool, every IDE env probe pays it.
Environment: vp v1.0.0, macOS 26 arm64, zsh 5.9 (/bin/zsh) and 5.9.2 (brew), bash 5.3.15 and 3.2, dash.
Repro (zsh, 3 lines)
PATH="$(printf '/Users/me/.local/share/mise/installs/tool-%03d/latest/bin:' {1..140})/x/bin"; tmp=":${PATH}:"; d=/x/bin
typeset -F3 SECONDS=0; a="${tmp#*":${d}:"}"; print "#* : ${SECONDS}s"
SECONDS=0; b="${tmp%%":${d}:"*}"; print "%%* : ${SECONDS}s"
#* : 0.109s
%%* : 0.000s
Measurements
Single ${tmp#*":${dir}:"} on an 8.7 KB PATH, target dir last:
| shell | #* (shipped) |
%% |
|---|---|---|
| zsh 5.9 | 147 ms | 5 ms |
| zsh 5.9.2 | 146 ms | 5 ms |
| bash 5.3.15 | 63 ms | 14 ms |
| bash 3.2 | 53 ms | 13 ms |
| dash | 264 ms | 4 ms |
Cost of sourcing the whole env file in zsh -f as PATH grows (vp dirs present, so the loop runs):
| PATH entries | chars | time |
|---|---|---|
| 20 | 1353 | 4 ms |
| 40 | 2653 | 13 ms |
| 80 | 5253 | 51 ms |
| 147 | 9656 | 172 ms |
| 300 | 19754 | 720 ms |
Whole env file from the real 147-entry PATH, median of 5:
| file | zsh 5.9 | zsh 5.9.2 | bash 5.3 | bash 3.2 | dash |
|---|---|---|---|---|---|
shipped ~/.vite-plus/env |
177 | 178 | 85 | 83 | 315 |
| literal-prefix one-liner (see below) | 6 | 6 | 128 | 133 | 147 |
| IFS-split loop (proposed) | 6 | 6 | 9 | 13 | 5 |
Proposed fix
A literal-prefix strip (__vp_after="${__vp_tmp#"${__vp_before}:${__vp_dir}:"}") fixes zsh but makes bash and dash slower (table above). Splitting PATH on : once and rebuilding it is linear on every shell and produced an identical PATH to the current script in /bin/sh, dash, bash 3.2, bash 5.3 and zsh for a PATH containing both vp dirs, one of them twice:
__vp_bin="$HOME/.vite-plus/bin"
__vp_fallback="$HOME/.vite-plus/fallback-bin"
__vp_new=
__vp_ifs=$IFS
IFS=:
if [ -n "${ZSH_VERSION-}" ]; then setopt localoptions shwordsplit noglob; else set -f; fi
for __vp_p in $PATH; do
case "$__vp_p" in "$__vp_bin"|"$__vp_fallback") ;; *) __vp_new="${__vp_new:+${__vp_new}:}${__vp_p}" ;; esac
done
IFS=$__vp_ifs
[ -n "${ZSH_VERSION-}" ] || set +f
PATH="${__vp_bin}${__vp_new:+:${__vp_new}}:${__vp_fallback}"
export PATH
unset __vp_bin __vp_fallback __vp_new __vp_ifs __vp_p
The snapshot runner from #2494 already exercises the file in sh, bash and zsh, so the rewrite can slot into the same tests.
Who hits this
Anyone whose PATH is long when a nested shell starts: mise/asdf/nix users with many tools, monorepo devs with per-package bin dirs, CI images. A fresh login shell with a 30-entry PATH pays ~4 ms, which is why it is easy to miss.
- Lenguaje dominante
- Rust
- Estrellas
- 6k
- Forks
- 271
- Merge medio
- 1 d 15 h
- PR fusionados (30 d)
- 172
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de voidzero-dev/vite-plus
-
pending triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
voidzero-dev/vite-plus#2892 · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
pending triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
voidzero-dev/vite-plus#2882 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
documentation pending triage
Dificultad 1/5 Menos de una hora Aptitud para principiantes 78/100
voidzero-dev/vite-plus#2875 · 4 comentarios ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
voidzero-dev/vite-plus#2849 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
voidzero-dev/vite-plus#2097 · 10 comentarios · 2 reacciones ·
Los mantenedores suelen responder en 1 día
Todos los issues de voidzero-dev/vite-plus
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
Los mantenedores suelen responder en 4 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
Los mantenedores suelen responder en 1 día
-
Update dusk-bls12_381 to 0.16Posiblemente ocupada @HDauven la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
-
`TcpListenerService` shares one `Extensions` store across all accepted connectionsPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
googlefonts/fontquant#43 ·