На первый взгляд,
Atomics.pause() выглядит как безобидная микро-оптимизация: подсказываем процессору, что поток в спин-локе, и он сам оптимизирует кэш. В production с Worker-пулами на 8+ потоках и SharedArrayBuffer эта иллюзия разбивается о когерентность кэша и деградацию производительности.Ложное пробуждение и протокол MESI
Atomics.pause() не даёт реальной задержки — процессор просто крутит микро-циклы. Когда десяток воркеров висят на Atomics.load() с прикрученным pause(), протокол когерентности (MESI) начинает бешено спамить состоянием Shared->Invalid. Кэш-промахи растут, latency скачет до 100 микросекунд. Типичная ошибка: думать, что pause() автоматически синхронизирует кэш — это не так, он лишь сообщает планировщику о намерении.Дедлоки из-за локального кэша
Если пишешь цикл спин-лока только через
Atomics.load() + pause(), без Atomics.wait(), то длительность паузы неопределённая. Поток может застрять на устаревшем значении в локальном L1-кэше из-за отсутствия барьера памяти. Пример из практики: в API-клиенте с shared очередь запросов на Node.js подняли буст, но через 30 секунд 25% запросов ушли в таймаут — поток просто не видел обновлённый флаг.while (Atomics.load(flag, 0) !== DONE) {
Atomics.pause(); // баг: нет гарантии выхода
// счётчик ложноных выходов растёт
}Практический совет: ограничь число итераций. Первые 10 — один
pause(), до 100 — два, потом — Atomics.wait() с таймаутом. Иначе спин-лок съедает все такты ЦП.NUMA-архитектуры и прыжки задержки
На AMD EPYC или Intel Xeon каждый
pause() триггерит инвалидацию L1/L2, затем обновление через QPI или Infinity Fabric. Задержка скачет в 10-100 раз. В Worker-пуле, разбросанном по разным ядрам, это убивает пропускную способность. Решение — привязка воркеров к сокету через navigator.hardwareConcurrency (браузер) или os.setPriority (Node.js) с группировкой по архитектуре.Предупреждение: не используй
Atomics.pause() сам по себе в высоконагруженных пулах — это прямая дорога к деградации кэша и скачкам памяти. Тестируй под конкретный процессор.Вывод:
Atomics.pause() — это хинт, а не панацея, и в реальных спин-локах без комбинации с экспоненциальным backoff и Atomics.wait() он приносит больше вреда, чем пользы.