Faktoren, die die Audiolatenz beeinflussen

Auf dieser Seite liegt der Schwerpunkt auf den Faktoren, die zur Ausgabelatenz beitragen. Die Ausführungen gelten jedoch auch für die Eingabelatenz.

Angenommen, die analoge Schaltung trägt nicht wesentlich dazu bei, sind die Hauptfaktoren für die Audiolatenz auf der Oberfläche:

  • Wissen anwenden
  • Gesamtzahl der Puffer in der Pipeline
  • Größe jedes Puffers in Frames
  • Zusätzliche Latenz nach dem App-Prozessor, z. B. von einem DSP

Die oben genannte Liste der Mitwirkenden ist zwar korrekt, aber auch irreführend. Das liegt daran, dass die Pufferanzahl und die Puffergröße eher ein Effekt als eine Ursache sind. Normalerweise wird ein bestimmtes Pufferschema implementiert und getestet. Während des Tests ist jedoch ein Audiounterlauf oder -überlauf als „Klick“ oder „Pop“ zu hören. Um dies auszugleichen, erhöht der Systemdesigner dann die Puffergrößen oder die Pufferanzahl. Dies hat zwar den gewünschten Effekt, dass Unter- oder Überläufe vermieden werden, aber auch die unerwünschte Nebenwirkung, dass die Latenz erhöht wird. Weitere Informationen zu Puffergrößen findest du im Video Audiolatenz: Puffergrößen.

Besser ist es, die Ursachen für Unter- und Überlauf zu ermitteln und diese zu beheben. Dadurch werden hörbare Artefakte eliminiert und es können noch kleinere oder weniger Puffer verwendet werden, was die Latenz reduziert.

Unserer Erfahrung nach sind die häufigsten Ursachen für Unter- und Überlauf:

  • Linux CFS (Completely Fair Scheduler)
  • Threads mit hoher Priorität mit SCHED_FIFO-Planung
  • Prioritätsumkehr
  • lange Planungslatenz
  • Lang andauernde Unterbrechungs-Handler
  • long interrupt disable time
  • Energiesparmodus
  • Sicherheitskerne

Linux CFS und SCHED_FIFO-Planung

Der Linux CFS ist so konzipiert, dass er für konkurrierende Arbeitslasten, die sich eine gemeinsame CPU-Ressource teilen, fair ist. Diese Fairness wird durch einen pro Thread festgelegten nice-Parameter dargestellt. Der Wert für „nice“ kann zwischen -19 (niedrigste Priorität, d. h. die größte zugewiesene CPU-Zeit) und 20 (höchste Priorität, d. h. die geringste zugewiesene CPU-Zeit) liegen. Im Allgemeinen erhalten alle Threads mit einem bestimmten Nice-Wert ungefähr dieselbe CPU-Zeit. Threads mit einem numerisch niedrigeren Nice-Wert sollten mehr CPU-Zeit erhalten. Die CFS ist jedoch nur über relativ lange Beobachtungszeiträume hinweg „fair“. Bei kurzfristigen Beobachtungszeiträumen kann CFS die CPU-Ressourcen auf unerwartete Weise zuweisen. So kann die CPU beispielsweise von einem Thread mit einem numerischen Wert für die „Niceness“ von 0 auf einen Thread mit einem numerischen Wert für die „Niceness“ von 100 umgestellt werden. Bei Audio kann dies zu einem Unter- oder Überlauf führen.

Die naheliegende Lösung besteht darin, CFS für leistungsstarke Audiothreads zu vermeiden. Ab Android 4.1 wird für solche Threads die Planungsrichtlinie SCHED_FIFO anstelle der von CFS implementierten Planungsrichtlinie SCHED_NORMAL (auch SCHED_OTHER genannt) verwendet.

SCHED_FIFO-Prioritäten

Auch wenn die leistungsstarken Audiothreads jetzt SCHED_FIFO verwenden, sind sie weiterhin anfällig für andere SCHED_FIFO-Threads mit höherer Priorität. Das sind in der Regel Kernel-Arbeitsthreads, es kann aber auch einige nicht audiobezogene Nutzerthreads mit der Richtlinie SCHED_FIFO geben. Die verfügbaren SCHED_FIFO-Prioritäten reichen von 1 bis 99. Die Audiothreads werden mit der Priorität 2 oder 3 ausgeführt. So bleibt Priorität 1 für Threads mit niedrigerer Priorität und die Prioritäten 4 bis 99 für Threads mit höherer Priorität verfügbar. Wir empfehlen, nach Möglichkeit Priorität 1 zu verwenden und die Prioritäten 4 bis 99 für Threads zu reservieren, die innerhalb eines bestimmten Zeitraums abgeschlossen werden, mit einem kürzeren Intervall als das der Audiothreads ausgeführt werden und nicht mit der Planung von Audiothreads interferieren.

Rate-monotonic scheduling

Weitere Informationen zur Theorie der Zuweisung fester Prioritäten finden Sie im Wikipedia-Artikel Rate-Monotonic Scheduling (RMS). Ein wichtiger Punkt ist, dass feste Prioritäten ausschließlich auf der Grundlage des Zeitraums zugewiesen werden sollten. Dabei werden Threads mit kürzeren Zeiträumen eine höhere Priorität zugewiesen, nicht aufgrund der wahrgenommenen „Wichtigkeit“. Nicht periodische Threads können als periodische Threads modelliert werden, wobei die maximale Ausführungshäufigkeit und die maximale Berechnung pro Ausführung verwendet werden. Wenn ein nicht periodischer Thread nicht als periodischer Thread modelliert werden kann (z. B. wenn er mit unbegrenzter Häufigkeit oder unbegrenzter Berechnung pro Ausführung ausgeführt werden kann), sollte ihm keine feste Priorität zugewiesen werden, da dies nicht mit der Planung echter periodischer Threads kompatibel ist.

