¿WSL va lento? Soluciona la E/S de archivos con esta regla

¿Te fue útil?

Cuando WSL es rápido, es aburrido: tus compilaciones se ejecutan, tus tests terminan, los ventiladores del portátil fingen que no están trabajando de más. Cuando WSL es lento, se vuelve personal. Un git status tarda segundos. npm install parece que lleva cada archivo al disco a mano. Empiezas a culpar a “WSL” como concepto, lo cual es como culpar a “las carreteras” por el tráfico.

La mayor parte del dolor en la E/S de archivos con WSL proviene de una herida autoinfligida: estás haciendo cargas de trabajo tipo Linux sobre el sistema de archivos de Windows. Arregla eso y gran parte del “WSL es lento” desaparece.

La única regla: no cruces la frontera del sistema de archivos

Regla: Haz trabajo de desarrollo Linux en el sistema de archivos Linux (/home, /, el VHDX ext4 de WSL). Haz trabajo de Windows en el sistema de archivos Windows (C:\, D:\). No hagas que ninguno de los dos sistemas operativos realice E/S intensiva en el sistema de archivos del otro.

Traducido a comportamiento diario:

  • Clona repositorios en ~/src dentro de WSL, no en /mnt/c/Users/you/src.
  • Mantén node_modules, entornos virtuales de Python, directorios target de Rust, cachés de Go, cachés de Gradle y cualquier cosa que genere miles de archivos pequeños dentro de WSL.
  • Si un editor es nativo de Windows (Visual Studio, GUI de Git de Windows, Node de Windows, etc.), apúntalo a rutas de Windows. Si la herramienta se ejecuta en WSL, apúntala a rutas de WSL.
  • Usa VS Code Remote – WSL (u otra similar) para que el editor hable con los archivos donde corren las herramientas Linux.

Esto no es ideología. Son mecánicas. Cruzar la frontera fuerza capas de traducción, mapeo de permisos, emulación de metadatos y a veces escaneo antivirus en exactamente el patrón más adverso: muchos archivos pequeños y llamadas stat frecuentes.

Un chiste corto, porque somos amigos: WSL no está lento—tus archivos simplemente están yendo al trabajo durante la hora punta.

Por qué la frontera duele: qué ocurre realmente en cada lado

WSL2 es un kernel Linux real dentro de una VM ligera

WSL2 ejecuta un kernel Linux real. Eso es bueno para compatibilidad y para el rendimiento dentro de Linux. Pero también significa que Linux tiene su propio sistema de archivos nativo (ext4) almacenado en un disco virtual (un archivo VHDX) en el lado de Windows.

Dentro de WSL, cuando lees ~/src/app, estás usando la pila normal de sistema de archivos de Linux: caché de páginas, metadatos ext4, búsquedas de inode, caché de entradas de directorio, etc. Es la ruta de E/S que Linux ha optimizado durante décadas.

/mnt/c no es “solo otra carpeta”

Cuando accedes a archivos de Windows desde WSL, normalmente lo haces a través de /mnt/c (o /mnt/d, etc.). Ese camino está respaldado por un sistema de archivos de Windows (típicamente NTFS) y se presenta a Linux mediante una capa de integración especial. Esa capa tiene que traducir:

  • Permisos de archivos de Linux a algo que NTFS pueda representar (y viceversa)
  • Expectativas de sensibilidad a mayúsculas
  • Comportamiento de symlinks y metadatos
  • Notificaciones de sistema de archivos (inotify vs eventos de cambio de Windows)
  • Semántica de rutas y caracteres ilegales

El verdadero culpable es la forma de las cargas de trabajo de desarrollo. Las compilaciones y gestores de paquetes no realizan una gran lectura secuencial. Hacen millones de operaciones pequeñas: stat(), open(), close(), escaneos de directorio, creación de archivos, cambios de permisos. Cada una de esas llamadas puede cruzar la frontera.

Antivirus e indexadores “aman ayudar” en el momento equivocado

Cuando los archivos viven en el sistema de archivos de Windows, Windows Defender (u otra suite de endpoint) puede escanearlos al crear/abrir/modificar. Eso no es una falla moral; es su trabajo. Pero las cargas de trabajo de desarrollo se parecen sospechosamente a malware desde un punto de vista puramente mecánico: miles de archivos de corta duración creados, modificados y ejecutados rápidamente.

