Вытеснение и work stealing
Во время пика одна горутина зажала всё ядро: цикл хеширования крутился без единой блокировки, и соседние запросы встали. Инцидент закрыли после разбора того, как планировщик обычно не даёт такому случиться.
планировщик обычно не даёт одной горутине зажать ядро — асинхронное вытеснение (с Go 1.14) снимает горутину, работающую дольше примерно 10 мс, но это не строгая гарантия; work stealing перераспределяет горутины между занятыми и пустующими P.
Вытеснение
Если горутина крутит бесконечный цикл без блокировок, кооперативного «уступить процессор» у неё нет. Ранние версии Go страдали: такая горутина могла зажать ядро. С Go 1.14 планировщик вытесняет асинхронно: sysmon (фоновый поток runtime) шлёт сигнал, и горутина, работающая дольше примерно 10 мс, снимается с исполнения. Порог приблизителен, и вытеснение может отложиться до безопасной точки — это не строгая гарантия справедливости.
Что здесь показано
- Стек — локальные переменные функции.
i = 3— значение;p = ptr → 10— указатель на значение;b = "hello"— срез (заголовок: указатель + длина + ёмкость). - Куча — данные, на которые ссылаются переменные:
rodata— байты строки-литерала (в бинарнике),данные N Б— бэкинг-массив слайса,строка— динамическая строка. - Горутины — лёгкие потоки Go: статус (running/runnable/waiting…), функция, в которой каждая сейчас находится, размер стека (растёт по мере работы) и пометка «из main» — горутина запущена из твоего кода.
- GC — сборщик мусора: фаза (off/mark) и число завершённых циклов.
Поэтому долгий CPU-bound код не вешает остальные горутины — их просто вклинивают в расписание.
Work stealing
Локальные очереди P заполняются неравномерно: одному P досталась пачка горутин, другой простаивает. Когда P пустеет, он «ворует» половину очереди у случайного занятого P. Так работа перетекает туда, где есть свободный контекст, без центрального диспетчера.
Почему это работает без пауз
Обе механики не требуют остановки мира: вытеснение — сигнал конкретной горутине, воровство — атомарные операции над очередями. Планировщик остаётся дешёвым, а загрузка ядер — равномерной. Отсюда практический вывод: не пиши код, который «ждёт уступки» от других горутин — вытеснение и воровство о балансе заботятся сами.
Вы узнаете:
- как sysmon следит за состоянием мира
- почему выгодно воровать половину очереди, а не одну горутину
Проверьте себя
Один P опустел и ищет работу. Как он её получает?
Почему воруют половину очереди, а не всё и не одну?
Порог вытеснения «примерно 10 мс» — строгая гарантия справедливости?
правильных ответов
Вытеснение (порог ~10 мс приблизителен, не строгая гарантия) обычно не даёт зажать ядро, work stealing выравнивает загрузку P.
10 000 ₽ · 60 минут · онлайн