WSL повільний? Виправте файловий ввід/вивід одним правилом

Було корисно?

Коли WSL працює швидко, це нудно: збірки виконуються, тести закінчуються, вентилятори ноутбука вдають, що не працюють на підвищених обертах. Коли WSL повільний — це особисто. git status займає секунди. npm install ніби крокує кожен файл до диска вручну. Ви починаєте звинувачувати «WSL» як концепт — це як звинувачувати «дороги» за затори.

Більшість проблем з I/O у WSL походять від одного самостійно спричиненого болю: ви виконуєте Linux-орієнтовані завдання на файловій системі Windows. Виправте це — і багато «WSL повільний» зникне.

Одне правило: не перетинайте межу файлових систем

Правило: Виконуйте Linux-розробку на Linux-файловій системі (/home, /, ext4 VHDX WSL). Виконуйте Windows-роботу на Windows-файловій системі (C:\, D:\). Не змушуйте одну ОС робити інтенсивний файловий ввід/вивід на файловій системі іншої ОС.

Переклад у щоденну поведінку:

  • Клонувати репозиторії в ~/src всередині WSL, а не в /mnt/c/Users/you/src.
  • Тримайте node_modules, Python virtualenv, Rust target dirs, кеші Go, кеші Gradle і все, що створює тисячі дрібних файлів, всередині WSL.
  • Якщо редактор — нативний для Windows (Visual Studio, Windows Git GUI, Windows Node тощо), вкажіть йому Windows-шляхи. Якщо інструменти запускаються в WSL — вказуйте WSL-шляхи.
  • Використовуйте VS Code Remote – WSL (або аналог) щоб редактор працював із тими файлами, де запускаються Linux-інструменти.

Це не ідеологія. Це механіка. Перетин межі примушує шари трансляції, відображення дозволів, емульцію метаданих і іноді антивірусне сканування у точно найгіршому патерні: багато дрібних файлів і часті виклики stat.

Короткий жарт, бо ми друзі: WSL не повільний — ваші файли просто щодня добираються на роботу під час години пік.

Чому межа шкодить: що насправді відбувається з кожного боку

WSL2 — це справжнє ядро Linux всередині легкого VM

WSL2 запускає реальне ядро Linux. Це добре для сумісності і для продуктивності всередині Linux. Але це також означає, що Linux має власну нативну файлову систему (ext4), збережену у віртуальному диску (файлі VHDX) на боці Windows.

Всередині WSL, коли ви читаєте ~/src/app, ви використовуєте звичайний стек файлової системи Linux: page cache, метадані ext4, пошук inode, кешування записів директорії тощо. Це той шлях I/O, який Linux оптимізував десятиліттями.

/mnt/c — це не «просто ще одна папка»

Коли ви отримуєте доступ до файлів Windows з WSL, зазвичай це через /mnt/c (або /mnt/d тощо). Цей шлях забезпечується файловою системою Windows (зазвичай NTFS) і подається Linux через спеціальний інтеграційний шар. Цьому шару потрібно транслювати:

  • дозволи Linux у щось, що NTFS може представити (і назад)
  • очікування чутливості до регістру
  • поведінку символічних посилань і метадані
  • сповіщення файлової системи (inotify проти Windows change events)
  • семантику шляхів і заборонені символи

Справжній вбивця — це форма робочих навантажень розробника. Збірки та менеджери пакетів не роблять одного великого послідовного читання. Вони виконують мільйони дрібних операцій: stat(), open(), close(), сканування директорій, створення файлів, зміни дозволів. Кожен такий виклик може перетинати межу.

Антивірус і індексація «люблять допомагати» в найневдалий момент

Коли файли знаходяться на файловій системі Windows, Windows Defender (або інший набір захисту) може сканувати їх при створенні/відкритті/зміні. Це не етична проблема; це їхня задача. Але навантаження розробницьких робочих процесів механічно схоже на поведінку шкідливого ПЗ: тисячі короткоживучих файлів, швидко створюваних, модифікованих і виконуваних.

Всередині ext4 VHDX WSL Defender не може перехопити кожен Linux-системний виклик так само. Модель сканування змінюється, і затрати часто різко падають.

Docker і bind-монти можуть подвоїти ваш біль

