Количество потоков, созданных GCD?
Есть ли хорошая документация о том, сколько потоков создано GCD?
В WWDC они рассказали нам, что они смоделированы вокруг ядер процессора. Однако, если я приведу этот пример:
for (int i=1; i<30000; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSThread sleepForTimeInterval:100000];
});
}
он открывает 66 потоков, даже на iPad1. (Он также открывает 66 потоков при вызове Lion изначально). Почему 66?
Ответы
Ответ 1
Сначала 66 == 64 (максимальный размер пула потоков GCD) + основной поток + некоторый другой случайный поток без GCD.
Во-вторых, GCD не волшебство. Он оптимизирован для хранения процессора с кодом, который в основном связан с процессором. "Магия" GCD заключается в том, что она динамически создает больше потоков, чем процессоры, когда рабочие элементы непреднамеренно и ненадолго ждут завершения операций.
Сказав это, код может путать планировщик GCD, преднамеренно спать или ждать событий, а не использовать источники отправки для ожидания событий. В этих сценариях блок работы эффективно реализует свой собственный планировщик, и поэтому GCD должен предположить, что поток был кооптирован из пула потоков.
Короче говоря, пул потоков будет работать оптимально, если ваш код предпочитает dispatch_after() над "sleep()", как API, и отправляет источники по циклам событий handcrafted (Unix select()/poll(), Cocoa runloops, или переменные состояния POSIX).
Ответ 2
В документации избегается упоминание количества созданных потоков. В основном потому, что оптимальное количество потоков сильно зависит от контекста.
Одна проблема с Grand Cendral Dispatch заключается в том, что она будет порождать новый поток, если выполняется работающая задача. То есть, вам следует избегать блокировки при использовании GCD, поскольку он имеет больше потоков, чем ядра, субоптимальные.
В вашем случае GCD обнаруживает, что задача неактивна, и порождает новый поток для следующей задачи.
Почему 66 - это предел выше меня.
Ответ 3
Количество занятых потоков равно ядру процессора. Заблокированные потоки (вы блокируете их с помощью sleepForTimeInterval
) не учитываются.
Если вы измените свой код на это (Swift):
for _ in 1..<30000 {
DispatchQueue.global().async {
while true {}
}
}
вы увидите, что создано только 2 темы (на iPhone SE):
![enter image description here]()
Существует ограничение потока, поэтому ваше приложение не будет уничтожено из-за большого потребления памяти, если у вас есть проблемы с заблокированными потоками (обычно из-за тупика).
Никогда не блокируйте потоки, и вы получите их столько же, сколько ваши ядра.