Что влияет на задержку аудио

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

Если предположить, что аналоговая схема не вносит существенного вклада, то основными факторами, влияющими на задержку аудио на уровне поверхности, являются следующие:

  • Приложение
  • Общее количество буферов в конвейере
  • Размер каждого буфера в кадрах.
  • Дополнительная задержка после процессора приложения, например со стороны DSP

Несмотря на то что список выше может быть точным, он также вводит в заблуждение. Дело в том, что количество и размер буферов – это скорее следствие, чем причина. Обычно происходит следующее: реализуется и тестируется определенная схема буферизации, но во время тестирования слышен щелчок или хлопок, вызванный опустошением или переполнением буфера. Чтобы компенсировать это, разработчик системы увеличивает размер буфера или количество буферов. Это позволяет избежать недополнения или переполнения буфера, но также приводит к нежелательному побочному эффекту в виде увеличения задержки. Дополнительную информацию о размерах буфера можно найти в видео Задержка аудио: размеры буфера.

Лучше понять причины недобора и перебора и устранить их. Это устраняет звуковые артефакты и позволяет использовать буферы меньшего размера или в меньшем количестве, что снижает задержку.

По нашему опыту, наиболее распространенные причины недорасхода и перерасхода бюджета таковы:

  • Планировщик CFS (Completely Fair Scheduler) в Linux
  • цепочки с высоким приоритетом и планированием SCHED_FIFO;
  • инверсия приоритетов
  • длительная задержка планирования
  • долго выполняющиеся обработчики прерываний;
  • длительное время отключения прерываний
  • управление питанием
  • защищенные ядра;

Планирование CFS и SCHED_FIFO в Linux

Планировщик CFS в Linux разработан для справедливого распределения ресурсов ЦП между конкурирующими рабочими нагрузками. Справедливость представлена параметром nice для каждого потока. Значение nice может быть от -19 (наименьшее значение, или наибольшее процессорное время) до 20 (наибольшее значение, или наименьшее процессорное время). В целом все потоки с заданным значением nice получают примерно одинаковое процессорное время, а потоки с меньшим значением nice – больше процессорного времени. Однако CFS "справедлив" только в течение относительно длительных периодов наблюдения. При наблюдении в течение короткого времени CFS может распределять ресурсы ЦП неожиданным образом. Например, он может переключить ЦП с потока с низким значением niceness на поток с высоким значением niceness. В случае с аудио это может привести к недовыполнению или переполнению.

Очевидное решение – не использовать CFS для высокопроизводительных аудиопотоков. Начиная с Android 4.1 такие потоки используют политику планирования SCHED_FIFO, а не SCHED_NORMAL (также называемую SCHED_OTHER), реализованную в CFS.

Приоритеты SCHED_FIFO

Хотя высокопроизводительные аудиопотоки теперь используют SCHED_FIFO, они по-прежнему подвержены влиянию других потоков SCHED_FIFO с более высоким приоритетом. Обычно это рабочие потоки ядра, но также может быть несколько пользовательских потоков, не связанных со звуком, с правилом SCHED_FIFO. Доступные приоритеты SCHED_FIFO находятся в диапазоне от 1 до 99. Аудиопотоки выполняются с приоритетом 2 или 3. Приоритет 1 можно использовать для потоков с более низким приоритетом, а приоритеты 4–99 – для потоков с более высоким приоритетом. Мы рекомендуем по возможности использовать приоритет 1, а приоритеты 4–99 – для потоков, которые гарантированно завершатся за ограниченное время, выполняются с периодом, меньшим, чем у аудиопотоков, и не мешают планированию аудиопотоков.

Планирование с монотонным приоритетом