Dentro del VHDX ext4 de WSL, Defender no puede enganchar cada syscall de Linux de la misma manera. El modelo de escaneo cambia y la sobrecarga a menudo cae drásticamente.

Docker y los bind mounts pueden duplicar tu dolor

Si ejecutas Docker Desktop integrado con WSL, montar un path de Windows en un contenedor Linux hace que la E/S rebote entre capas: contenedor → VM Linux → sistema de archivos Windows → de regreso. Si montas un path de WSL (ext4 de Linux) en el contenedor, te quedas mayormente dentro de la pila Linux.

Segundo chiste corto (y ya): Si montas /mnt/c en un contenedor, has inventado un nuevo benchmark llamado “tiempo hasta el arrepentimiento”.

Hechos e historia interesantes que explican la rareza actual

  • WSL1 vs WSL2 no es una mera actualización menor. WSL1 traducía syscalls de Linux a syscalls de Windows; WSL2 ejecuta un kernel real en una VM, cambiando el comportamiento de E/S y la compatibilidad.
  • El sistema de archivos de Linux de WSL2 vive dentro de un VHDX. Es un archivo de disco virtual almacenado en Windows, típicamente bajo tu perfil de usuario. El sistema de archivos ext4 de Linux está dentro de ese archivo.
  • Los metadatos entre sistemas de archivos son caros. Las herramientas de Linux llaman a stat() constantemente; mapear metadatos de Windows a semánticas Linux no es gratis, especialmente a través de una frontera de VM.
  • La sensibilidad a mayúsculas tiene una historia diferente. NTFS soporta características de sensibilidad a mayúsculas, pero las herramientas de Windows históricamente asumieron rutas insensibles a mayúsculas. Linux asume sensibilidad. El pegamento de compatibilidad tiene que arbitrar.
  • Inotify es central en pilas de desarrollo modernas. Webpack, Jest, servidores de lenguaje—muchos dependen de eventos del sistema de archivos de Linux. Mapear notificaciones de cambios a través de capas Windows/Linux es notoriamente complicado y a veces lento.
  • Las cargas de muchos archivos pequeños son el peor caso para las capas de frontera. Bases de datos, gestores de paquetes y sistemas de build realizan muchos fsyncs, renombres, archivos temporales y churn de directorio—exactamente lo que las “interop filesystems” odian.
  • La protección endpoint en empresas cambió la ecuación. A medida que la seguridad corporativa se endureció, la sobrecarga de escaneo en el lado de Windows se volvió más notable. El mismo portátil puede “sentirse rápido” o “roto” solo moviendo un repo.
  • El drvfs de WSL tiene opciones sensibles al rendimiento. Configuraciones como el manejo de metadatos pueden cambiar la corrección y la velocidad al usar /mnt/c.

Guion rápido de diagnóstico (encuentra el cuello de botella en minutos)

Si alguien dice “WSL está lento”, no empieces ajustando sysctls oscuros. Empieza por encontrar en qué lado de la frontera están y cuál es la forma de la E/S.

Primero: identifica dónde está el repositorio

  • Si la ruta empieza con /mnt/, asume sobrecarga de frontera hasta que se demuestre lo contrario.
  • Si la ruta está bajo /home (u otra ruta nativa de Linux), la lentitud probablemente esté en otra parte: contención de CPU, presión de memoria, antivirus escaneando el archivo VHDX, patrones de montaje en Docker, o algo patológico en la cadena de herramientas.

Segundo: identifica el tipo de carga de trabajo

  • Muchos archivos pequeños (node_modules, site-packages de Python, git status, ripgrep, indexado de servidores de lenguaje): la sobrecarga de frontera domina.
  • Archivos grandes y secuenciales (procesamiento de medios, checkpoints de modelos): es más probable que estés limitado por el rendimiento bruto del disco o por la CPU.
  • Muchos fsync/rename (bases de datos, gestores de paquetes): capas de corrección y semánticas de sincronización dominan.

Tercero: busca patrones de “doble traducción”

  • Ejecutar herramientas Linux sobre archivos de Windows (/mnt/c)
  • Ejecutar herramientas Windows sobre archivos de Linux (\\wsl$ rutas accedidas intensamente por apps de Windows)
  • Contenedores que montan rutas de Windows en contenedores Linux