Якщо ви запускаєте Docker Desktop інтегрований з WSL, примонтовання Windows-шляху в Linux-контейнер змушує I/O відскакувати через шари: контейнер → Linux VM → Windows файлову систему → назад. Якщо ви монтуєте WSL-шлях (ext4) в контейнер, ви залишаєтеся в основному всередині Linux-стеку.

Другий короткий жарт (і все): якщо ви bind-монтуєте /mnt/c у контейнер, ви винайшли новий бенчмарк під назвою «час до жалю».

Цікаві факти й історія, що пояснюють сучасні дивності

  • WSL1 і WSL2 — це не проста зміна версії. WSL1 транслював виклики Linux у Windows-системні виклики; WSL2 запускає реальне ядро в VM, змінюючи поведінку I/O і сумісність.
  • Файлова система Linux у WSL2 знаходиться всередині VHDX. Це віртуальний диск-файл, збережений у Windows, зазвичай під профілем користувача. Всередині цього файлу лежить ext4.
  • Обмін метаданих між файловими системами дорогий. Інструменти Linux постійно викликають stat(); відображення метаданих Windows у семантику Linux не безкоштовне, особливо через межу VM.
  • Історично чутливість до регістру відрізнялася. NTFS підтримує функції чутливості до регістру, але інструменти Windows історично припускали нечутливі до регістру шляхи. Linux припускає чутливість. Клей для сумісності мусить реферувати.
  • inotify важливий для сучасних стеків розробки. Webpack, Jest, сервери мови — багато покладаються на події файлової системи Linux. Відображення змін файлів між Windows і Linux повільне і складне.
  • Навантаження дрібних файлів — найгірший випадок для шарів-інтероперації. Бази даних, менеджери пакетів і системи збірки роблять багато fsync, перейменувань, тимчасових файлів і метушні в директоріях — саме те, що «interop файлові системи» ненавидять.
  • Корпоративний захист кінцевих точок змінив розрахунок. Коли безпека в компаніях посилилася, накладні витрати сканування на стороні Windows стали помітнішими. Той самий ноутбук може «відчуватися швидким» або «ламатися» просто через переміщення репозиторію.
  • Монтування drvfs у WSL має опції, чутливі до продуктивності. Налаштування, як-от обробка метаданих, можуть змінювати коректність і швидкість при використанні /mnt/c.

Швидкий план діагностики (знайдіть вузьке місце за хвилини)

Якщо хтось каже «WSL повільний», не починайте з тонких налаштувань sysctl. Почніть із визначення, з якого боку межі вони знаходяться і якої форми I/O.

Перше: визначте, де знаходиться репозиторій

  • Якщо шлях починається з /mnt/, вважайте, що накладні витрати межі присутні, поки не доведено протилежне.
  • Якщо шлях під /home (або інший нативний Linux-шлях), уповільнення, ймовірно, в іншому місці: навантаження CPU, тиск пам’яті, антивірус, що сканує VHDX, патерни монтування Docker або щось патологічне в ланцюжку інструментів.

Друге: визначте тип робочого навантаження

  • Багато дрібних файлів (node_modules, Python site-packages, Git status, ripgrep, індексація серверів мови): домінує накладна в межі.
  • Великі послідовні файли (обробка медіа, контрольні точки моделей): ви швидше обмежені пропускною спроможністю диска або CPU.
  • Багато fsync/rename (бази даних, менеджери пакетів): домінують шари коректності та семантика синхронізації.

Третє: перевірте патерни «подвійної трансляції»

  • Запуск Linux-інструментів над файлами Windows (/mnt/c)
  • Запуск Windows-інструментів над файлами Linux (\\wsl$ шляхи, які активно використовуються Windows-додатками)
  • Контейнери, що bind-монтують Windows-шляхи в Linux-контейнери

Четверте: вимірюйте, а не відчувайте

Виберіть один мікро-бенчмарк, що відповідає робочому навантаженню: проходження директорії, створення файлів, git status або крок збірки. Порівняйте Linux-шлях проти Windows-шляху. Якщо бачите велику різницю — рішення просте: перемістіть файли або змініть стратегію монтування.

Практичні завдання: команди, виводи та рішення

Ось реальні команди, які можна запустити всередині WSL. Кожне завдання включає, що означає вивід і що робити далі.

