🔥

Тред #7


Вот и вечер наступил, можно поговорить про GCD. Я думаю, многие знакомы базовыми понятиями, что такой serial или concurrent queue. Или методы async и sync.

Поэтому начну с интересного. Есть такая конструкция dispatchPrecondition. Работает похожим образом с assert. Можно использовать для того что бы проверять выполняется ли код например на главной очереди или наоборот

Я буду писать немного хаотично, потому что формат твиттера не самый удобный для публикации технических материалов (во всяком случае для меня), в любом случае в конце будет небольшой анонс. Итак поехали дальше

Следующий важный факт. Работая в многопоточный среде, мы должны стараться максимально избегать context switch, т к это ресурсоемкая операция.

Что мы можем для этого сделать: Использовать как можно реже concurrent queue. Действительно, т к этот тип очереди выполняет свои задачи параллельно, то используется несколько потоков одновременно из thread pool, так же это может привести к thread explosion, но об этом позже

Сократить количество serial queue, несмотря на то что serial queue может использовать только один поток за раз, большое количество serial queue в приложении может привести к ненужному context switch. Apple рекомендует использовать одну очередь под систему (network, db and etc)

Но что же делать если очень хочется больше очередей. Можно использовать target queue hierarchy, это позволяет перенаправить выполнение задач на target queue, которая в свою очередь будет выполнять их на одном потоке.

Thread explosion, как я уже сказал до этого concurrent выполняет свои задачи параллельно на разных потоках. Проблема возникает если ставим большое количество задач на этот тип очереди. Очень много потоков и ограниченное число ядер.

Получается ресурсоемко и в худшем случае чревато дедлоком. Такую ситуацию можно избежать, используя concurrentPerform. Он автоматически определяет необходимое количество потоков для выполнения задач

Так я немного подустал, завтра вечером продолжим. А пока анонс

Продолжаем про GCD. Сегодня поговорим про QoS, quality of service. Механизм приоритезации, чем выше приоритет у задачи, тем больше выделяется процессорного времени на ее выполение, а следовательно энергии

Всего 4 типа: userInteractive - для задач с максимальным приоритетом, например работа UI userInitiated - для задач, когда нужен быстрый ответ например загрузка данных и последующее отображение utility - для продолжительных задач, когда юзер не ожидает немедленного результата

backround - для задач, которые выполняются в бэкграунде.

Главный поток всегда выполняется в userInteractive (наивысшем) qos, т е все задачи, выполняющиеся в главном потоке получают наивысший приоритет

QoS propagation, когда мы не указываем qos напрямую срабатывает automatic propagation. Те присваивается qos вызывающей очереди. Например есть очередь utility, которая ставит на выполнение задачу в другую очередь, в итоге задача будет выполнятся с qos utility

Но есть исключение, если мы ставим задачу из главного потока в другую очередь, то qos понижается с userInteractive до userInitiated

Мы можем указывать напрямую qos при создании очередей и в методах async или sync

В определенных случаях GCD автоматически разруливает qos у задач. Например очередь с qos utility выполняет свою задачу с таким же приоритетом, в какой то момент в очередь ставится задача с более высоким приоритетом.

Что бы избежать priority inversion GCD автоматически поднимает приоритет у уже выполняющейся задачи