Cuarto: mide, no intuyas

Elige un micro-benchmark que coincida con la carga: recorridos de directorio, creación de archivos, git status o un paso de compilación. Compara ruta Linux vs ruta Windows. Si ves un delta grande, la decisión es simple: mueve los archivos o cambia la estrategia de montaje.

Tareas prácticas: comandos, salidas y la decisión que tomas

Estos son comandos reales que puedes ejecutar dentro de WSL. Cada tarea incluye lo que significa la salida y qué deberías hacer a continuación.

Task 1: Confirmar qué versión de WSL estás usando

cr0x@server:~$ wsl.exe -l -v
  NAME            STATE           VERSION
* Ubuntu-22.04    Running         2

Significado: VERSION 2 significa que estás en WSL2 (buen valor por defecto). VERSION 1 se comporta de forma diferente, especialmente para interoperabilidad de sistema de archivos.

Decisión: Si estás en WSL1 y necesitas mejor compatibilidad Linux o mejor comportamiento de sistema de archivos nativo, migra a WSL2. Si tu flujo de trabajo usa principalmente acceso a archivos de Windows, WSL1 a veces puede sentirse menos terrible en /mnt/c—pero es una compensación de nicho.

Task 2: Ver dónde estás (ruta WSL vs montaje de Windows)

cr0x@server:~$ pwd
/mnt/c/Users/alex/projects/myapp

Significado: Estás en el sistema de archivos de Windows vía /mnt/c.

Decisión: Si este repo tiene muchos archivos pequeños (la mayoría los tiene), muévelo a ~/src y vuelve a ejecutar la operación lenta. Espera un cambio radical.

Task 3: Identificar el tipo de sistema de archivos que respalda tu directorio actual

cr0x@server:~$ df -T .
Filesystem     Type  1K-blocks      Used Available Use% Mounted on
C:             9p    487531516 214221812 273309704  44% /mnt/c

Significado: El tipo 9p indica un mecanismo de compartición de archivos paravirtualizado. Este es el camino de la frontera; las cargas de trabajo pesadas en metadatos a menudo sufren aquí.

Decisión: Si ves ext4 bajo / o /home, estás en el sistema de archivos nativo de WSL. Si ves 9p (u otro similar), evita ejecutar builds aquí.

Task 4: Comparar comportamiento de “tormenta de stat” en rutas Windows vs Linux

cr0x@server:~$ time bash -lc 'for i in {1..2000}; do stat /mnt/c/Windows/notepad.exe >/dev/null; done'

real    0m3.214s
user    0m0.103s
sys     0m0.521s

Significado: Miles de operaciones de metadatos en /mnt/c cuestan segundos.

Decisión: Si tu carga se parece a esto (Git, Node, Python), no mantengas el repo en /mnt/c.

Task 5: Ejecutar el mismo bucle de metadatos en el sistema de archivos Linux

cr0x@server:~$ time bash -lc 'for i in {1..2000}; do stat /bin/bash >/dev/null; done'

real    0m0.152s
user    0m0.092s
sys     0m0.054s

Significado: El mismo patrón de syscall, mucho más rápido en rutas nativas de Linux.

Decisión: Usa esto antes/después de mover un repo para probar que el problema es la sobrecarga de la frontera, no que “WSL es lento”.

Task 6: Revisar opciones de montaje para /mnt/c (importan)

cr0x@server:~$ mount | grep " /mnt/c "
C: on /mnt/c type 9p (rw,relatime,dirsync,aname=drvfs;path=C:\;uid=1000;gid=1000;metadata,umask=22,fmask=11)

Significado: Opciones como metadata influyen en cómo se almacenan/emulan los permisos de Linux en archivos de Windows. Algunas opciones mejoran la corrección pero pueden costar rendimiento.

Decisión: Si debes trabajar en /mnt/c, sé intencional con las opciones de montaje vía /etc/wsl.conf. Si no tienes una razón fuerte, no optimices esto—mueve el repo en su lugar.

Task 7: Confirmar que el sistema de archivos de tu distro WSL es ext4