Завдання 1: Підтвердьте, яку версію WSL ви використовуєте

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

Значення: VERSION 2 означає, що ви на WSL2 (добрий дефолт). VERSION 1 поводиться по-іншому, особливо для міжфайлової інтероперації.

Рішення: Якщо ви на WSL1 і вам потрібна краща сумісність Linux або краща поведінка нативної Linux-файлової системи, мігруйте на WSL2. Якщо ваш робочий процес головно працює з файлами Windows, WSL1 іноді може відчуватися менш болісним на /mnt/c — але це нішевий компроміс.

Завдання 2: Подивіться, де ви знаходитесь (WSL шлях проти Windows монтування)

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

Значення: Ви на файловій системі Windows через /mnt/c.

Рішення: Якщо цей репозиторій має багато дрібних файлів (більшість саме такі), перемістіть його в ~/src і знову запустіть повільну операцію. Очікуйте різницю немов ніч і день.

Завдання 3: Визначте тип файлової системи, що підтримує поточний каталог

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

Значення: Тип 9p вказує на паравіртуалізований механізм спільного доступу до файлів. Це шлях межі; навантаження, що інтенсивно працюють з метаданими, часто тут страждають.

Рішення: Якщо ви бачите ext4 під / або /home, ви на нативній WSL-файловій системі. Якщо бачите 9p (або подібне), уникайте запуску збірок тут.

Завдання 4: Порівняйте поведінку «шторму stat» на Windows- і 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

Значення: Тисячі операцій метаданих на /mnt/c коштують секунди.

Рішення: Якщо ваше навантаження виглядає так (Git, Node, Python), не тримайте репозиторій на /mnt/c.

Завдання 5: Запустіть той самий цикл метаданих на 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

Значення: Той самий патерн системних викликів значно швидший на нативних Linux-шляхах.

Рішення: Скористайтеся цим як тестом до/після переміщення репозиторію, щоб довести, що проблема — накладні витрати межі, а не «WSL повільний» загалом.

Завдання 6: Перевірте опції монтування для /mnt/c (вони мають значення)

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)

Значення: Опції типу metadata впливають на те, як дозволи Linux зберігаються/емуляться на файлах Windows. Деякі опції покращують коректність, але можуть коштувати продуктивності.

Рішення: Якщо ви мусять працювати на /mnt/c, будьте свідомі опцій монтування через /etc/wsl.conf. Якщо немає сильної причини, не оптимізуйте це — краще перемістіть репозиторій.

Завдання 7: Підтвердіть, що файлова система дистро WSL — ext4

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

Значення: ext4 — нативна Linux-файлова система у WSL2. Саме тут ви хочете мати репозиторій і артефакти збірки.

Рішення: Якщо / — ext4, у вас вже є швидка смуга. Помістіть проекти сюди.

Завдання 8: Знайдіть топ-винуватців I/O під час повільної команди

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>

Значення: Виклики, що торкаються /mnt/c, займають десятки мілісекунд кожен. Помножте на тисячі — і отримаєте сум.

Рішення: Перемістіть репозиторій. Якщо не можете — зменшіть кількість файлів (vendoring, обрізання node_modules) або змініть робочий процес, щоб уникнути операцій, що важко працюють через межу.

Завдання 9: Перевірте тиск пам’яті (пейджинг робить I/O мов мед)

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

Значення: Ви під тиском пам’яті і використовуєте swap. Кожна файлова операція конкурує з пейджингом.

Рішення: Закрийте ферму вкладок браузера, зменшіть паралелізм або налаштуйте ліміти пам’яті WSL (через .wslconfig у Windows), якщо вашому навантаженню реально потрібна ОЗП.

Завдання 10: Виміряйте швидкість обходу директорії там, де лежить репозиторій

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

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

Значення: Просте проходження директорії ~8 секунд — величезний червоний прапорець для накладних витрат межі (або дуже великий репозиторій, але ви це знаєте).

Рішення: Запустіть той самий find після переміщення репозиторію в ~/src. Якщо час впаде в багато разів — ви знайшли вузьке місце.

Завдання 11: Перевірте, чи випадково репозиторій лежить на Windows через симлінк/плутанину шляхів

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

