Причины задержки звука

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

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

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

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

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

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

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

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

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

Очевидным решением является отказ от использования 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 для тех потоков, которые гарантированно завершаются в течение ограниченного периода времени, выполняются с периодом меньшим, чем период аудиопотоков, и известно, что они не мешают планированию. аудиопотоков.

Монотонное планирование

Дополнительную информацию о теории назначения фиксированных приоритетов см. в статье Википедии «Монотонное планирование скорости» (RMS). Ключевым моментом является то, что фиксированные приоритеты должны распределяться строго на основе периода, при этом более высокие приоритеты должны назначаться потокам с более короткими периодами, а не на основе воспринимаемой «важности». Непериодические потоки можно моделировать как периодические потоки, используя максимальную частоту выполнения и максимальное количество вычислений за выполнение. Если непериодический поток нельзя смоделировать как периодический поток (например, он может выполняться с неограниченной частотой или с неограниченным количеством вычислений за выполнение), то ему не следует назначать фиксированный приоритет, поскольку это было бы несовместимо с планированием истинных периодических потоков. .

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

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

Планирование задержки

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

Прерывания

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

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

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

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

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

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

Ядра безопасности

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