Wie Websites CPU und Akku verschwenden
(h.43z.one)- Bei der Untersuchung von White Noise auf einem Linux-Laptop zeigte sich ein Problem, bei dem ein Firefox-Tab den PulseAudio-Audiosink ständig aktiv hält, auch wenn tatsächlich kein Ton zu hören ist
module-suspend-on-idlewar so konfiguriert, dass das Audiogerät nach 10 Sekunden angehalten wird, aber wenn eine Website einen AudioContext erstellt, wechselt der Sink nicht inIDLE/SUSPENDED- Dasselbe Verhalten trat bei Outlook-Webbenachrichtigungen, einem Klick auf x.com, der Sprachwiedergabe von Google Translate und in der Discord-Web-App auf; schon
new AudioContext()reichte aus, damit das Rauschen begann - In Messungen lag die CPU-Auslastung von
pulseaudioohne Rauschen bei 0,0 %, mit Rauschen jedoch bei 4,7 %, und der Stromverbrauch des Systems stieg um etwa 1,5 W AudioContext.suspend()kann den Zugriff auf die Audio-Hardware stoppen und so CPU- und Akkuverbrauch senken, aber Firefox beendet die Verschwendung nicht wie Chrome nach einer gewissen Zeit automatisch
Das Problem: Der Audiosink schläft nicht ein
- Auf einem neuen Laptop war aus den Lautsprechern ein leises, aber störendes White Noise zu hören, selbst wenn keine Musik oder sonstige Audiodaten abgespielt wurden
- Um den PulseAudio-Status unter Linux zu prüfen, wurde
pactl list sinks shortverwendet- Der Status eines Audiosinks erscheint als
IDLE,SUSPENDEDoderRUNNING - Wenn der Sink
SUSPENDEDwar, blieben die Lautsprecher ruhig - Bei
IDLEoderRUNNINGkonnte White Noise auftreten, auch ohne tatsächliche Audiowiedergabe
- Der Status eines Audiosinks erscheint als
- In
/etc/pulse/default.paund/etc/pulse/system.pawarmodule-suspend-on-idlegeladen- Laut Konfiguration sollte der Audiosink nach 10 Sekunden Inaktivität automatisch angehalten werden
- In manchen Situationen wechselte der Sink jedoch nicht in
IDLEund erreichte daher auch nieSUSPENDED
Warum inaktives Audio Strom verbraucht
module-suspend-on-idletrennt Sinks und Sources, die eine gewisse Zeit lang mit keinem Stream verbunden sind, vom Backend- Der wichtigste Effekt ist Energieeinsparung
- Wenn PulseAudio auch im Leerlauf leere Daten an die Soundkarte sendet, verbraucht ALSA mehr CPU-Zyklen
- Wenn nicht geplant ist, dauerhaft einen aktiven Stream zu halten, ist ein kurzer Timer für die Energieeinsparung vorteilhafter
Die Ursache ließ sich auf Firefox-Tabs und Websites eingrenzen
- Immer wenn White Noise zu hören war, wurde mit
pactl list sink-inputsgeprüft, welches Programm den Audiosink nutzt - Die Ursache war jedes Mal Firefox
- Unter den offenen Tabs war keiner, der tatsächlich Ton hätte abspielen sollen
- Es gab auch keine stummgeschalteten Videos
- Zur i3-Statusleiste wurde ein kleines Skript hinzugefügt, das eine rote Markierung anzeigt, wenn der Audiosink auf
RUNNINGwechselt - Zunächst wirkte es so, als seien die Benachrichtigungstöne von outlook.office.com in einem angehefteten Tab die Ursache
- Beim Eingang einer E-Mail begann das White Noise
- Es stoppte erst nach einem Neuladen des Tabs oder einem Neustart von Firefox
- Später wurde dasselbe Verhalten auch auf anderen Websites bestätigt
- Auf x.com begann das Rauschen sofort nach einem beliebigen Klick
- Auch beim Anhören der Übersetzungsausgabe auf translate.google.com trat das Rauschen auf
- In der Discord-Web-App zeigte sich derselbe Effekt schon dann, wenn sie einfach geöffnet blieb
Ergebnisse der CPU- und Strommessungen
- Ohne White Noise wurde die CPU-Auslastung von
pulseaudiomit 0,0 % angezeigt - Im selben Umfeld lagen die Strommesswerte meist im Bereich von 4,2 bis 5,1 W
- Mit White Noise stieg die CPU-Auslastung von
pulseaudioauf 4,7 % - Dabei lagen die Strommesswerte meist im Bereich von 5,8 bis 6,7 W
- Der Unterschied ist nicht vernachlässigbar und lässt sich auf ungefähr 1,5 W mehr zusammenfassen
WebAudio API und AudioContext
- In HTML/JavaScript gibt es zwei Wege, Audio wiederzugeben: das
<audio>-Tag und die WebAudio API - Für dynamische Klangwiedergabe wie bei Outlook wird die WebAudio API verwendet; um Audioverarbeitung zu nutzen, muss zunächst ein
AudioContexterzeugt werden - Das Problem ist, dass schon die Ausführung von
const audioCtx = new AudioContext();White Noise aus den Lautsprechern verursachen kann - Als Testseite wird https://editor.43z.one/sqare/i angegeben
AudioContext.suspend()hält den Zeitfortschritt des Audiokontexts an und pausiert den Zugriff auf die Audio-Hardware, wodurch CPU- und Akkuverbrauch sinken könnenAudioContext.resume()startet den Zeitfortschritt eines angehaltenen Audiokontexts wieder
Unterschiede zwischen Firefox und Chrome
- Viele Websites erstellen einen
AudioContext, obwohl sie nicht sofort Ton ausgeben müssen, und setzen ihn anschließend nicht auf suspend - Chrome beendet die Verschwendung von CPU und Akku nach einer gewissen Zeit automatisch
- Firefox stoppt nicht automatisch und behält den Zustand bei, in dem es weiterhin White Noise erzeugt
- Die unmittelbare Ursache liegt zwar bei den Websites, doch es bleibt die Kritik, dass Firefox seine Nutzer nicht vor dieser Ressourcenverschwendung schützt
- Es besteht außerdem der Verdacht, dass bei verbundenen Bluetooth-Kopfhörern nach einem Klick auf x.com ebenfalls die Übertragung von White Noise beginnt und so deren Akku verschwendet wird
Vorläufige Gegenmaßnahme: AudioContext Suspender
- Um das Problem abzumildern, wurde eine Erweiterung entwickelt, die
AudioContextautomatisch anhält und ihn wieder startet, wenn eine Website Ton abspielen will - Die Erweiterung ist nicht perfekt
- Das erneute Starten braucht etwas Zeit
- Da es mehrere Wege gibt, Audio zu starten, wird der Kontext möglicherweise nicht immer wieder aufgenommen
- Für den vorgesehenen Zweck ist sie dennoch ausreichend
- Verwandte Links
- Zugehörige Bugzilla-Tickets
1 Kommentare
Hacker-News-Kommentare
Wie man sich vorstellen kann, ist es deutlich komplizierter, als einen
AudioContextnach einer gewissen Zeit der Stille zu pausieren, aber ich denke, es lässt sich trotzdem beheben. Andere Browser haben es bereits getan, und es gibt auch Kompromisse, die vertretbar sind.Quelle: Ich habe in Firefox viel von der Funktionalität in diesem Bereich implementiert und bin außerdem Editor des Web-Audio-API-Standards.
Die meisten verstehen die hier beschriebenen Umstände. Es gibt viel zu tun, und die Zeit ist begrenzt.
Ich habe selbst erlebt, dass Firefox-Entwickler mehr tun als erwartet, damit viel genutzte Websites für Nutzer korrekt funktionieren. Ich weiß, wie weit ihr geht, wenn ein Problem Nutzer betrifft, also bitte weiter so.
Da Audioverarbeitung je nach Browser-Engine und Betriebssystem unterschiedlich implementiert ist, entsteht eine Signatur, wenn man einen völlig unhörbaren Ton abspielt und ihn über die API wieder aufnimmt.
Mit dieser Signatur lässt sich prüfen, ob der Browser den User-Agent fälscht, im Headless-Modus läuft oder zu allen möglichen Sonderfällen gehört, die nicht nach einem echten Nutzer aussehen, der gerade ein Produkt kauft.
https://github.com/fingerprintjs/fingerprintjs/blob/3201a7d6...
Im Tab erscheint kein Wiedergabe-Icon, und selbst wenn man den Tab stummschaltet, hört das Geräusch nicht auf.
Selbst wenn man Firefox im Windows-Lautstärkemixer stummschaltet, hört der Ton nicht auf.
Korrektur: Für Desktop-Nutzer ist diese Erweiterung eigentlich ziemlich schlecht. Es ist noch viel störender, wenn das weiße Rauschen ständig an- und ausgeht.
Deshalb habe ich mir selbst ein Programm geschrieben, das die Ausgabe offen hält, ohne Daten über die Leitung zu schicken, damit die Ausgabe nicht in den Idle-Zustand wechselt.
Im Laptop-Kontext ergibt das allerdings wenig Sinn; dort ist Energiesparen angebracht.
Im Windows-Treiber gibt es eine Option, den Stream auf Always On zu setzen. Ich wünschte, macOS hätte das auch.
play -qn &starten lassen.Eine Nachrichtenseite hat offenbar Audio abgespielt und dabei immer wieder neue Anzeigen geladen, und wegen des Audios ging der Tab nicht in den Energiesparzustand. Wegen unerwarteter Datenkosten musste ich am Ende zu Chrome wechseln.
Es gab also kein weißes Rauschen, aber audio-bedingten Stromverbrauch: https://bugzilla.mozilla.org/show_bug.cgi?id=1821102
Selbst jetzt nutzt
coreaudiodauf dem Mac 20 % CPU, obwohl nichts abgespielt wird. Das ruiniert die Akkulaufzeit wirklich, und ich überlege, bis zur Behebung auf einen anderen Browser umzusteigen, aber ich möchte Firefox nicht wegen etwas aufgeben, das so nebensächlich wirkt.Update: Scheint ein verwandter, aber anderer Bug zu sein.
https://source.chromium.org/chromium/chromium/src/+/main:med...
Im Grunde wird nach etwa 30 Sekunden erkannter Stille von einer vom Audio-Gerät des Betriebssystems gestützten Sink auf eine Null-Sink umgeschaltet.
Zur Einordnung: Da diese Methode eine andere Uhr als das Audio-Gerät verwendet, gab es einige Berichte, dass bei bestimmten Tönen Verzerrungen auftreten, wenn der Kontext später tatsächlich genutzt wird. Der Workaround besteht darin, dass die Website die im Artikel erwähnte suspend/resume API verwendet.
audioContextintern implementiert ist, aber offenbar steckt darin einiges, das ziemlich clever und dynamisch arbeiten soll. Einen Benachrichtigungston abzuspielen wirkt ähnlich, als würde man stattimg href *.svgmit D3 ein SVG zeichnen.Ich frage mich, ob es so etwas wie einen Service-Worker-Hook gibt, mit dem man einfache, wiederholbare Dinge wie Benachrichtigungs-Handler bei einer effizienteren API auf niedrigerer Ebene registrieren kann.
In Firefox 134.0.1 unter macOS höre ich gar nichts.