WSL може відчуватися як суперсила: інструменти Linux на робочому столі Windows, миттєве переключення контексту, без плати за перезавантаження. А потім одного дня ви відкриваєте дистрибутив і… чекаєте. І чекаєте. Порожній термінал дивиться на вас, ніби затягує переговори про контракт.
Більшість скарг «WSL повільний» не про CPU. Це таймаути, init-скрипти оболонки, що роблять забагато, зламані монтування та мережеві припущення, які були правдиві на ноутбуку 2019 року і невірні в корпоративному VPN 2026 року. Виправлення рідко зводиться до однієї магічної правки. Це дисциплінована діагностика й безжальна обрізка.
Цікаві факти та контекст
- WSL 1 і WSL 2 — різні всесвіти. WSL 1 транслює виклики ядра Linux у виклики Windows; WSL 2 запускає справжнє ядро Linux у легкій VM. Через це режими відмов при запуску різняться.
- WSL 2 використовує віртуальний диск (VHDX) для кожного дистрибутива. Отже, продуктивність зберігання визначається VHDX, поведінкою файлової системи хоста, скануванням антивірусом і тим, де знаходиться VHDX (наприклад, повільний HDD проти NVMe).
- Підтримка systemd з’явилася пізно і змінила очікування. Рікми люди обходили «відсутність init» власними скриптами. Коли systemd став підтримуваним, ті хаки не зникли самі по собі.
- /mnt/c — це не «просто папка». Це межа між двома ОС із різною семантикою й накладними витратами. Тяжкі збірки там можуть відчуватися як робота в болоті.
- Корпоративні VPN люблять ламати розв’язання імен (name resolution). Оболонка WSL, яка робить один DNS-запит за підказку, може з ранку працювати нормально, а ввечері «зависати на 8 секунд».
- Багато проблем з повільним запуском WSL — самі на собі. Фреймворки підказок, менеджери плагінів і «допоміжні» скрипти, що викликають git, kubectl або хмарові CLI під час запуску, — звичні підозрювані.
- Запуск WSL — це не одна річ. Є ініціалізація дистрибутива, налаштування монтувань, налаштування мережі, потім запуск вашої оболонки, а далі те, що роблять ваші скрипти оболонки.
- Windows Defender може впливати більше, ніж ваш CPU. Сканування в реальному часі в каталогах з репозиторіями (особливо node_modules і артефакти збірки) може домінувати у сприйнятій затримці.
- PATH може бути проблемою продуктивності. Імпорт величезного Windows PATH у WSL уповільнює пошук команд і ламатиме інструменти оригінальними способами.
Як насправді відбувається запуск WSL (щоб припинити здогадки)
Коли ви запускаєте дистрибутив WSL, ви не «завантажуєте Linux» так, як VM у UI гіпервізора. Але й не просто запускаєте процес, як колись здавалося у WSL 1. WSL 2 запускає (або відновлює) легку VM з ядром Linux, підключає VHDX дистрибутива, конфігурує віртуальну мережу й потім запускає ваш запитаний командний процес — зазвичай вашу оболонку за замовчуванням.
З точки зору латентності є чотири рівні, і кожен має свій підпис, коли щось іде не так:
1) Підйом/відновлення VM
Якщо WSL був ідл, його могли вимкнути. Наступний запуск має підняти VM. Зазвичай це швидко, але може тягнутися, коли хост зазнає тиску по пам’яті, коли зберігання повільне або коли щось змушує робити додаткову роботу (наприклад, агресивний захист кінцевої точки).
2) Ініціалізація дистрибутива (і systemd, якщо ввімкнено)
Сучасний WSL може запускати systemd. Це добре — сервіси поводяться нормально — але додає поведінку схожу на завантаження. Якщо юніт повільний, аварійний або чекає на мережу, ви заплатите цю вартість під час «запуску». Якщо systemd не ввімкнено, у вас можуть бути старі init-скрипти або хакі на момент входу, що намагаються його імітувати.
3) Монтування та зв’язки між ОС
WSL підключає диски Windows, налаштовує /mnt і опційно імпортує змінні середовища Windows, як-от PATH. Поведінка монтувань керується в /etc/wsl.conf. Коли монтування неправильне, ви побачите зависання, що виглядають як «оболонка не відкривається», але справжній винуватець — блокуюче монтування або перевірка файлової системи.
4) Ініціалізація оболонки
Це та частина, яку ви контролюєте. Bash читає /etc/profile і ваші персональні dotfiles. Zsh читає інші файли. Fish має свій світ. Якщо ваша підказка виконує git status у величезному репозиторії, або ваш профіль викликає хмарний CLI, що чекає на проксі — термінал виглядатиме «завислим», хоча WSL у порядку.
Цитата варта стіни, бо продуктивність запуску здебільшого — це очікування залежностей:
парафраз — Вернер Фогельс: «Усе ламається постійно; проєктуйте системи, що до цього готові.»
У WSL-прояві «відмова» часто означає «таймаут», який ходить у костюмі.
Швидкий план діагностики (перший/другий/третій)
Якщо ви хочете, щоб WSL запускався швидко, потрібно визначити, який рівень уповільнює запуск. Не починайте з переписування dotfiles. Не починайте з перевстановлення дистрибутива. Почніть з вимірювань таким чином, щоб ізолювати вузьке місце.
Перший: відокремте ініціалізацію оболонки від усього решта
- Запустіть WSL із командою, яка уникає ініціалізації інтерактивної оболонки.
- Якщо це швидко — проблема в dotfiles/підказках/плагінах.
- Якщо все ще повільно — проблема в WSL/дистрибутиві/systemd/монтуваннях/мережі.
Другий: перевірте systemd і сервіси (якщо ввімкнено)
- Дізнайтеся в systemd, скільки часу воно взяло.
- Шукайте юніти, що чекають на мережу, DNS або монтування.
- Вимкніть усе, що не потрібне для девелоперської оболонки.
Третій: мережа/DNS і монтування
- DNS-таймаути — найпоширеніший винуватець «випадкових 5–10 секунд».
- Доступ до /mnt/c і імпорт Windows PATH — звичні «смерті від тисячі порізів».
- Якщо все інше чисто, тоді атакуйте збереження/VHDX і виключення антивірусу.
Жарт №1: Якщо ваша підказка робить три мережеві виклики, це вже не підказка. Це розподілена система з почуттями.
Практичні завдання: команди, виводи та рішення
Ви виправите це швидше, якщо поводитиметесь як на інциденті: збирайте докази, ізолюйте змінні, робіть одну зміну за раз і зберігайте шлях до відкату. Нижче реальні завдання з командами, прикладами виводів і тим, що вирішувати з них.
Завдання 1: Виміряйте час запуску WSL без вашої інтерактивної оболонки
cr0x@server:~$ /usr/bin/time -p wsl.exe -d Ubuntu-22.04 -- bash -lc 'true'
real 0.62
user 0.00
sys 0.00
Що означає вивід: Число real — це часовий проміжок за стіною. Це обходить логіку підказки та більшість драм dotfile.
Рішення: Якщо це швидко (<1–2с), але ваш звичайний термінал повільний, переходьте до налагодження ініціалізації оболонки. Якщо це повільно — копайте далі в systemd/монтування/мережа/зберігання.
Завдання 2: Порівняйте час запуску інтерактивної оболонки
cr0x@server:~$ /usr/bin/time -p bash -lic 'exit'
real 2.87
user 0.19
sys 0.08
Що означає вивід: Це вимірює логін + інтерактивну ініціалізацію. Якщо real значно більше за user і sys, ви чекаєте на I/O, мережу або блокуючі subprocess’и.
Рішення: Якщо інтерактивна оболонка повільна, а неінтерактивна швидка — підозрюйте dotfiles/підказки/плагіни.
Завдання 3: Подивіться, яку оболонку ви реально запускаєте і як її викликано
cr0x@server:~$ echo "$0"; ps -p $$ -o pid,ppid,cmd
-bash
PID PPID CMD
812 799 -bash
Що означає вивід: Провідний дефіс означає login shell. Це змінює, які файли підключаються (/etc/profile, ~/.bash_profile тощо).
Рішення: Якщо ви випадково запускаєте login shell, коли це не потрібно, виправте профіль терміналу (Windows Terminal / VS Code), щоб запускати non-login shell для швидкості.
Завдання 4: Прослідкуйте, які файли підвантажує ваша оболонка (bash)
cr0x@server:~$ bash -lic 'set -o posix; shopt -po login_shell; echo "BASH_VERSION=$BASH_VERSION"; exit'
set -o posix
shopt -s login_shell
BASH_VERSION=5.1.16(1)-release
Що означає вивід: Підтверджує, що ви в login shell, і показує версію bash (релевантно для можливостей старту й сумісності).
Рішення: Якщо login shells повільні, перемістіть важке в login-only файли в on-demand функції або припиніть використовувати login shells для інтерактивних сесій.
Завдання 5: Використайте bash xtrace, щоб знайти повільний рядок
cr0x@server:~$ bash -lic 'PS4="+\t\D{%s}\t"; set -x; source ~/.bashrc; exit' 2> /tmp/bashrc.trace
...output...
Що означає вивід: Файл трасування має мітки часу для кожного виконуваного рядка. Шукайте великі розриви між мітками.
Рішення: Видаліть, відкладіть або захистіть повільні команди. Якщо розрив збігається з викликом git, kubectl, gcloud, npm або інструментів DNS — ви знайшли якір.
Завдання 6: Профілювання zsh (якщо ви використовуєте zsh)
cr0x@server:~$ zsh -lic 'zmodload zsh/zprof; source ~/.zshrc; zprof' | head -n 12
num calls time self name
-----------------------------------------------------------------------------------
1) 1 189.22 189.22 38.51% 189.22 189.22 compinit
2) 1 121.77 121.77 24.78% 121.77 121.77 gitstatus_init
Що означає вивід: Він ранжує функції за часом. compinit і складні помічники git-підказки часто домінують.
Рішення: Кешуйте completion, зменшіть плагіни або перейдіть на простішу підказку. У WSL «швидко» важливіше за «круто».
Завдання 7: Перевірте, чи ввімкнено systemd і чи воно повільне
cr0x@server:~$ ps -p 1 -o pid,comm,args
PID COMMAND COMMAND
1 systemd /sbin/init
Що означає вивід: Якщо PID 1 — systemd, то запуск WSL включає роботу systemd-юнитів.
Рішення: Якщо systemd увімкнено і вам не потрібні служби — подумайте про його відключення. Якщо потрібне — вимірюйте й налаштовуйте юніти.
Завдання 8: Виміряйте час завантаження systemd і знайдіть повільні юніти
cr0x@server:~$ systemd-analyze time
Startup finished in 2.103s (kernel) + 5.882s (userspace) = 7.985s
graphical.target reached after 5.841s in userspace
Що означає вивід: Час userspace — там живуть повільні служби.
Рішення: Якщо userspace — кілька секунд, перелічіть «blame».
cr0x@server:~$ systemd-analyze blame | head -n 10
3.214s systemd-networkd-wait-online.service
1.102s snapd.service
0.688s apt-daily.service
0.512s systemd-resolved.service
Що означає вивід: Ці юніти спожили найбільше часу. wait-online — класичний «чому я чекаю на мережу, якої немає?» юніт.
Рішення: Маскуйте або переналаштуйте сервіси, що не потрібні в середовищі розробки оболонки.
Завдання 9: Перевірте монтування і чи платите ви додатково за диски Windows
cr0x@server:~$ mount | grep -E '/mnt/|drvfs' | head -n 5
C: on /mnt/c type drvfs (rw,noatime,uid=1000,gid=1000,metadata,case=off)
D: on /mnt/d type drvfs (rw,noatime,uid=1000,gid=1000,metadata,case=off)
Що означає вивід: Диски Windows змонтовано як drvfs. Опції, як-от metadata і case, впливають на сумісність і продуктивність.
Рішення: Якщо ваш робочий процес активно використовує POSIX-права, зберігайте metadata. Якщо ні — можна спростити. Але більший виграш — перемістити гарячі репозиторії в Linux-файлову систему.
Завдання 10: Виявте, чи працюєте ви в /mnt/c (пастка продуктивності)
cr0x@server:~$ pwd
/mnt/c/Users/alex/source/mega-repo
Що означає вивід: Ви на Windows-зберіганні. Збірки, встановлення пакетів і операції git часто будуть повільніші.
Рішення: Клонуте репо під ~ (Linux-файлова система) і використовуйте редактор, що може до нього звертатися (VS Code Remote – WSL розроблено саме для цього).
Завдання 11: Перевірте поведінку DNS (швидкий відмов проти повільного зависання)
cr0x@server:~$ getent hosts github.com
140.82.121.4 github.com
Що означає вивід: Розв’язання DNS пройшло швидко. Якщо воно зависає — отримаєте свого головного підозрюваного.
Рішення: Якщо повільно/зависає — перевірте /etc/resolv.conf і налаштування DNS WSL. Якщо швидко — уповільнення десь інде.
Завдання 12: Підтвердіть, чи /etc/resolv.conf генерується автоматично і який nameserver ви використовуєте
cr0x@server:~$ ls -l /etc/resolv.conf; head -n 10 /etc/resolv.conf
-rw-r--r-- 1 root root 235 Jan 12 09:14 /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation...
nameserver 172.24.64.1
search corp.example
Що означає вивід: WSL генерує resolv.conf і вказує на віртуальний gateway IP. На VPN це може бути нормально або перетворитися на вечірку таймаутів.
Рішення: Якщо DNS ненадійний/повільний — відключіть автогенерацію і встановіть стабільну стратегію резолверів для вашого середовища (деталі в розділі мережі).
Завдання 13: Перевірте, чи імпорт Windows PATH роздуває пошук команд
cr0x@server:~$ echo "$PATH" | tr ':' '\n' | wc -l
142
Що означає вивід: 142 запису в PATH — це не досягнення. Це ризик. Багато з них — шляхи Windows, що спричиняють додаткові перевірки файлової системи.
Рішення: Розгляньте відключення appendWindowsPath у /etc/wsl.conf і додавання лише потрібних шляхів явно.
Завдання 14: Визначте, чи ваша підказка виконує дорогі git-операції
cr0x@server:~$ PS1='\u@\h:\w\$ ' bash --noprofile --norc
cr0x@server:~$ exit
exit
Що означає вивід: Це запускає чистий bash з простою підказкою. Якщо він миттєво відгукується — проблема у вашій «красивій» підказці.
Рішення: Замініть фреймворк підказки або налаштуйте його так, щоб не викликати git при кожному оновленні підказки (або робіть це лише в середині git-репо з кешуванням).
Завдання 15: Швидка перевірка на зависання команд у dotfiles через timeout
cr0x@server:~$ timeout 2s bash -lc 'source ~/.bashrc; echo ok' || echo "bashrc exceeded 2s"
bashrc exceeded 2s
Що означає вивід: Ваш bashrc не встигає завершитися за дві секунди у неінтерактивному запуску. Всередині щось блокує.
Рішення: Використайте трасування (Завдання 5) і видаліть/захистіть повільні частини.
Завдання 16: Перевірте, чи ввімкнено Windows interop і чи це вам шкодить
cr0x@server:~$ cat /proc/sys/fs/binfmt_misc/WSLInterop 2>/dev/null | head -n 5
enabled
interpreter /init
flags: P
offset 0
magic 4d5a
Що означає вивід: Interop увімкнено, отже з Linux можна запускати Windows виконувані файли. Це зручно — і іноді повільно, коли скрипти випадково викликають Windows-інструменти.
Рішення: Якщо бачите повільні команди і виявляєте, що вони резольвляться в Windows-бінарі (наприклад, git.exe), виправте порядок PATH або відключіть interop для цього робочого процесу.
Припиніть повільні оболонки: профільні скрипти, фреймворки підказок і пастки PATH
Старт оболонки — це місце, куди йде продуктивність, бо це «лише скрипт». Скрипти ростуть як цвіль: повільно, а потім раптом ви підвантажуєте п’ять менеджерів плагінів і движок тем, щоб надрукувати ваше ім’я курсивом.
WSL підсилює це, бо багато «оболонкової солодощі» припускає низьку латентність локальних ресурсів. Але у WSL ви можете проходити через /mnt/c, випадково викликати Windows-бінарі або спричиняти DNS-запити через напівавтомобільний VPN.
Знайте, які файли виконуються, і припиніть подвійне підвантаження
Bash зазвичай підвантажує:
/etc/profile(login shells)~/.bash_profileабо~/.profile(login shells)~/.bashrc(interactive shells)
Класичне уповільнення — ~/.bash_profile підвантажує ~/.profile, той підвантажує ~/.bashrc, а термінал запускає login interactive shell, який знову підвантажує ~/.bashrc. Ви щойно виконали повільний код двічі. Ніхто не помічає, поки репо не виросте й git status не стане дорогою операцією.
Фреймворки підказок: оберіть один і конфігуруйте його свідомо
Starship, oh-my-zsh теми, powerlevel10k, кастомні git-помічники — ці інструменти чудові. Вони також із задоволенням запускають зовнішні команди багаторазово. У WSL зовнішні команди можуть перетинати межу ОС і викликати Windows-інструменти або потрапляти на файлові шари, що не кешуються так, як ви очікуєте.
Правила, які я застосовую в командах:
- Ніяких мережевих викликів під час рендерингу підказки. Це включає хмарні CLI, отримувачі контексту kube, або «корисні» перевірки версій.
- Ніякого рекурсивного git status у великих репозиторіях за замовчуванням. Віддавайте перевагу швидким перевіркам або кешу; уникайте
git statusв підказці, якщо не можете обмежити його вартість. - Відкладання важкої ініціалізації. Системи completion, менеджери версій мов і інструменти на зразок direnv повинні завантажуватися ліниво, коли це можливо.
PATH: тримайте його коротким, детермінованим і з пріоритетом для Linux
WSL може імпортувати Windows PATH записи. Це зручно, поки оболонка не мусить перевіряти 140 директорій для визначення python, і половина з них на /mnt/c. Гірше: іноді ви запускаєте git.exe, коли думаєте, що використовуєте Linux git. Тепер операції з репо стрибають через межу.
Практичні поради:
- Відключіть додавання Windows PATH, якщо воно не потрібне.
- Якщо потрібні поодинокі Windows-інструменти, додайте їх явно і поставте в кінець PATH.
- При налагодженні «повільних команд» перевіряйте, який бінар використовується за допомогою
type -aабоcommand -v.
Огорожіть будь-які опціональні інструменти швидкими перевірками
Якщо ініціалізація оболонки викликає інструмент, що може не існувати, не викликайте його сліпо й не чекайте на помилку. Перевірте спочатку:
command -v tool >/dev/null— дешево.- Виклик
tool --versionне завжди дешевий (деякі CLI ініціалізують плагіни та конфіг).
І перестаньте робити «перевірки оновлень» при кожному старті оболонки. Якщо це дійсно потрібно — заплануйте їх у фоні після появи підказки.
Зламані init-скрипти та systemd: коли «завантаження» не є завантаженням
Історично WSL навчав людей ставитися до запуску дистрибутива як «запустити оболонку і сподіватися на краще». Потім з’явилася підтримка systemd і всі почали вмикати служби. Це нормально — поки не стає проблемою.
Вирішіть, чи вам справді потрібен systemd
Якщо ваш робочий процес потребує Docker всередині WSL, фонових демонів, таймерів або нагляду за сервісами — systemd може бути правильним рішенням. Якщо ви в основному компілюєте й користуєтесь CLI-інструментами — systemd часто є додатковим навантаженням.
Навіть із увімкненим systemd слід бути вибірковим. WSL — не сервер на утриманні. Це середовище розробки, яке має стартувати миттєво і бути одноразовим.
Поширені повільні юніти в WSL
- systemd-networkd-wait-online.service: чекає готовності мережі; часто марний у WSL, де мережа піднімається інакше.
- snapd.service: може додати помітну затримку запуску; snaps не завжди виправдані в WSL.
- apt-daily.service і таймери: фонові оновлення можуть підіймати навантаження на диск саме тоді, коли ви відкриваєте оболонку.
- Інтеграція resolved: може погано взаємодіяти з автогенерованим resolv.conf WSL залежно від конфігурації.
Masking vs disabling: виберіть правильний молоток
Якщо юніт активно шкодить при запуску — mask (заблокуйте) його, щоб він не міг стартувати випадково. Якщо ви просто не хочете, щоб він був увімкненим за замовчуванням — disable. Для продуктивності старту WSL маскування wait-online — звичний виграш.
І так: іноді «зламаний init-скрипт» — це ваш власний ~/.profile, що прикидається init-системою. Якщо у вас є скрипти, що запускають демони, експортують середовище і торкаються монтувань — ви створили міні-init. Воно має всі недоліки systemd, але без діагностики.
Монтування та ввід/вивід файлів: податок /mnt/c, параметри automount і де лежить ваш репо
Більшість історій жахів продуктивності WSL пов’язані з файловою системою Windows. Не тому, що вона погана, а тому, що вона інша. Інструменти Linux припускають POSIX-семантику. Windows-семантика не є POSIX. WSL закриває різницю. Папір не безкоштовний.
Тримайте «гарячий» код у Linux-файловій системі
Якщо вам важливі старт і інтерактивна відзивчивість, ваші основні репозиторії й результати збірки мають лежати під /home всередині дистрибутива. Це означає клонування у WSL, а не редагування клонів на C:\. Ви все ще можете редагувати з Windows через інструменти, що знають про WSL.
Ця проста зміна виправляє:
- Повільний
git status,git diff - Повільні встановлення залежностей (npm/pip/gradle кеші)
- Дивну поведінку прав файлів
- Накладні витрати на сканування кінцевої точки (часто менш болісно всередині VHDX)
Налаштуйте automount, але не наслідуйте сліпо
/etc/wsl.conf може контролювати поведінку automount. Люди люблять копіювати конфіг із блогу і забувати, що вони це зробили. Через шість місяців щось ламається і всі звинувачують WSL.
Ключові ідеї:
- metadata дозволяє POSIX-права на Windows-файлах. Корисно, але може додавати накладні витрати та плутанину, якщо вам це не потрібно.
- case важливий для інструментів, де має значення регістр у шляхах.
- appendWindowsPath може роздмухати PATH і уповільнити пошук команд.
Будьте свідомі, що ви доступаєтеся через межу
Доступ до кількох конфігураційних файлів на /mnt/c — це нормально. А от запуск збірки, що робить мільйони дрібних файлових операцій там — це власна поразка щодо продуктивності. Якщо ваш фреймворк підказки сканує директорії на /mnt/c під час старту — це навмисно повільна оболонка.
Мережа та DNS: фабрика мовчазних таймаутів
Проблеми з DNS — найпоширеніша причина «WSL інколи зависає на 5–10 секунд». Причина нудна: багато інструментів роблять резольвування імен під час старту, і вони часто роблять це синхронно. Ваша оболонка не здається повільною; вона здається замороженою.
Куди йде DNS-біль у WSL:
- WSL автогенерує
/etc/resolv.confна основі мережі Windows. - Корпоративні VPN змінюють DNS і маршрути Windows на льоту.
- Деякі організації виштовхують DNS-сервери, доступні тільки при підключенні до VPN.
- Інструменти на кшталт git, плагіни kubectl, менеджери пакетів мов і підказки можуть викликати DNS.
Швидко виявити
Якщо getent hosts some-domain зависає — ви знайшли головного підозрюваного. Далі вирішуєте, чи виправляти DNS на рівні WSL (поведінка resolv.conf), чи в dotfiles/інструментах (припинити виклики DNS під час старту).
Зробіть поведінку DNS детермінованою
Для багатьох корпоративних середовищ найстабільніша установка:
- Вимкнути автогенерацію
/etc/resolv.conf. - Записати resolv.conf, який працює і в VPN, і поза ним, або генерувати його скриптом, прив’язаним до стану VPN.
- Уникати покладання на «те, що Windows думає сьогодні».
Але обережно: якщо ви захардкодите публічні резолвери в організації з жорсткими обмеженнями, внутрішні домени зламаються. Правильний підхід залежить від середовища. Інженерія надійності — це мистецтво поваги до реальності, а не суперечок з нею.
Реальність збереження/VHDX: що означає «диск повільний» у WSL2
Коли WSL2 здається повільним, люди звинувачують «VM». Коли дуже повільним — «Windows». Насправді все більш конкретно: це ваш віртуальний диск, його розташування і канал зберігання хоста.
Зрозумійте наслідки VHDX
Ваша Linux-файлова система живе в VHDX-файлі. Випадкові I/O-патерни, інтенсивна робота з маленькими файлами і метаданими (привіт, node_modules) чутливі до продуктивності хостового зберігання. Якщо ваш профіль користувача Windows знаходиться на зашифрованому або перенаправленому диску, ваш WSL VHDX може лежати в неприємному місці.
Захист кінцевої точки — змінна продуктивності
Сканування в реальному часі може зробити роботу з файлами повільною. Якщо стартові скрипти торкаються багатьох файлів (сканування підказок, відновлення кешів completion, менеджери мов), ви відчуєте це під час «запуску WSL», хоча реальна робота — це сканування файлів.
Працюйте з безпекою, а не проти неї. Нудна, правильна практика — встановити схвалені виключення для розташування VHDX або конкретних директорій з високим обігом файлів. Якщо ваша організація не дозволяє виключень, найефективніший важіль — мінімізувати обіг файлів при старті і тримати репозиторії в Linux-файловій системі, щоб уникати накладних витрат drvfs.
Жарт №2: Антивірус — як сигналізатор диму, що ще й коментує вашу техніку приготування — корисно, але він може зіпсувати тиху вечірку.
Три корпоративні міні-історії (що реально ламається в організаціях)
Інцидент через хибне припущення: «DNS локальний, тож швидкий»
Платформна команда випустила стандартизоване WSL-середовище для інженерів: Ubuntu, zsh, красива підказка, кілька допоміжних скриптів і контекст kubectl у підказці, бо «це корисно». В офісі все тестувалося добре. Вдома половина команди поскаржилась, що WSL «випадково зависає» при відкритті нового терміналу.
Хибне припущення було тонким: вони вважали, що вартість DNS-резольвування незначна. На корпоративному Wi‑Fi так і було. На домашніх мережах і split-tunnel VPN DNS-запити для внутрішніх доменів таймаутили перед fallback. Скрипт підказки не просто читав конфіг — він викликав kubectl, той викликав плагін, що намагався розв’язати внутрішнє API-ім’я. Кожна нова оболонка платила таймаут.
Налагодження було класичною SRE-роботою: відтворити з чистою підказкою, потім додавати компоненти назад. getent hosts зависав точно тоді, коли зависала підказка. Вирішили двома способами: (1) прибрали виклики kubectl з рендерингу підказки; (2) зробили DNS детермінованим, відключивши автогенерацію resolv.conf і керуючи резолверами залежно від стану VPN.
Урок: шляхи старту мають бути вільними від мережевої залежності. Якщо потрібен динамічний контекст — обчислюйте його асинхронно після появи підказки і кешуйте з TTL.
Оптимізація, що обернулась проти: «Давайте покладемо репозиторії на C: для зручності»
Група продуктивності розробників хотіла просте правило: тримати код у C:\src, щоб інструменти Windows і WSL обидва могли його бачити. Всім подобалася зручність. Для дрібних сервісів все працювало.
Потім з’явився монорепо з важкими TypeScript-збірками і масивним деревом залежностей. Раптом ті самі ноутбуки, що були «достатньо швидкі», почали витрачати хвилини на інсталяцію, і оболонки стали кілька секунд показувати підказку, бо підказки і completion-системи сканували репо, щоб вивести контекст.
Вони намагались оптимізувати параметри drvfs, відключили metadata, додали noatime і підправили все, що могли. Маргінальні покращення. Фундаментальна невідповідність залишалась: лінуксові тулчейни виконують мільйони файлових операцій через міст Windows-файлової системи.
Реальне виправлення було нудним і трохи незручним: перемістити репо під ~/src всередині Linux-файлової системи і використовувати WSL-aware редактори. Вони лишили невелику кількість Windows-доступних файлів на /mnt/c, але «гарячий шлях» перейшов в ext4 всередині VHDX. Часи старту й збірок повернулися до розумних.
Нудна але правильна практика, що врятувала день: «Скрипти старту — це production-код»
У регульованому підприємстві багато інженерів використовували WSL, і вони ставилися до dotfiles як до персонального мистецтва. Потім прийшло оновлення безпеки: нові проксі-настройки, оновлені bundles сертифікатів і зміни у внутрішньому DNS-маршруванні. Наступного ранку частина організації не могла швидко відкривати WSL-термінали. Дехто взагалі не міг.
Одна команда не панікувала, бо мала практику, що звучить негарно: вони тримали логіку ініціалізації оболонки мінімальною, під контролем версій і з переглядом. Їхні dotfiles були розділені на «критичні при старті» і «приємні мати», з таймаутами навколо всього, що могло б блокувати. Вони також мали задокументований шлях порятунку: запуск з --noprofile --norc, щоб відновити зламану оболонку.
Коли інші команди перевстановлювали дистрибутиви і звинувачували Windows-оновлення, ця команда мала робочий термінал, могла запускати діагностику і допомагати іншим. Виправлення для всієї організації виявилося простим узгодженням DNS/проксі, але команди з дисциплінованими dotfiles втратили менше часу і дали чистіші дані інциденту.
Мораль: те, що виконується при старті, — частина вашої платформи. Ставтеся до цього так само серйозно, як до production init-скриптів — бо саме воно вам потрібно, коли все інше горить.
Поширені помилки: симптом → корінна причина → виправлення
1) Симптом: Термінал відкривається, залишається порожнім 5–15 секунд, потім з’являється підказка
Корінна причина: Блокуюча команда в ініціалізації оболонки (зазвичай пов’язана з DNS) або фреймворк підказки, що запускає повільні підпроцеси.
Виправлення: Запустіть чисту оболонку (bash --noprofile --norc), підтвердьте, що вона миттєва, потім трасуйте файли ініціалізації (bash xtrace або zsh zprof). Приберіть мережеві виклики з підказки. Додайте таймаути для опціональних помічників.
2) Симптом: Повільно тільки при VPN (або тільки поза VPN)
Корінна причина: Резолвери в /etc/resolv.conf доступні лише в одному стані; запити таймаутять.
Виправлення: Відключіть автогенерацію resolv.conf і керуйте резолверами свідомо для вашого середовища, або виправте налаштування DNS/VPN на стороні Windows, щоб WSL успадковував коректну поведінку.
3) Симптом: Перехід у репо (cd) нормальний, але кожна нова підказка займає 1–2 секунди
Корінна причина: Підказка виконує git status або еквівалент при кожному рендері; репо велике або на drvfs.
Виправлення: Спрощуйте підказку або вмикайте кешування; уникайте сканування при кожній підказці; перемістіть репо у Linux-файлову систему.
4) Симптом: Запуск WSL став повільним після ввімкнення systemd
Корінна причина: Повільні systemd-юнити (wait-online, snapd, apt timers) тягнуть userspace запуск.
Виправлення: Використайте systemd-analyze blame і маскуйте/вимикайте непотрібні юніти. Якщо systemd не потрібен — відключіть його.
5) Симптом: Команди «лагодять», навіть прості, як python або node
Корінна причина: PATH величезний; резолюція команд перевіряє багато Windows-каталогів; або ви випадково викликаєте Windows-бінарі.
Виправлення: Зменшіть PATH, відключіть додавання Windows PATH, перевірте type -a для бінарів, виправте порядок PATH.
6) Симптом: Повільно тільки в одному дистрибутиві; інші швидкі
Корінна причина: Дистрибутив-специфічні dotfiles, systemd-юнити або пошкоджені кеші (completion, shims менеджерів мов).
Виправлення: Порівняйте systemd blame, порівняйте dotfiles, тимчасово перейменуйте ~/.bashrc/~/.zshrc, перебудуйте кеші.
7) Симптом: Час старту погіршився після «налаштування» /etc/wsl.conf
Корінна причина: Сліпе наслідування налаштувань automount/interop спричинило додаткову роботу або проблеми сумісності.
Виправлення: Поверніться до мінімальної конфігурації, потім застосовуйте зміни по одній, вимірюючи. Залишайте лише ті зміни, що реально допомагають.
8) Симптом: Випадкові паузи під час старту оболонки, частіше у великих репо
Корінна причина: Сканування антивірусом операцій з великою кількістю файлів, які ініціюють стартові скрипти (відновлення кешів completion, сканування підказок).
Виправлення: Зменшіть обіг файлів при старті; розгляньте санкціоновані виключення; тримайте репо в Linux-файловій системі; уникайте відновлення кешів при кожному запуску.
Контрольні списки / покроковий план
Покроково: доведіть час запуску WSL до менше 1 секунди (або наскільки реально можливо)
- Виміряйте базовий час без інтерактивної ініціалізації. Використайте Завдання 1. Якщо це повільно — не торкайтеся dotfiles поки що.
- Виміряйте час інтерактивної оболонки. Використайте Завдання 2. Якщо інтерактивна — це дельта, профілюйте dotfiles і вбивайте мережеві/підказкові негаразди.
- Відкрийте чисту оболонку. Використайте Завдання 14 (
--noprofile --norc), щоб довести, що середовище може бути швидким. - Профілюйте ініціалізацію оболонки. Bash xtrace (Завдання 5) або zsh zprof (Завдання 6).
- Уберіть мережеві залежності зі старту. Ні DNS, ні хмарних CLI, ні викликів kube під час рендерингу підказки.
- Перенесіть гарячі репо з /mnt/c. Якщо ви збираєте на drvfs — ви платите додатково за це.
- Обріжте PATH. Зменшіть записи, відключіть імпорт Windows PATH, якщо можете.
- Перевіряйте systemd лише якщо потрібно. Якщо PID 1 — systemd, запустіть
systemd-analyze blameі маскуйте повільні юніти. - Підтвердіть швидкість DNS.
getent hostsмає бути миттєвим. Якщо ні — виправте стратегію resolv.conf. - Перевіряйте після кожної зміни. Не комбінуйте хаотично правки — міряйте, зберігайте, повторюйте.
Операційний чекліст: підтримуйте швидкість з плином часу
- Dotfiles — це код під рев’ю, а не фольклор.
- Підказка не має виконувати небконтрольовані операції (мережа, глибокі файлові сканування).
- Будь-яка опціональна допоміжна команда має таймаут або механізм лінивого завантаження.
- Репо за замовчуванням перебувають у Linux-файловій системі; drvfs — для поділу, а не для важких збірок.
- Коли вмикаєте systemd — аудитуйте і мінімізуйте увімкнені юніти.
- У корпоративних мережах явно вирішіть стратегію DNS; не покладайтеся на «авто».
FAQ
1) Чому WSL інколи швидкий, а інколи болісно повільний?
Тому що ви часто чекаєте таймаутів: DNS, готовність мережі або команда в init оболонки, що блокується за певних умов (стан VPN, проксі, недоступний домен).
2) Як зрозуміти, що проблема в самому WSL, а що — в конфігурації оболонки?
Запустіть WSL з тривіальною командою (Завдання 1). Якщо це швидко, але інтерактивна оболонка повільна (Завдання 2) — проблема в dotfiles/підказках/плагінах.
3) Чи погана ідея вмикати systemd у WSL?
Не обов’язково. Це виправдано, якщо вам потрібні керовані сервіси. Це також джерело затримок, якщо увімкнені юніти чекають на мережу або виконують фонове обслуговування. Вимірюйте з systemd-analyze і обрізайте.
4) Чому робота під /mnt/c робить усе повільнішим?
Тому що drvfs мостить дві моделі файлових систем. Інструменти Linux виконують багато метаданих операцій, які дорожчі через ту межу. Помістіть збіркові репо під ~ всередині дистрибутива.
5) Який найшвидший фікс у dotfiles, що зазвичай допомагає?
Перестаньте запускати дорогі команди в підказці. Приберіть git status з PS1 або налаштуйте кешування. Якщо треба показувати інформацію про git — зробіть це легковагово і обмежено.
6) Як зрозуміти, що DNS — винуватець?
Якщо getent hosts some-domain зависає або займає секунди — DNS причетний. Також перевірте, чи уповільнення корелює з включенням/виключенням VPN.
7) Чи варто відключити інтеграцію Windows PATH?
Якщо PATH величезний або ви випадково запускаєте Windows-бінарі — так. Відключіть і додавайте конкретні Windows-шляхи лише за потреби, бажано наприкінці.
8) Я використовую VS Code з WSL. Чи змінює це щось?
Ні, воно робить усе важливішим. VS Code породжує оболонки й допоміжні процеси. Повільна ініціалізація оболонки робить редактор повільним і нестабільним. Тримайте старт мінімальним і детермінованим.
9) Я виправив підказку, але WSL все одно займає ~5 секунд при першому відкритті на день
Ймовірно це підйом/відновлення VM плюс systemd (якщо ввімкнено) плюс розігрів диска. Виміряйте з Завдання 1 і інструментами systemd. Якщо базовий час повільний — перевірте systemd-юнити, монтування і зберігання/антивірус.
10) Який найнадійніший «вихід» коли оболонка зламана і не стартує?
Запустіть чисту оболонку: bash --noprofile --norc або zsh -f, потім виправте або тимчасово перейменуйте ваші rc-файли.
Висновок: практичні наступні кроки
Швидкість запуску WSL не є таємницею. Це ланцюг постачань: стан VM, системні сервіси, монтування, мережа, а потім ваші скрипти оболонки. Найповільніша залежність виграє. Якщо ви хочете, щоб усе було швидко — припиніть здогадки і почніть ізоляцію.
Зробіть це далі, по порядку:
- Виміряйте базовий запуск без інтерактивної ініціалізації оболонки.
- Виміряйте інтерактивний запуск оболонки; якщо це дельта — профілюйте dotfiles і прибирайте підказки/мережевий шум.
- Якщо базовий час повільний — перевірте час завантаження systemd і повільні юніти; потім монтування і DNS.
- Перемістіть важкі репозиторії в Linux-файлову систему і тримайте /mnt/c для легкого спільного доступу.
- Обріжте PATH і припиніть імпортувати весь Windows-екосистему, якщо вона вам дійсно не потрібна.
Коли ви зробите це правильно, WSL знову відчуватиметься тим, чим мав бути: швидким, одноразовим Linux-робочим простором, що стартує за час, який треба, щоб придумати наступну команду.