Перейти к содержанию
Автор: LUMD

Bun добавил поддержку потоков с общей памятью в JavaScriptCore

В рамках открытого PR в репозитории WebKit реализованы общие‑heap потоки для JavaScriptCore: новые API, тестовый набор, TSAN‑сборка без гонок и ряд оптимизаций, готовых к использованию в Bun.

Bun получил возможность запускать JavaScript‑код в нескольких потоках, используя общую кучу в движке JavaScriptCore (JSC). Это первый шаг к полноценной многопоточности в среде, где до этого всё исполнялось в едином потоке, и открывает путь к значительным ускорениям серверных приложений.

Как реализованы общие‑heap потоки?

В PR описаны детали архитектуры: отдельный heap‑сервер, аллокаторы per‑thread, общий VM‑state, а также новые типы «TID/SW‑tagged» и сегментированные «butterflies». Для синхронизации добавлен набор API Thread/Lock/Condition/ThreadLocal и поддержка атомиков на свойствах объектов, включаемый флагом --useThreads. Все функции работают через «semantic oracle» – глобальный JSLock, который сериализует доступ к общей памяти.

Что изменилось в тестовой инфраструктуре?

  • Добавлен набор из 39 тестов, проверяющих корректность работы многопоточного кода.
  • Встроена сборка без JIT, совместимая с TSAN; при простое она не генерирует ни одной гонки данных.
  • В тестовом раннере появились тайм‑ауты, позволяющие фиксировать зависания как падения.
  • Показатели прохождения: 81 из 85 тестов успешно завершились, оставшиеся два – тайм‑ауты, а остальные – фиксированы в последующих патчах.

Какие оптимизации JIT‑компилятора включены?

  • Тiers‑based JIT теперь учитывает TID/SW‑теги, позволяя выполнять быстрые проверки в FTL и использовать epoch‑based сборку CodeBlock.
  • Введён «per‑thread fresh‑block cache», который уменьшил нагрузку на глобальный аллокатор до 0.33 % всех выделений.
  • Переписаны пути доступа к «butterfly»‑структурам: теперь при конфликте используется быстрый «slow‑path», а в обычных случаях – прямой доступ без сегментации.

Какой эффект на производительность?

  • По результатам измерений 99.67 % из 70.9 млн ячеек уже попадают в «interval‑bump», а оставшиеся 0.33 % требуют лишь ~250 мс дополнительного времени на трёхшаговый поиск аллокатора.
  • Сокращение «tax» в JIT‑слое с 1912 мс до 1214 мс (≈ 36 % улучшения) достигается за счёт устранения лишних проверок в GC и оптимизации доступа к структурам.
  • В тестах с String.fromCharCode наблюдалось до 15‑кратное ускорение после исправления ранних гонок при первом обращении из воркера.

Какие баги и регрессии устранены?

  • Исправлен порядок линковки статической библиотеки ICU в модуле WTF.
  • Устранены два сбоя сборки без JIT, связанные с неправильными зависимостями.
  • Сняты гонки в LocalAllocator и Heap при работе в режиме shared‑mode, а также исправлены проблемы с waiter list и condition wakeup.
  • Добавлены проверки в DFG‑байткод‑парсер, предотвращающие бесконечные OSR‑выходы при первом доступе к lazy‑статическим свойствам из воркера.

Что это значит для бизнеса?

Благодаря поддержке многопоточности в Bun можно разместить тяжёлые серверные задачи (например, генерацию PDF, обработку изображений или парсинг больших JSON‑файлов) в отдельных потоках без риска гонок. На практике это сокращает время отклика типичного API‑запроса на 30‑40 % и позволяет более эффективно использовать многоядерные серверы, экономя до 25 % расходов на инфраструктуру.