Подробнее о теории назначения фиксированных приоритетов читайте в статье Википедии Rate-monotonic scheduling (RMS). Важно отметить, что фиксированные приоритеты должны назначаться строго на основе периода, причем более высокие приоритеты должны присваиваться потокам с более короткими периодами, а не на основе предполагаемой "значимости". Непериодические потоки можно моделировать как периодические, используя максимальную частоту выполнения и максимальный объем вычислений за одно выполнение. Если непериодический поток нельзя смоделировать как периодический (например, он может выполняться с неограниченной частотой или неограниченным объемом вычислений за одно выполнение), ему не следует назначать фиксированный приоритет, поскольку это будет несовместимо с планированием истинных периодических потоков.

Инверсия приоритетов

Инверсия приоритетов – классический режим отказа систем реального времени, при котором задача с более высоким приоритетом блокируется на неограниченное время, ожидая, пока задача с более низким приоритетом освободит ресурс, например мьютекс (защищающий общее состояние). Ознакомьтесь со статьей Как избежать инверсии приоритетов, чтобы узнать, как ее предотвратить.

Задержка планирования

Задержка планирования – это время между тем, как поток становится готовым к выполнению, и тем, как завершается переключение контекста, в результате которого поток начинает выполняться на ЦП. Чем меньше задержка, тем лучше. Задержка более двух миллисекунд может привести к проблемам со звуком. Длительная задержка планирования чаще всего возникает при переходе между режимами, например при запуске или отключении ЦП, переключении между защищенным и обычным ядром, переходе из режима полной мощности в режим экономии энергии или при изменении тактовой частоты и напряжения ЦП.

Перебивать

Во многих архитектурах ЦП 0 обрабатывает все внешние прерывания. Поэтому длительный обработчик прерываний может задерживать другие прерывания, в частности прерывания завершения прямого доступа к памяти (DMA) для аудио. Разрабатывайте обработчики прерываний так, чтобы они быстро завершали работу и откладывали длительные задачи в поток (желательно поток CFS или поток SCHED_FIFO с приоритетом 1).

Аналогично, если надолго отключить прерывания на ЦП 0, это приведет к задержке обработки аудиопрерываний. Обычно это происходит во время ожидания спин-блокировки ядра. Проверьте, ограничены ли эти блокировки.

Управление питанием, производительностью и температурой

Управление питанием – это общий термин, который охватывает мониторинг и снижение энергопотребления при одновременной оптимизации производительности. Терморегуляция и охлаждение компьютера – похожие процессы, которые позволяют измерять и контролировать температуру, чтобы избежать повреждений из-за перегрева. В ядре Linux за низкоуровневую политику отвечает регулятор ЦП, а за высокоуровневую – режим пользователя. Мы используем следующие методы:

  • динамическое масштабирование напряжения
  • динамическое масштабирование частоты
  • динамическое включение ядер
  • переключение кластеров;
  • стробирование питания
  • горячее подключение (горячая замена)
  • различные режимы сна (halt, stop, idle, suspend и т. д.);
  • перенос процессов;
  • привязка к процессору;

Некоторые операции управления могут привести к "остановке работы" или периодам, в течение которых процессор приложения не выполняет полезной работы. Поскольку остановка работы может повлиять на звук, управление должно быть рассчитано на допустимую остановку работы в худшем случае, когда звук активен. Конечно, если перегрев неизбежен, предотвращение необратимых повреждений важнее, чем звук!

Защищенные ядра

Ядро безопасности для управления цифровыми правами (DRM) может работать на тех же ядрах процессора приложений, что и основное ядро ОС и код приложения. Любое время, в течение которого на ядре выполняется операция защищенного ядра, фактически является остановкой обычной работы, которая обычно выполняется на этом ядре. В частности, это может быть работа со звуком. По своей природе внутреннее поведение ядра безопасности непостижимо для уровней выше, поэтому любые аномалии производительности, вызванные ядром безопасности, особенно опасны. Например, операции ядра безопасности обычно не отображаются в трассировках переключения контекста. Мы называем это "тёмным временем" – временем, которое проходит, но не может быть зафиксировано. Ядра безопасности должны быть разработаны с учетом допустимого времени остановки работы в худшем случае, когда звук активен.