Подтвердить что ты не робот

Количество потоков, созданных 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?

4b9b3361

Ответ 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

Существует ограничение потока, поэтому ваше приложение не будет уничтожено из-за большого потребления памяти, если у вас есть проблемы с заблокированными потоками (обычно из-за тупика).

Никогда не блокируйте потоки, и вы получите их столько же, сколько ваши ядра.