Значення: Навіть якщо ваш prompt виглядає «Linux-подібним», це підтверджує реальний бекінг-шлях.

Рішення: Якщо він резольвиться до /mnt/*, розглядайте це як доступ до файлової системи Windows і очікуйте повільнішої метаданної I/O.

Завдання 12: Перевірте, чи Git не робить додаткової роботи через семантику файлової системи

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

Значення: Файловий кеш Git і preload index можуть допомогти, але вони не чарівні, якщо ви на /mnt/c. Вони зменшують частину системних викликів; вони не усувають межу.

Рішення: Тримайте ці опції ввімкненими для великих репозиторіїв, але не використовуйте їх як виправдання тримати репозиторій на Windows. Спочатку перемістіть репозиторій.

Завдання 13: Перевірте, чи повільний шлях — це bind-монт контейнера з 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

Значення: Docker присутній і, ймовірно, інтегрований з WSL. Тепер питання — куди вказують ваші bind-монти.

Рішення: Якщо ваш docker run -v використовує шляхи /mnt/c, змініть їх на WSL-шляхи (для Linux-контейнерів) і перевірте знову.

Завдання 14: Спостерігайте джерела монтувань всередині запущеного контейнера

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=...)

Значення: Контейнер бачить bind-монт як 9p. Це знову межа, але вже всередині контейнера.

Рішення: Для Linux-контейнерів bind-монтуйте шлях під /home у WSL натомість. Контейнер зазвичай побачить його як нативну Linux-файлову систему і поводитиметься краще.

Три корпоративні історії з поля бою

1) Інцидент через неправильне припущення: «Це мережа»

Тикет прийшов як класичний: «CI працює, але локальні збірки випадково повільні». Команда використовувала Windows-ноутбуки з WSL2. Репозиторій був величезний — монорепо із системою збірки, що сканує весь проект, щоб визначити зміни. Люди звинувачували Wi‑Fi, VPN, DNS — що завгодно, що звучало як зовнішня залежність.

Один інженер ескалував це як «мережевий інцидент», бо завантаження залежностей і git status відчувалися повільно. Це було помилкове припущення, але правдоподібне. У корпоративному середовищі правдоподібність часто достатня, щоб втратити тиждень.

Ми зробили те, що роблять втомлені SRE: виміряли. strace показав, що збірка не чекала сокетів; вона чекала на stat() і getdents64() виклики проти /mnt/c. Репозиторій клонували в директорію Windows, щоб Windows-IDE «легко бачив» файли. Кожна інкрементальна збірка прогулювала десятки тисяч файлів через межу.

Виправлення було надзвичайно нудним: клонувати в ~/src, використовувати Remote WSL для редактора і перестати намагатися змусити одну директорію служити двом ОС одночасно. Часи збірки стабілізувалися. «Випадковість» зникла, бо насправді її ніколи не було — це були ефекти кешу і фонове сканування, що підсилювали фундаментально повільний шлях.

Постмортем урок не про WSL. Він про припущення. Якщо ви за замовчуванням трактуєте локальну продуктивність як мережеву проблему, ви продовжите «фіксити» VPN, а ваші файли тим часом робитимуть об’їзд.

2) Оптимізація, що обернулася проти: «Залишимо на C:, щоб бекапи ловили це»

Інша організація мала директиву з відповідності: робочі стани розробників мають щодня бекапитись. Хтось вирішив, що найпростіше — змусити репозиторії жити під профілем користувача Windows. Так існуючий агент бекапу ловив усе без спеціальних випадків.

На папері виглядало чисто. На практиці це було політикою проти продуктивності. Node і Python проекти повзли. Контейнери з bind-монтами в ці директорії працювали ніби мережевий диск з 1998 року. Розробники почали обходити це: копіювати репозиторії кудись, вимикати контролі безпеки де могли або «тимчасово» працювати на не заархівованих scratch-дисках.

Спроба оптимізації — спростити бекапи — створила нові ризики. Команді безпеки довелося погоджувати виключення. Розробницька команда бачила падіння продуктивності. Всі стали незадоволені, що є найнадійнішим індикатором проблем у операціях.

Зрештою компроміс був розумніший: тримати вихідники всередині WSL для продуктивності і робити бекапи через погоджений механізм, який може опрацьовувати VHDX WSL або експортувати критичні репозиторії за розкладом. Це вимагало координації і трохи інженерної роботи, тому цього не зробили одразу.

Це патерн: оптимізація, що ігнорує форму I/O розробки, обернеться проти вас. Ви не можете політикою вирішити проблему системних викликів.

3) Нудна, але правильна практика, що врятувала ситуацію: «Уніфікуйте місце розміщення коду»

Платформна команда втомилася від того, що кожне онбординг-навчання перетворюється на індивідуальне налагодження продуктивності. Вони не хотіли подвигів; вони хотіли дефолт, що працює. Тож стандартизували невеликий набір практик: код — у ~/src всередині WSL, dev-контейнери монтують звідти, а редактори підключаються через WSL remote.

Вони також закріпили два діагностики в онбординг-документі: запустити df -T ., щоб підтвердити, що ви на ext4, і запустити невеликий тест з find для часу проходження. Якщо одна з перевірок не проходила — налаштування вважалося «незавершеним», незалежно від того, чи зібралася програма раз.

Потім стався день, коли новий агент безпеки Windows почав створювати помітні накладні витрати на файлові операції в директоріях користувача Windows. Це могло стати хаосом: команди пропускали дедлайни, сотні повідомлень «WSL зламаний» і звичні звинувачування між IT та інженерами.

Але команди, що дотримувалися нудного правила, майже не помітили змін. Їхні гарячі шляхи жили в ext4 WSL, подалі від нових скануючих гачків. Тікети підтримки все ще приходили, але вони концентрувалися навколо тих, хто відхилився від стандарту. Це гарна операційна властивість: радіус ураження корелює з невідповідністю.

Практика не була хитрою. Вона була правильною. І правильне масштабується краще, ніж хитре.

Типові помилки: симптом → корінна причина → виправлення

Ось те, що я бачу регулярно: ті самі симптоми, ті самі корінні причини, ті самі виправлення. Якщо пізнаєте свою проблему тут — припиніть експерименти і зробіть виправлення.

1) «git status займає вічність»

  • Симптом: git status 2–20 секунд у середньому репозиторії.
  • Корінна причина: Репозиторій на /mnt/c і Git прогулює велику кількість файлів + накладні витрати метаданих межі.
  • Виправлення: Перемістіть репозиторій у ~/src. Тримайте Git-операції всередині WSL. Використовуйте VS Code Remote – WSL, якщо хочете Windows UI.

2) «npm install нестерпно повільний»

  • Симптом: CPU не завантажено, але час встановлення величезний; багато часу «нічого не робиться».
  • Корінна причина: Тисячі створень дрібних файлів на файловій системі Windows; можливе антивірусне сканування кожного запису.
  • Виправлення: Тримайте проєкт і кеш пакунків всередині ext4 WSL. Уникайте встановлення node_modules на /mnt/c. Якщо корпоративна політика примушує Windows-шляхи, добийтеся виключень Defender для відповідної директорії (обережно і з погодженням безпеки).

3) «Мій hot reload не підхоплює зміни, тому я перемістив код на /mnt/c»

  • Симптом: Файл-ватчери пропускають події в WSL, тому хтось перемістив репозиторій у Windows-шляхи, щоб «полагодити» це.
  • Корінна причина: Неправильні ліміти watcher або специфічні проблеми інструменту; переміщення на Windows обміняло коректність на проблеми продуктивності.
  • Виправлення: Виправте ватчери в WSL (збільште inotify limits, налаштуйте інструмент на опитування, якщо потрібно). Тримайте репозиторій у WSL; не переміщуйте його в Windows як першу відповідь.

4) «Docker builds повільні, коли монтую вихідні»

  • Симптом: Контейнеризовані збірки повзуть; нативні збірки менш жахливі.
  • Корінна причина: Bind-монт з /mnt/c у Linux-контейнер; контейнер бачить 9p і страждає.
  • Виправлення: Bind-монтуйте з шляхів ext4 WSL. Або копіюйте вихідні в образ для кроків збірки, що роблять інтенсивний I/O (і приймайте компроміс).

5) «Вчора було швидко»

  • Симптом: Той самий репозиторій, ті самі команди, раптове уповільнення.
  • Корінна причина: Тиск пам’яті, оновлення Windows/Defender, що змінило сканування, WSL VM у поганому стані, або репозиторій тихо перемістився (розпакування у Windows-папку тощо).
  • Виправлення: Заново підтвердіть тип шляху (df -T .), перевірте пам’ять (free -h) і спробуйте wsl.exe --shutdown з Windows, щоб перезавантажити стан VM.

6) «Мій редактор повільний, не збірка»

  • Симптом: Пошук, індексація та функції серверу мови відстають.
  • Корінна причина: Редактор нативний для Windows активно сканує \\wsl$ шляхи, або редактор в WSL сканує /mnt/c. У будь-якому випадку: межа.
  • Виправлення: Тримайте редактор і файлову систему узгодженими. Windows-редактор + Windows-файли, або WSL-інструменти + WSL-файли з віддаленою інтеграцією.

Чеклісти / покроковий план

Чекліст A: План «зробити швидко» (дефолт, якого слід дотримуватися)

  1. Створіть дім для репозиторіїв всередині WSL:
    cr0x@server:~$ mkdir -p ~/src
    
  2. Клонувати репозиторій всередині 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.

    Рішення: Якщо клон тут швидкий, але збірки були повільні на /mnt/c, ви підтвердили правило.

  3. Запустіть повільну команду ще раз (збірка/тест/встановлення) та виміряйте час:
    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

    Рішення: Якщо час впав з секунд до субсекунди — припиніть налагодження і приймайте правило назавжди.

  4. Тримайте артефакти збірки також всередині WSL. Не виводьте в /mnt/c «зручності заради». Зручність — це як латентність проникає в систему.

Чекліст B: Якщо все ж потрібно використовувати /mnt/c (робіть це свідомо)

  1. Підтвердіть, що ви на /mnt/c:
    cr0x@server:~$ df -T .
    Filesystem     Type  1K-blocks      Used Available Use% Mounted on
    C:             9p    487531516 214221812 273309704  44% /mnt/c

    Рішення: Очікуйте, що операції, важкі на метадані, будуть повільнішими. Плануйте пом’якшення наслідків.

  2. Зменшіть метушню з файлами: уникайте величезних дерев залежностей де можливо, використовуйте lockfiles, обрізайте dev-залежності і тримайте кеші всередині WSL, якщо інструмент це дозволяє.
  3. Будьте обережні з налаштуваннями монтування. Вони можуть обмінювати швидкість на коректність. Якщо ваше середовище залежить від Unix-дозволів, відключення метаданих може непомітно ламати збірки.

Чекліст C: Контейнерні робочі процеси (Docker/Podman), що вам не шкодять

  1. Тримайте код на ext4 (~/src).
  2. Bind-монтуйте з WSL-шляху в контейнери:
    cr0x@server:~$ docker run --rm -v /home/cr0x/src/acme-app:/work -w /work node:20-bullseye bash -lc 'node -v'
    v20.11.1

    Рішення: Якщо монтування всередині контейнера виглядає як нативна Linux-файлова система (не 9p), ви на правильному шляху.

  3. Якщо збірки все ще повільні, уникайте bind-монтів для кроку збірки: скопіюйте вихідні в Dockerfile і збирайте всередині образу. Це зазвичай швидше для інтенсивного I/O і кращо для відтворюваності, але гірше для швидкої ітерації. Обирайте свідомо.

Цитата (перефразована ідея), що має значення

Werner Vogels (перефразована ідея): «Усе ламається постійно — проєктуйте й експлуатуйте системи з цією реальністю на увазі.»

Ця стаття про продуктивність, але також про операції: припускайте, що межа зрадить вас під навантаженням, бо це складна точка інтеграції. Покладіть свій гарячий шлях кудись нудне і нативне.

Питання й відповіді (FAQ)

1) Що саме означає «межа файлових систем» у WSL?

Це лінія між нативним збереженням Linux всередині WSL (ext4 у VHDX) і файловою системою Windows, змонтованою в WSL (зазвичай /mnt/c). Перетин її змушує трансляцію і часто додаткове сканування.

2) Чи WSL2 завжди швидший за WSL1?

Ні. WSL2 зазвичай швидший для нативного доступу до Linux-файлової системи і сумісності. WSL1 іноді може відчуватися менш болісним при роботі безпосередньо з файлами Windows, бо він не використовує той самий шлях спільного доступу через VM. Більшість сучасних налаштувань розробки все ж виграють від WSL2, якщо дотримуватися правила і тримати код в ext4.

3) Чи можу я тримати репозиторій на Windows і просто «налаштувати» WSL?

Ви можете підвищити показники на краях, але ви боретесь із фізикою: багато метаданних операцій через шар трансляції. Якщо продуктивність важлива — перемістіть репозиторій. Налаштування підходить для обмежень, а не для переваг.

4) А що з доступом до файлів WSL із Windows-додатків через \\wsl$?

Епізодичний доступ — ок. Інтенсивне сканування, індексація або збірка Windows проти шляхів \\wsl$ можуть повернути проблеми межі в інший бік. Тримайте «важкі інструменти» там, де лежать файли.

5) Чому Node.js (і node_modules) так часто проблема?

Бо це фабрика дрібних файлів. Інсталятори і бандлери створюють і перебирають величезні дерева директорій, постійно торкаючись метаданих. Межові файлові системи найгірше справляються саме з цим патерном.

6) Чи дійсно антивірус має таке велике значення?

Так, часто. Антивірус оптимізований для безпеки, а не для вашого графа збірки. Коли він прив’язується до подій відкриття/створення файлів на Windows-шляхах, він додає помітну латентність на операцію. Після тисяч операцій ваша кава вже холодна.

7) Якщо я переміщу репозиторій у WSL, як його бекапити?

Використовуйте віддалені Git-репозиторії як джерело істини і ставтеся до локальних клонів як тимчасових, коли можливо. Якщо потрібні бекапи робочих станів, використовуйте погоджений механізм, що захоплює дані WSL (або періодично експортуйте репозиторії). Не «вирішуйте» бекапи, змушуючи повільні шляхи для щоденної розробки.

8) Моя компанія вимагає репозиторії в каталозі Windows home. Який найменш поганий варіант?

Покажіть виміри: продемонструйте час до/після і вивід df -T. Запропонуйте відповідну альтернативу (бекап WSL-даних або дзеркалювання вихідників). Якщо політику змінити не вдається, мінімізуйте метушню файлів, уникайте контейнерних bind-монтів Windows шляхів і тримайте кеші всередині WSL, де дозволено.

9) Чи безпечно зберігати важливі дані всередині ext4 VHDX WSL?

Це так само безпечно, як будь-які локальні дані — тобто вам усе одно потрібні бекапи. Це не по суті небезпечно, але й не магія. Якщо ноутбук помре, ваш VHDX теж помре, якщо немає плану бекапу.

10) Який найкращий тест, щоб довести, що проблема — I/O через межу?

Запустіть ту саму операцію в тому самому репозиторії спочатку на /mnt/c, потім після клонування в ~/src. Якщо час змінюється в рази — це накладні витрати межі. Жодних дискусій.

Висновок: практичні наступні кроки

Якщо ви запам’ятаєте одне: тримайте Linux-навантаження на Linux-файлових системах. Клонуйте в ~/src. Збирайте там. Запускайте контейнери звідти. Використовуйте віддалену інтеграцію редактора, щоб не відчувати, ніби ви «відмовляєтеся» від Windows UI.

Кроки, які можна зробити сьогодні:

  1. Запустіть pwd і df -T . у вашому репозиторії. Якщо бачите /mnt/c і 9p — ви знайшли проблему.
  2. Клонувати репозиторій в ~/src і повторно запустити повільну команду з time. Зберігайте числа.
  3. Якщо задіяний Docker — припиніть bind-монтувати Windows-шляхи для Linux-контейнерів.
  4. Стандартизувати правило в команді. Проблеми продуктивності люблять несумісність.

WSL не загадка. Це інтерфейс між двома операційними системами з різними припущеннями. Поважайте межу — і WSL перестане поводитися так, ніби йому краще кудись іти.

← Попередня
Мерехтіння та відключення USB‑C док-станцій: послідовність прошивки й драйверів, яка працює
Наступна →
Зберігання: iSCSI проти NFS проти NVMe-oF — що насправді перемагає і чому

Залишити коментар