Prioritätsumkehr

Die Prioritätsinversion ist ein klassischer Fehlermodus von Echtzeitsystemen, bei dem eine Aufgabe mit höherer Priorität für eine unbegrenzte Zeit blockiert wird, während eine Aufgabe mit niedrigerer Priorität eine Ressource freigibt, z. B. einen Sperrbildschirm, der einen freigegebenen Status schützt. Im Artikel Prioritätsinversion vermeiden finden Sie Informationen zu Methoden, mit denen sich das Problem beheben lässt.

Planungslatenz

Die Planungslatenz ist die Zeitspanne zwischen dem Zeitpunkt, zu dem ein Thread zur Ausführung bereit ist, und dem Abschluss des resultierenden Kontextwechsels, sodass der Thread tatsächlich auf einer CPU ausgeführt wird. Je kürzer die Latenz, desto besser. Werte über zwei Millisekunden führen zu Problemen mit dem Audiosignal. Eine lange Planungslatenz tritt am ehesten bei Modusübergängen auf, z. B. beim Starten oder Herunterfahren einer CPU, beim Wechseln zwischen einem Sicherheitskernel und dem normalen Kernel, beim Wechseln vom Vollleistungs- in den Energiesparmodus oder beim Anpassen der CPU-Taktfrequenz und -Spannung.

Unterbrechungen

In vielen Designs verarbeitet CPU 0 alle externen Unterbrechungen. Ein lang laufender Interrupt-Handler kann also andere Interrupts verzögern, insbesondere DMA-Fertigstellungs-Interrupts (Direct Memory Access). Entwerfen Sie Unterbrechungsabarbeiter so, dass sie schnell abgeschlossen werden und lange Arbeiten an einen Thread übergeben werden (vorzugsweise einen CFS-Thread oder SCHED_FIFO-Thread mit Priorität 1).

Wenn Interrupts auf CPU 0 für einen längeren Zeitraum deaktiviert werden, hat dies ebenfalls zur Folge, dass die Bearbeitung von Audio-Interrupts verzögert wird. Lange Zeiträume für die Unterbrechungsdeaktivierung treten in der Regel beim Warten auf eine Spinlock des Kernels auf. Prüfen Sie diese Spin-Locks, um sicherzustellen, dass sie begrenzt sind.

Energieversorgung, Leistung und Temperaturverwaltung

Energieverwaltung ist ein weit gefasster Begriff, der Maßnahmen zur Überwachung und Reduzierung des Energieverbrauchs bei gleichzeitiger Optimierung der Leistung umfasst. Die Temperaturverwaltung und die Computerkühlung sind ähnlich, zielen aber darauf ab, die Wärme zu messen und zu steuern, um Schäden durch Überhitzung zu vermeiden. Im Linux-Kernel ist der CPU-Taktregler für die Low-Level-Richtlinie verantwortlich, während im Nutzermodus die High-Level-Richtlinie konfiguriert wird. Zu den verwendeten Techniken gehören:

  • dynamische Spannungsskalierung
  • dynamische Frequenzskalierung
  • Aktivierung des dynamischen Kerns
  • Cluster Switching
  • Power Gating
  • Hotplug (Hot-Swap)
  • verschiedene Ruhemodi (Halt, Stopp, Inaktivität, Aussetzen usw.)
  • Prozessmigration
  • Prozessoraffinität

Einige Verwaltungsvorgänge können zu „Arbeitsunterbrechungen“ oder Zeiten führen, in denen der Anwendungsprozessor keine nützliche Arbeit ausführt. Diese Arbeitsunterbrechungen können die Audioqualität beeinträchtigen. Daher sollte die Verwaltung so konzipiert sein, dass eine akzeptable Worst-Case-Arbeitsunterbrechung möglich ist, während die Audiowiedergabe aktiv ist. Wenn ein thermischer Durchschlag bevorsteht, ist es natürlich wichtiger, bleibende Schäden zu vermeiden, als den Audiostream aufrechtzuerhalten.

Sicherheitskerne

Ein Sicherheitskernel für die Digital Rights Management (DRM) kann auf denselben Anwendungsprozessorkernen ausgeführt werden, die auch für den Hauptbetriebssystemkernel und den Anwendungscode verwendet werden. Wenn ein Sicherheitskernvorgang auf einem Kern aktiv ist, wird die normale Arbeit, die normalerweise auf diesem Kern ausgeführt wird, effektiv unterbrochen. Dazu gehören insbesondere Audioarbeiten. Das interne Verhalten eines Sicherheitskerns ist von höheren Schichten aus nicht nachvollziehbar. Daher sind Leistungsanomalien, die durch einen Sicherheitskern verursacht werden, besonders schädlich. Sicherheitskernvorgänge werden beispielsweise in der Regel nicht in Kontextwechsel-Spuren aufgeführt. Wir nennen dies „dunkle Zeit“ – Zeit, die vergeht, aber nicht beobachtet werden kann. Sicherheitskerne sollten für eine akzeptable Worst-Case-Arbeitsunterbrechung bei aktiver Audiowiedergabe ausgelegt sein.