Релиз Bun v1.4.1: сброс JIT-кода в простое, поддержка HTTP/2 на общем порту и оптимизация бандлов Zod на 79%
Серверный рантайм Bun на базе движка JavaScriptCore привлекал внимание сообщества рекордными показателями в синтетических бенчмарках. Однако в реальной эксплуатации критически важны не только миллисекунды ответа, но и стабильность потребления памяти, предсказуемость под нагрузкой и сетевая совместимость. Релиз Bun v1.4.1 включает 202 исправления дефектов и вводит глубокие оптимизации виртуальной машины, сетевого стека Bun.serve и бандлера, нацеленные на надежность долгоживущих микросервисов.
Очистка скомпилированного JIT-кода в моменты простоя
Одной из острых проблем серверных Node.js и JavaScript-приложений (включая Next.js SSR, Express и Fastify) остается раздувание оперативной памяти (Resident Set Size, RSS). В рантаймах с динамической JIT-компиляцией часто вызываемый код компилируется в машинные инструкции процессора. Эти бинарные артефакты удерживаются в памяти неограниченно долго даже после прекращения пикового трафика: сервер простаивает, но память операционной системе не возвращается.
В Bun v1.4.1 виртуальная машина JavaScriptCore принудительно выгружает скомпилированный машинный JIT-код, если процесс переживает продолжительный простой (около трех минут без входящих запросов). При новом всплеске функции компилируются заново, но освобождение неактивных страниц позволяет снизить базовый футпринт контейнеров без перезапуска сервиса.
| Сценарий (Linux x64, 60с нагрузки + 3 мин простоя) | Bun v1.4.0 (RSS) | Bun v1.4.1 (RSS) | Node.js v26 |
|---|---|---|---|
| Next.js SSR | 222 МБ | 142 МБ | 195 МБ |
| Express | 65 МБ | 53 МБ | — |
| Fastify | 65 МБ | 55 МБ | — |
| Elysia | 46 МБ | 44 МБ | — |
| Hono | 35 МБ | 34 МБ | — |
| Vite dev | 142 МБ | 111 МБ | 115 МБ |
Для Next.js SSR объем памяти сократился на 80 МБ (со 142 МБ против 222 МБ в версии 1.4.0 и 1303 МБ в Bun 1.3.14). Важно понимать границу оптимизации: сброс JIT-кода не снижает рабочий набор активного сервиса под постоянным потоком запросов, а ликвидирует накопление фонового балласта в периоды затишья.
Сетевой стек: совмещенный порт для HTTP/1.1 и HTTP/2
Встроенный веб-сервер Bun.serve() получил нативную поддержку HTTP/2 на том же самом порту, что и HTTP/1.1.
Для защищенных соединений (TLS) выбор протокола происходит на этапе рукопожатия через расширение ALPN (Application-Layer Protocol Negotiation): при наличии маркера h2 сервер переключается на бинарные фреймы HTTP/2, иначе используется HTTP/1.1. На открытых сокетах сервер распознает префикс инициализации HTTP/2 preface.
Bun.serve({
port: 3000,
tls: {
key: Bun.file('./server.key'),
cert: Bun.file('./server.crt'),
},
http2: true,
fetch(req) {
return new Response('Подключение успешно');
},
});
Единый обработчик fetch обслуживает запросы обоих стандартов, избавляя от необходимости поднимать промежуточный reverse-proxy для локальной терминации HTTP/2. Однако в реализации есть ограничения: HTTP/2 пока не поддерживает WebSockets и хвостовые заголовки (trailers), а флаг http1: false отключает fallback на HTTP/1.x, что требует осторожности с legacy-клиентами и проверками health-check.
Потоковый ввод-вывод и противодавление в WebSockets
Метод прямой записи Bun.write(path, response) теперь принимает потоковые объекты Response, Request и ReadableStream. Данные передаются в файловый дескриптор ядра потоком по мере поступления сетевых пакетов, минуя буферизацию всего тела в оперативной памяти. В официальном тесте скачивания файла на 128 МБ пиковый скачок RSS снизился со 161 МБ до 13 МБ. Чтение приостанавливается, если в буфере накапливается 256 КБ непрочитанных данных, а удаленный без чтения Response закрывает соединение.
Клиентский WebSocket получил методы socket.pause() и socket.resume(). Спецификация WHATWG WebSocket не позволяет регулировать скорость чтения: если сервер шлет поток событий, а клиент занят медленной записью на диск, память переполняется.
Методы Bun управляют системным сокетом:
- При заполнении буфера потребителя вызывается
socket.pause(). - Рантайм прекращает чтение из TCP-сокета, окно TCP заполняется и отправитель естественным образом притормаживает передачу (TCP backpressure).
- При освобождении буфера (событие
drain) вызываетсяsocket.resume().
Уже декодированные сообщения при этом все равно доставляются, а сам API специфичен для Bun и не предназначен для браузеров.
Оптимизация сборщика: tree-shaking для export * as
Бандлер bun build исправил устранение неиспользуемого кода (tree-shaking) для библиотек с реэкспортом вида export * as. Ранее импорт отдельной функции (например, import { z } from 'zod') затягивал весь объект пространства имен. Для Zod это означало включение 252 внутренних сущностей, включая JSON Schema генераторы и файлы локализаций.
Bun v1.4.1 преобразует обращения к свойствам в прямые вызовы функций:
- Zod 4.5: бандл уменьшился с 375,3 КБ до 77,3 КБ (−79%);
- fp-ts: с 21,8 КБ до 3,2 КБ (−85%);
- Effect: с 369,1 КБ до 163,6 КБ (−56%).
Если объект пространства имен передается в функцию целиком, используется в спред-операторе ({ ...ns }) или читается по вычисляемому ключу, оптимизация отключается. Флаг --no-deprecated-namespace-object-setters запрещает мутацию таких объектов.
Системные API, криптография и пакетный менеджер
Среди других архитектурных доработок релиза:
- Хеширование Argon2: модуль
node:cryptoполучил нативную поддержкуcrypto.argon2иcrypto.argon2Sync(argon2d, argon2i, argon2id) в системном пуле потоков с байтовой совместимостью с Node.js. - Инлайнинг Buffer: низкоуровневые операции чтения и записи бинарных буферов инлайнятся виртуальной машиной (операция
writeFloatLEна macOS arm64 ускорилась с 2,85 нс до 0,31 нс). - Оптимизация AsyncLocalStorage: устранены лишние аллокации при вызовах
await, исправлены утечки контекста при вызовеenterWithв таймерах и колбэках. - Офлайн-режим установки: флаг
bun install --offlineпадает с ошибкой при отсутствии пакета в кэше, гарантируя изоляцию без скрытых сетевых запросов. Флаг--prefer-offlineиспользует локальный кэш без валидации, но разрешает скачивание отсутствующих зависимостей. Для Electron в монорепозиториях внедрена опцияselfContainedс выделеннымnode_modules.
Регламент безопасного обновления
Для внедрения Bun v1.4.1 рекомендуется следующий регламент:
- Зафиксировать исходные размеры артефактов
bun build --minify, потребление памяти и задержки ответов сервиса. - Обновить рантайм командой
bun upgrade(или через официальный установщикcurl -fsSL https://bun.sh/install | bash). - Прогнать интеграционные тесты сетевого слоя, проверив согласование ALPN и корректность проксирования HTTP/2.
- Проверить конфигурацию TLS: Bun теперь валидирует сертификат строго по хосту из URL, требуя параметр
tls.servernameпри нестандартном проксировании. - Проверить фронтенд-сборки на корректность работы оптимизированных импортов библиотек.
