Какие есть приоритеты QoS в GCD и зачем они нужны
Что проверяют
Понимаете ли вы, что QoS это не просто «приоритет потока», а сигнал системе о том, насколько работа важна пользователю, и от него зависят процессор, энергопотребление и ввод-вывод. Следом почти всегда спрашивают про инверсию приоритетов.
Как отвечать
Назовите классы DispatchQoS.QoSClass от высшего к низшему:
.userInteractive: работа, от которой зависит следующий кадр: анимации, обработка касаний. На этом уровне работает главный поток, тяжёлые вычисления сюда не кладут;.userInitiated: пользователь нажал и ждёт результата, например открытия документа или данных для экрана;.default: промежуточный уровень, его получаетDispatchQueue.global()без аргументов;.utility: долгие задачи, прогресс которых пользователь видит, но не ждёт каждую секунду: загрузка файла с индикатором, импорт. Система балансирует скорость и энергию;.background: пользователь о задаче не знает: индексация, бэкап, предзагрузка. Может сильно замедляться, особенно в режиме энергосбережения;.unspecified: QoS не задан, система выведет его из контекста.
Задают его через DispatchQueue.global(qos: .utility), DispatchQueue(label:qos:), DispatchWorkItem(qos:), у Operation есть свойство qualityOfService. В Swift Concurrency аналог это TaskPriority: .high, .medium, .low, .background и совпадающие с ними по значению .userInitiated и .utility.
По QoS система решает, кому отдать производительные ядра, как объединять таймеры и насколько притормаживать диск.
Где спотыкаются
Не знают про инверсию приоритетов. Если задача .userInitiated синхронно ждёт серийную очередь с работой .background, система поднимет QoS этой работы. С DispatchSemaphore так не выйдет: у семафора нет владельца, и главный поток застрянет в ожидании фоновой задачи. Xcode подсвечивает такие места через Thread Performance Checker.
Ставят .userInteractive всему подряд, «чтобы было быстрее». Важная работа конкурирует с неважной, батарея садится быстрее, а выигрыша нет.
Путают QoS с порядком выполнения. В серийной очереди задачи идут строго по порядку постановки, и более высокий QoS не заставит поздний блок обогнать ранний.