Ответ
Thread Explosion — это ситуация, когда приложение создаёт чрезмерное количество потоков, превышающее возможности системы, что приводит к деградации производительности.
Основные причины:
- Неконтролируемое использование
DispatchQueue.global()для запуска множества параллельных задач. - Рекурсивные или вложенные асинхронные вызовы, каждый из которых порождает новый поток.
- Использование
syncвызовов на concurrent очередях, что может приводить к блокировкам и созданию дополнительных потоков для избежания deadlock.
Последствия:
- Высокая нагрузка на CPU из-за частого переключения контекста между потоками.
- Увеличение потребления памяти (каждый поток имеет свой стек).
- Рост задержек (latency) и возможные краши из-за исчерпания системных ресурсов.
Решение и best practices:
- Используйте ограниченные очереди. Вместо неограниченной глобальной очереди создавайте свои с явным указанием типа (
concurrentилиserial). - Контролируйте параллелизм через
OperationQueue. УстановитеmaxConcurrentOperationCountдля ограничения количества одновременно выполняемых задач. - Применяйте шаблоны, такие как пул потоков или семафоры (
DispatchSemaphore), для регулирования нагрузки.
Пример плохого и хорошего кода:
// ❌ Плохо: Риск Thread Explosion
for i in 0..<1000 {
DispatchQueue.global().async {
performHeavyTask(index: i)
}
}
// ✅ Лучше: Контролируемый параллелизм
let processingQueue = OperationQueue()
processingQueue.maxConcurrentOperationCount = ProcessInfo.processInfo.activeProcessorCount // Ограничение по числу ядер
for i in 0..<1000 {
processingQueue.addOperation {
performHeavyTask(index: i)
}
}