Почему выбран неправильный Quality of Service для сервиса и какой лучше использовать в iOS
Что проверяют
Понимаете ли вы, что Quality of Service это заявка на приоритет и энергию, а не способ ускорить код. Дальше проверяют знание уровней, умение выбрать по признаку «ждёт ли пользователь результата прямо сейчас» и понимание инверсии приоритетов.
Как отвечать
QoS это декларация намерения. По ней система выбирает приоритет потока, частоту процессора, приоритет ввода-вывода и то, насколько агрессивно откладывать работу ради батареи. Уровни сверху вниз:
.userInteractive: то, без чего не нарисуется кадр, отрисовка и анимация;.userInitiated: явное действие пользователя, результат нужен сразу, человек смотрит на индикатор;.utility: долгая работа с прогрессом, импорт, синхронизация по запросу;.background: то, чего пользователь не ждёт: префетч, отправка аналитики, индексация. Система спокойно откладывает такую работу.
Типовой неправильный выбор описывается парой: сервис положили на фоновый уровень, а от него зависит первый экран, и на устройстве в режиме энергосбережения запуск растягивается. Обратная ошибка: весь сетевой слой объявили пользовательским уровнем, и он начал конкурировать с отрисовкой.
Задаётся это через DispatchQueue.global(qos:) или очередь со своим qos, а в структурированной конкурентности через приоритет задачи, который наследуют дочерние. Про инверсию: когда высокоприоритетный поток ждёт ресурс, занятый фоновым, система поднимает приоритет владельца, но работает это не для всех примитивов.
Где спотыкаются
Считают, что QoS ускоряет выполнение. Он меняет очерёдность и энергорежим. На свободном устройстве разницы не видно, она вылезает под нагрузкой и на слабом железе, поэтому баг воспроизводится только у пользователей.
Ставят всё на высокий уровень «чтобы быстрее». Когда приоритет одинаковый у всех задач, приоритета нет вообще, страдают отрисовка и расход батареи.
Блокируют вызывающий поток семафором в ожидании фоновой работы. Это классический источник инверсии приоритетов и залипаний интерфейса, лечится асинхронным продолжением, а не повышением уровня фоновой задачи.