Как устроен ThreadPool
Вопрос
Расскажите, как работает пул потоков .NET и почему он важен для ASP.NET Core.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Рабочие потоки и потоки завершения ввода-вывода
Глобальная очередь и локальные очереди потоков с кражей работы (work stealing)
Минимум потоков создаётся сразу, дальше алгоритм hill climbing и медленный рост
Блокирующие вызовы приводят к голоданию пула
LongRunning задачи получают отдельный поток
Диагностика: dotnet-counters, ThreadPool.GetAvailableThreads
Что могут спросить следом
- Что делает TaskCreationOptions.LongRunning?
- Когда помогает ThreadPool.SetMinThreads и почему это костыль?
Разбор
Пул держит набор рабочих потоков, которые берут задачи из очередей. Есть глобальная очередь и локальные очереди у каждого потока: задача, созданная внутри другой задачи, кладётся в локальную, а простаивающие потоки крадут работу у соседей. Это снижает конкуренцию за общую очередь.
Число потоков регулируется автоматически. До минимума, равного числу ядер, потоки создаются сразу. Дальше алгоритм hill climbing добавляет потоки постепенно, измеряя пропускную способность, и при нехватке реагирует с задержкой. Поэтому, если код блокирует потоки через .Result, Thread.Sleep или синхронный ввод-вывод, начинается голодание: очередь растёт, а потоков не хватает.
ASP.NET Core обрабатывает все запросы на пуле, так что его здоровье напрямую влияет на задержки. Долгую выделенную работу помечают TaskCreationOptions.LongRunning, тогда задача получает свой поток. SetMinThreads иногда ставят как временный костыль, но правильное лечение это асинхронный код. Смотрю dotnet-counters: длину очереди и число потоков пула.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.