libuv та його роль
1. Що таке libuv
libuv - це крос-платформна бібліотека на C, створена спеціально для Node.js. Вона реалізує:
- Event Loop (цикл подій);
- асинхронний I/O (введення-виведення без блокувань);
- пул потоків (Thread Pool) для фонових задач;
- таймери, черги й системні події.
Спочатку вона була створена для Node.js, але тепер використовується і в інших проєктах (наприклад, Luvit, Julia).
2. Event Loop - головний цикл подій
libuv реалізує Event Loop, який керує порядком виконання задач:
Спрощена модель:
- V8 виконує синхронний код.
- Коли зустрічає асинхронну операцію (наприклад,
fs.readFileабоsetTimeout), Node.js передає її libuv. - libuv поміщає задачу в чергу подій.
- Коли результат готовий (файл прочитано, таймер спрацював, з'єднання встановлено), libuv ставить callback назад у чергу Event Loop.
- V8 виконує callback, коли до нього доходить черга.
Отже, Event Loop дозволяє Node.js бути однопоточним на рівні JS, але багатопоточним під капотом.
3. Thread Pool - пул потоків
Хоча JS-код виконується в одному потоці, деякі операції виконуються у фоні:
- операції з файловою системою (
fs), - DNS-запити,
- криптографічні операції (
crypto.pbkdf2,scrypt), - стиснення (
zlib).
libuv використовує пул із 4 потоків (за замовчуванням) для їх виконання. Ти можеш збільшити це число за допомогою змінної середовища:
UV_THREADPOOL_SIZE=8 node app.js4. Асинхронний I/O
libuv уміє працювати із системними викликами:
- epoll (Linux),
- kqueue (macOS, BSD),
- IOCP (Windows),
- event ports (Solaris).
Ці механізми дозволяють ефективно відстежувати події (наприклад, читання з сокета) без блокування потоку, поки операція не завершиться.
Це основа неблокуючого введення-виведення (non-blocking I/O).
5. Таймери та черги задач
libuv керує:
setTimeoutіsetInterval;setImmediateіprocess.nextTick;- внутрішніми чергами подій (
microtasks,macrotasks).
Кожна категорія має свою фазу виконання всередині Event Loop:
timers → I/O callbacks → idle/prepare → poll → check → close callbacks6. Взаємодія з V8 та Node.js
libuv не виконує JavaScript - це робить V8. Але вона:
- отримує асинхронні задачі від JS (через Node.js bindings);
- виконує їх у фоні або чекає системних подій;
- повертає результати назад у V8 через Event Loop.
7. Приклад у дії
const fs = require('fs');
console.log('Початок');
fs.readFile('data.txt', 'utf-8', (err, data) => {
console.log('Файл прочитано');
});
setTimeout(() => console.log('Таймер спрацював'), 0);
console.log('Кінець');Порядок виконання:
Початок ← V8 (синхронно)
Кінець ← V8 (синхронно)
Таймер спрацював ← libuv (через Event Loop)
Файл прочитано ← libuv (через Thread Pool)8. Резюме: ролі libuv
| Компонент | Роль |
|---|---|
| Event Loop | Керує чергами подій і callback-ів |
| Thread Pool | Виконує важкі операції у фоні |
| Async I/O | Забезпечує неблокуюче введення-виведення |
| Таймери | Керує часом і розкладом задач |
| Крос-платформність | Працює однаково на Windows, Linux, macOS |
У зв'язці:
┌────────────┐
│ JavaScript │ ← (виконується в V8)
└─────┬──────┘
│ виклики fs, http, timers
▼
┌────────────┐
│ libuv │ ← (Event Loop, Thread Pool, async I/O)
└─────┬──────┘
▼
┌────────────┐
│ ОС (API) │ ← (файли, мережа, таймери)Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.