SeniorПроизводительностьРедкоЕщё не отвечали
Троттлинг на счётном примитиве DispatchSemaphore вызывает взрывной рост потоков — продиагностируйте и переработайте его
Каждый заблокированный wait() паркует поток GCD; не видя простаивающих, GCD плодит новые — десятки застревают на семафоре (взрыв потоков), тратя память. Переработка без блокировки потоков — лимит через maxConcurrentOperationCount или async/await.
- ✗Считают, что заблокированный поток ничего не стоит держать
- ✗Думают, что меньшее значение семафора мешает GCD плодить потоки
- ✗Меняют блокирующий
wait()на блокирующийsync, что тоже паркует потоки
- →Почему GCD создаёт новые потоки, когда существующие заблокированы?
- →Как async/await ограничивает параллелизм, не паркуя поток?
Причина — блокировка потоков. Каждый semaphore.wait() на глобальной очереди паркует рабочий поток; GCD, не видя свободных, поднимает новые, и десятки застревают на семафоре.
// ❌ было: блокирует рабочие потоки GCD
let sema = DispatchSemaphore(value: 4)
for job in jobs {
DispatchQueue.global().async {
sema.wait()
defer { sema.signal() }
job.run()
}
}
// ✅ стало: ограничиваем параллелизм, не блокируя потоки
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 4
jobs.forEach { job in queue.addOperation { job.run() } }
Либо async/await: withTaskGroup с не более чем 4 одновременными задачами — приостановка вместо блокировки, поток при этом освобождается.