cr0x@server:~$ df -T /
Filesystem     Type  1K-blocks     Used Available Use% Mounted on
/dev/sdc       ext4  263174212 73488328 176211952  30% /

Significado: ext4 es el sistema de archivos nativo de Linux en WSL2. Aquí es donde quieres tu repo y artefactos de build.

Decisión: Si / es ext4, ya tienes el carril rápido. Pon tus proyectos aquí.

Task 8: Encontrar los principales culpables de E/S durante un comando lento

cr0x@server:~$ sudo apt-get update -y >/dev/null 2>&1; sudo apt-get install -y strace >/dev/null 2>&1
cr0x@server:~$ strace -f -tt -T -o /tmp/trace.log git status >/dev/null 2>&1
cr0x@server:~$ tail -n 3 /tmp/trace.log
12:01:11.402033 stat("/mnt/c/Users/alex/projects/myapp/.git/index", {st_mode=S_IFREG|0644, st_size=112394, ...}) = 0 <0.011224>
12:01:11.413901 openat(AT_FDCWD, "/mnt/c/Users/alex/projects/myapp/node_modules", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3 <0.019887>
12:01:11.434022 getdents64(3, /* 256 entries */, 32768) = 8192 <0.028441>

Significado: Las llamadas que tocan /mnt/c tardan decenas de milisegundos cada una. Multiplícalo por miles y obtienes tristeza.

Decisión: Mueve el repo. Si no puedes, reduce el número de archivos (vendorizar, podar node_modules) o cambia el flujo de trabajo para evitar operaciones pesadas en la frontera.

Task 9: Revisar presión de memoria (paging convierte la E/S en melaza)

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           7.7Gi       6.9Gi       214Mi       118Mi       630Mi       356Mi
Swap:          2.0Gi       1.8Gi       220Mi

Significado: Estás bajo presión de memoria y usando swap. Cada operación de archivo compite con el paginado.

Decisión: Cierra la granja de pestañas del navegador, reduce el paralelismo o ajusta los límites de memoria de WSL (vía .wslconfig en Windows) si tu carga realmente necesita RAM.

Task 10: Medir la velocidad de recorrido de directorio donde vive tu repo

cr0x@server:~$ time bash -lc 'find . -type f >/dev/null'

real    0m7.842s
user    0m0.231s
sys     0m1.104s

Significado: Un simple recorrido de directorio que toma ~8 segundos es una bandera roja gigante por sobrecarga de frontera (o un repo enorme, pero lo sabrías).

Decisión: Ejecuta el mismo find después de mover el repo a ~/src. Si baja por múltiplos, has encontrado el cuello de botella.

Task 11: Comprobar si tu repo vive accidentalmente en Windows por confusión de symlink/ruta

cr0x@server:~$ readlink -f .
/mnt/c/Users/alex/projects/myapp

Significado: Incluso si tu prompt de shell parece “tipo Linux”, esto confirma la ruta real de respaldo.

Decisión: Si se resuelve a /mnt/*, trátalo como acceso al sistema de archivos de Windows y espera E/S de metadatos más lenta.

Task 12: Validar que Git está haciendo trabajo extra por semánticas del sistema de archivos

cr0x@server:~$ git config --show-origin --get core.fscache
file:/home/cr0x/.gitconfig    true
cr0x@server:~$ git config --show-origin --get core.preloadindex
file:/home/cr0x/.gitconfig    true

Significado: La caché de sistema de archivos y el preload index de Git pueden ayudar, pero no son mágicos si estás en /mnt/c. Reducen algunas syscalls; no eliminan la frontera.

Decisión: Mantén estos habilitados para repos grandes, pero no los uses como excusa para dejar el repo en Windows. Mueve el repo primero.

Task 13: Comprobar si tu ruta lenta es un bind mount de contenedor desde Windows

cr0x@server:~$ docker info 2>/dev/null | sed -n '1,12p'
Client:
 Version:           26.1.0
Server:
 Containers: 3
  Running: 1
  Paused: 0
  Stopped: 2
 Storage Driver: overlay2

Significado: Docker está presente y probablemente integrado con WSL. Ahora la pregunta es hacia dónde apuntan tus bind mounts.

Decisión: Si tu docker run -v usa rutas /mnt/c, cámbialo a una ruta de WSL (para contenedores Linux) y vuelve a probar.

Task 14: Observar fuentes de montaje dentro de un contenedor en ejecución

cr0x@server:~$ docker run --rm -v /mnt/c/Users/alex/projects/myapp:/work alpine sh -lc 'mount | head -n 5'
overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/...,upperdir=/var/lib/docker/overlay2/...,workdir=/var/lib/docker/overlay2/...)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev type tmpfs (rw,nosuid,size=65536k,mode=755,inode64)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666)
9p on /work type 9p (rw,relatime,trans=fd,rfdno=...,wfdno=...)

Significado: El contenedor ve el bind mount como 9p. Ahí está la frontera otra vez, ahora dentro del contenedor.

Decisión: Para contenedores Linux, monta desde una ruta bajo /home en WSL en su lugar. El contenedor normalmente lo verá como un sistema de archivos Linux nativo y se comportará mejor.

Tres mini-historias corporativas desde el terreno

1) Incidente causado por una suposición errónea: “Es la red”

El ticket llegó clásico: “CI está bien, pero las compilaciones locales son aleatoriamente lentas.” El equipo usaba portátiles Windows con WSL2. El repo era enorme, un monorepo con un sistema de build que amaba escanear para decidir qué cambió. La gente culpaba al Wi‑Fi, VPN, DNS—cualquier cosa que sonara como dependencia externa.

Un ingeniero lo escaló como un “incidente de red” porque descargar dependencias se sentía lento y git status iba lento. Era una suposición plausible, pero equivocada. En entorno corporativo, la plausibilidad suele ser suficiente para desperdiciar una semana.

Hicimos lo que hacen los SRE cuando están cansados de narrativas: medimos. Un strace mostró que el build no esperaba sockets; esperaba stat() y getdents64() contra /mnt/c. El repo se había clonado en un directorio de Windows para que un IDE nativo de Windows “lo viera fácilmente.” Cada build incremental recorría decenas de miles de archivos a través de la frontera.

La solución fue agresivamente aburrida: clonar en ~/src, usar Remote WSL para el editor y dejar de intentar que un directorio sirviera a dos sistemas operativos a la vez. Los tiempos de build se estabilizaron. La “aleatoriedad” desapareció porque nunca fue aleatoria; era simplemente efectos de caché y escaneos en segundo plano amplificando un camino fundamentalmente lento.

La lección del postmortem no fue sobre WSL. Fue sobre suposiciones. Si tratas el rendimiento local como un problema de red por defecto, seguirás “arreglando” VPNs mientras tus archivos toman la ruta panorámica.

2) Optimización que salió mal: “Lo dejamos en C: para que los backups lo capturen”

Otra organización tenía una directiva impulsada por cumplimiento: las estaciones de desarrollador deben respaldar “producto de trabajo” diariamente. Alguien decidió que la forma más fácil de asegurar cumplimiento era exigir que los repos vivieran bajo el perfil de usuario de Windows. De ese modo, el agente de backup existente atraparía todo sin excepciones.

En papel parecía limpio. En la práctica, fue una política anti-rendimiento. Proyectos Node y Python se volvieron lentos. Contenedores con bind mounts a esos directorios corrían como si usaran una unidad de red de 1998. Los desarrolladores empezaron a buscar atajos: copiar repos a lugares aleatorios, desactivar controles de seguridad donde podían, o “temporalmente” trabajar en discos scratch no respaldados.

La optimización intentada—simplificar backups—creó nuevo riesgo. El equipo de seguridad vio proliferar excepciones. El equipo de desarrollo vio caer la productividad. Todos se pusieron de mal humor, que es la métrica más fiable en operaciones.

El compromiso eventual fue más inteligente: mantener los repos fuente dentro de WSL para rendimiento, y respaldar vía un mecanismo aprobado que pueda manejar el VHDX de WSL o exportar repos críticos en un cronograma. Requirió coordinación y un poco de esfuerzo de ingeniería, por eso no fue la primera solución aplicada.

Este es el patrón: una optimización que ignora la forma de E/S del desarrollo fracasará. No puedes gobernar con políticas lo que hacen los syscalls.

3) Práctica aburrida pero correcta que salvó el día: “Estandarizar dónde vive el código”

Un equipo de plataforma se cansó de que cada onboarding se convirtiera en un taller de depuración de rendimiento a medida. No querían heroísmos; querían un valor por defecto que funcionara. Así que estandarizaron un pequeño conjunto de prácticas: el código va en ~/src dentro de WSL, los dev containers montan desde allí y los editores se conectan vía WSL remote.

También codificaron dos diagnósticos en el doc de onboarding: ejecutar df -T . para confirmar que estás en ext4 y ejecutar una pequeña prueba de tiempo con find. Si alguna de las comprobaciones fallaba, la configuración no estaba “lista”, independientemente de si la app compilaba una vez.

Entonces llegó el día en que un nuevo agente de seguridad de Windows causó sobrecarga notable en operaciones de archivos en directorios de usuario de Windows. Podría haber sido caos: equipos perdiendo plazos, cientos de mensajes “WSL está roto” y el pinball de culpas entre TI e ingeniería.

Pero los equipos que siguieron la regla aburrida casi no lo notaron. Sus caminos calientes vivían en ext4 de WSL, alejados de los nuevos hooks de escaneo. Los tickets de soporte aún llegaron, pero se agruparon alrededor de personas que habían desviado del estándar. Esa es una propiedad operativa agradable: el radio de explosión se correlaciona con el incumplimiento.

La práctica no fue ingeniosa. Fue correcta. Y lo correcto escala mejor que lo ingenioso siempre.

Errores comunes: síntoma → causa raíz → solución

Esto es lo que veo repetidamente: los mismos síntomas, las mismas causas raíces, las mismas soluciones. Si reconoces tu dolor aquí, deja de experimentar y aplica la solución.

1) “git status tarda una eternidad”

  • Síntoma: git status toma 2–20 segundos en un repo medio.
  • Causa raíz: Repo en /mnt/c y Git recorriendo muchos archivos + sobrecarga de metadatos en la frontera.
  • Solución: Mueve el repo a ~/src. Mantén las operaciones Git dentro de WSL. Usa VS Code Remote – WSL si quieres una UI de Windows.

2) “npm install es insoportable”

  • Síntoma: La CPU no está al máximo, pero el tiempo de instalación es enorme; mucho tiempo “sin hacer nada”.
  • Causa raíz: Miles de creaciones de archivos pequeños en el sistema de archivos de Windows; posible escaneo antivirus en cada escritura.
  • Solución: Mantén el proyecto y la caché de paquetes dentro de ext4 de WSL. Evita instalar node_modules en /mnt/c. Si la política corporativa obliga a rutas de Windows, solicita exclusiones de Defender para el directorio relevante (con aprobación de seguridad).

3) “Mi recarga en caliente no detecta cambios, así que puse el código en /mnt/c”

  • Síntoma: Los watchers de archivos no detectan eventos dentro de WSL, así que alguien movió el repo a rutas de Windows para “arreglarlo”.
  • Causa raíz: Límites de watcher mal configurados o problemas específicos de vigilancia en la herramienta; mover a Windows cambió la corrección por problemas de rendimiento.
  • Solución: Arregla los watchers en WSL (aumenta límites de inotify, ajusta la herramienta a polling si es necesario). Mantén el repo en WSL; no lo reubiques a Windows como respuesta inicial.

4) “Las builds Docker son lentas cuando monto mi código”

  • Síntoma: Las builds en contenedor se arrastran; las builds nativas son menos malas.
  • Causa raíz: Bind mount desde /mnt/c hacia un contenedor Linux; el contenedor ve un montaje 9p y sufre.
  • Solución: Monta desde rutas ext4 de WSL. O copia el código dentro de la imagen para los pasos de build que hacen E/S intensiva (y acepta la compensación).

5) “Ayer era rápido”

  • Síntoma: Mismo repo, mismos comandos, ralentización repentina.
  • Causa raíz: Presión de memoria, actualización de Windows/Defender cambiando comportamiento de escaneo, VM de WSL en mal estado o el repo se movió silenciosamente de ruta (extracción de zip en una carpeta de Windows, etc.).
  • Solución: Reconfirma el tipo de ruta (df -T .), revisa la memoria (free -h) y prueba wsl.exe --shutdown desde Windows para reiniciar el estado de la VM.

6) “Mi editor es lento, no la compilación”

  • Síntoma: Búsquedas, indexado y funciones del servidor de lenguaje van lentas.
  • Causa raíz: El editor es nativo de Windows escaneando intensamente \\wsl$, o el editor está en WSL escaneando /mnt/c. En cualquier caso: frontera.
  • Solución: Mantén editor y sistema de archivos alineados. Editor de Windows + archivos de Windows, o herramientas en WSL + archivos en WSL con integración remota.

Listas de verificación / plan paso a paso

Checklist A: El plan “hacerlo rápido” (el valor por defecto que deberías seguir)

  1. Crea un lugar para repos dentro de WSL:
    cr0x@server:~$ mkdir -p ~/src
    
  2. Clona tu repo dentro de WSL:
    cr0x@server:~$ cd ~/src
    cr0x@server:~$ git clone git@github.com:example/acme-app.git
    Cloning into 'acme-app'...
    remote: Enumerating objects: 12453, done.
    Receiving objects: 100% (12453/12453), 22.3 MiB | 18.2 MiB/s, done.

    Decisión: Si clonar aquí es rápido pero las compilaciones eran lentas en /mnt/c, has validado la regla.

  3. Ejecuta tu comando lento otra vez (build/test/install) y mídelo:
    cr0x@server:~$ cd ~/src/acme-app
    cr0x@server:~$ time git status
    On branch main
    Your branch is up to date with 'origin/main'.
    
    real    0m0.187s
    user    0m0.090s
    sys     0m0.070s

    Decisión: Si bajó de segundos a subsegundo, deja de depurar y adopta la regla permanentemente.

  4. Mantén los artefactos de build dentro de WSL también. No escribas a /mnt/c “por conveniencia.” La conveniencia es cómo la latencia entra.

Checklist B: Si debes usar /mnt/c de todos modos (hazlo con los ojos abiertos)

  1. Confirma que estás en /mnt/c:
    cr0x@server:~$ df -T .
    Filesystem     Type  1K-blocks      Used Available Use% Mounted on
    C:             9p    487531516 214221812 273309704  44% /mnt/c

    Decisión: Espera que las operaciones ricas en metadatos sean más lentas. Planea mitigaciones.

  2. Reduce el churn de archivos: evita árboles enormes de dependencias cuando sea posible, usa lockfiles, poda dependencias de desarrollo y mantén las cachés dentro de WSL si la herramienta lo permite.
  3. Sé cuidadoso con ajustes de opciones de montaje. Pueden intercambiar velocidad por corrección. Si tu entorno depende de permisos Unix, desactivar metadata puede romper builds de forma sutil.

Checklist C: Flujos con contenedores (Docker/Podman) que no te saboteen

  1. Mantén el código en ext4 (~/src).
  2. Monta desde la ruta de WSL en los contenedores:
    cr0x@server:~$ docker run --rm -v /home/cr0x/src/acme-app:/work -w /work node:20-bullseye bash -lc 'node -v'
    v20.11.1

    Decisión: Si el montaje aparece como un sistema de archivos Linux nativo dentro del contenedor (no 9p), vas por buen camino.

  3. Si las builds aún se arrastran, evita bind mounts para el paso de build: copia el código en el Dockerfile y construye dentro de la imagen. Eso suele ser más rápido para E/S intensiva y reproducibilidad, y peor para velocidad de iteración. Elige con intención.

Una cita (idea parafraseada) que importa aquí

Werner Vogels (idea parafraseada): “Todo falla, todo el tiempo—diseña y opera sistemas con esa realidad en mente.”

Este es un artículo de rendimiento, pero también es de operaciones: asume que la frontera te traicionará bajo carga, porque es un punto de integración complejo. Pon tu camino caliente en un lugar aburrido y nativo.

Preguntas frecuentes

1) ¿Qué es exactamente “la frontera del sistema de archivos” en WSL?

Es la línea entre el almacenamiento nativo de Linux dentro de WSL (ext4 en el VHDX de WSL) y el almacenamiento de Windows montado en WSL (típicamente /mnt/c). Cruzarla obliga a traducción y a menudo escaneos extra.

2) ¿WSL2 siempre es más rápido que WSL1?

No. WSL2 suele ser más rápido para acceso nativo a sistemas de archivos Linux y para compatibilidad. WSL1 a veces puede sentirse menos doloroso al operar directamente sobre archivos de Windows porque no involucra el mismo camino de compartición de archivos de la VM. La mayoría de setups modernos se benefician de WSL2 si sigues la regla y mantienes el código en ext4.

3) ¿Puedo mantener mi repo en Windows y simplemente “ajustar” WSL?

Puedes mejorar cosas en los márgenes, pero estarás peleando contra la física: muchas operaciones de metadatos a través de una capa de traducción. Si el rendimiento importa, mueve el repo. El tuning es para restricciones, no por preferencia.

4) ¿Y acceder a archivos de WSL desde apps de Windows via \\wsl$?

El acceso ocasional está bien. El escaneo, indexado o build intensivo del lado de Windows sobre rutas \\wsl$ puede reintroducir el dolor de frontera en la otra dirección. Mantén la herramienta pesada del mismo lado que los archivos.

5) ¿Por qué Node.js (y node_modules) es un problema común?

Porque es una fábrica de archivos pequeños. Instaladores y bundlers crean y recorren árboles de directorio enormes, tocando metadatos constantemente. Los sistemas de archivos de frontera son peores en ese patrón exacto.

6) ¿El antivirus realmente importa tanto?

Sí, a menudo. El antivirus está optimizado para seguridad, no para tu grafo de build. Cuando engancha eventos de abrir/crear archivos en rutas de Windows, puede añadir latencia notable por operación. Miles de operaciones después, tu café está frío.

7) Si muevo mi repo a WSL, ¿cómo lo respaldo?

Usa remotos Git como fuente de la verdad y trata los clones locales como desechables cuando sea posible. Si necesitas backups de estación de trabajo, usa un enfoque aprobado que capture datos de WSL (o exporta periódicamente los repos). No “resuelvas” backups forzando rutas lentas en el desarrollo diario.

8) Mi empresa exige repos bajo mi directorio home de Windows. ¿Cuál es la opción menos mala?

Contrapón con mediciones: muestra los tiempos antes/después y las salidas de df -T. Propón una alternativa compliant (respaldo de datos WSL o espejado de origen). Si no puedes cambiar la política, reduce el churn de archivos, evita contenedores montando rutas de Windows y mantén cachés dentro de WSL cuando sea posible.

9) ¿Es seguro guardar datos importantes dentro del VHDX ext4 de WSL?

Es tan seguro como cualquier dato en disco local—lo que significa que aún necesitas backups. No es inherentemente inseguro, pero tampoco mágico. Si tu portátil muere, tu VHDX muere con él a menos que tengas un plan.

10) ¿Cuál es la mejor prueba única para demostrar que el problema es E/S de frontera?

Ejecuta la misma operación en el mismo repo una vez en /mnt/c y otra vez después de clonar en ~/src. Si el tiempo cambia por múltiplos, es sobrecarga de frontera. No hay debate necesario.

Conclusión: pasos prácticos siguientes

Si recuerdas una cosa: Mantén cargas de trabajo Linux en sistemas de archivos Linux. Clona en ~/src. Compila allí. Ejecuta contenedores desde allí. Usa integración remota de editores para no sentir que “renuncias” a la interfaz de Windows.

Pasos siguientes que puedes hacer hoy:

  1. Ejecuta pwd y df -T . en tu repo. Si ves /mnt/c y 9p, has encontrado el problema.
  2. Clona el repo en ~/src y vuelve a ejecutar tu comando lento con time. Conserva los números.
  3. Si Docker está involucrado, deja de bind-montar rutas de Windows para contenedores Linux.
  4. Estandariza la regla en tu equipo. Los problemas de rendimiento aman la inconsistencia.

WSL no es un misterio. Es una interfaz entre dos sistemas operativos con supuestos distintos. Respeta la frontera y WSL dejará de comportarse como si tuviera un lugar mejor adonde ir.

← Anterior
Parpadeos y desconexiones en docks USB‑C: orden de firmware y controladores que funciona
Siguiente →
Almacenamiento: iSCSI vs NFS vs NVMe-oF — ¿Cuál gana realmente y por qué

Deja un comentario