Watt The Fox?

how websites waste CPU cycles & battery and Firefox lets them

by h43z (hompage)

I recently got a new notebook and noticed that the speakers would occasionally emit a faint but annoying white noise. This issue was only noticeable in a quiet room when no music or other audio was playing through the speakers.

After some digging, I came across the following command

pactl list sinks short

(check powercfg /requests on windows?!)

This command lists all available audio sinks for PulseAudio on Linux along with their current state. The states can be one of the following: IDLE, SUSPENDED, or RUNNING.

I observed that the speakers remained silent whenever the audio sink was in the SUSPENDED state. However, the white noise would sometimes occur when the sink was in IDLE or RUNNING, even when no music or sounds were being played.

Even though I had the setting to automatically suspend the audio sinks after 10 seconds of inactivity:

% grep -R module-suspend-on-idle /etc/pulse/
/etc/pulse/default.pa:load-module module-suspend-on-idle
/etc/pulse/system.pa:load-module module-suspend-on-idle

But sometimes, the sink never went IDLE and therefore never got SUSPENDED.

The manual for module-suspend-on-idle says:

Since 0.9.11. Disconnects sinks and sources from their backend after a
predetermined amount of idle time. Idle time is accumulated when the sink/source
in question is not connected to any streams.

Advantages: Saves power. ALSA uses considerably more CPU cycles when pulseaudio
has to send empty data to the soundcard during idle. If you don't plan to have
an active stream all the time, set the timer to a low value for best power savings.

I began using the command:

pactl list sink-inputs

whenever I noticed the white noise, trying to identify which program was using the audio sink.

It turned out to always be Firefox. However, none of the open tabs were supposed to play any sound—not even muted videos.

To get behind what was going on, I created a small script for my i3 status bar. The script displays a red indicator whenever the audio sink switched to the RUNNING state.

The culprit seemed to be the notification sound from my pinned tab of outlook.office.com. Whenever I received an email, the white noise would start and wouldn't stop until I reloaded the tab or restarted Firefox.

This issue was not just about the annoying white noise—it was also draining my notebook’s battery faster.

Here’s the CPU/power consumption without the white noise:

$ htop -F pulseaudio
    PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+ ▽Command
   3770 h43z        9 -11 1094M 30924 21580 S  0.0  0.1 10:57.51 /usr/bin/pulseaudio --daemonize=no --log-target=journal

$ powerstat -d0 3
  Time    User  Nice   Sys  Idle    IO  Run Ctxt/s  IRQ/s  Watts
20:54:31   0.8   0.1   0.5  98.6   0.0    1    957    900   4.42
20:54:34   0.0   0.1   0.2  99.7   0.0    1    728    591   4.34
20:54:37   0.3   0.1   1.3  98.2   0.1    1   1444   1241   4.32
20:54:40   0.0   0.1   0.1  99.8   0.0    1    695    556   4.46
20:54:43   0.4   0.1   0.4  99.1   0.0    1   1322    935   5.08
20:54:46   0.1   0.1   0.4  99.4   0.0    1   1216    944   4.50
20:54:49   0.0   0.1   0.1  99.8   0.0    1   1032    742   4.45
20:54:52   0.0   0.1   0.2  99.7   0.1    1    952    667   4.44
20:54:55   0.0   0.0   0.3  99.7   0.0    1    873    676   4.31
20:54:58   0.2   0.1   1.1  98.4   0.1    1   1508   1244   4.26
20:55:01   0.1   0.1   0.3  99.5   0.0    1   1191    877   4.42
20:55:04   0.1   0.1   0.3  99.6   0.0    1    994    757   4.44
20:55:07   0.6   0.1   0.3  99.0   0.0    1   1304    947   4.20
20:55:10   0.1   0.1   0.2  99.6   0.0    1    953    696   4.30
20:55:13   0.0   0.2   0.3  99.5   0.0    1    903    701   4.17

And here with the noise:

$ htop -F pulseaudio
    PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+ ▽Command
   3770 h43z        9 -11 1094M 30924 21580 S  4.7  0.1 10:56.31 /usr/bin/pulseaudio --daemonize=no --log-target=journal

$ powerstat -d0 3
  Time    User  Nice   Sys  Idle    IO  Run Ctxt/s  IRQ/s  Watts
20:52:42   0.7   0.1   1.3  98.0   0.0    1   3460   1542   5.98
20:52:45   0.7   0.1   1.4  97.8   0.0    2   3723   1788   6.00
20:52:48   0.7   0.1   1.4  97.8   0.0    3   3487   1719   5.99
20:52:51   1.1   0.1   1.4  97.5   0.0    1   3916   1861   6.34
20:52:54   0.6   0.1   1.3  98.0   0.0    1   3514   1692   5.89
20:52:57   0.7   0.1   1.8  97.3   0.1    1   3956   2067   6.57
20:53:00   0.8   0.1   1.1  98.0   0.0    1   3534   1522   5.88
20:53:03   0.6   0.1   1.2  98.0   0.0    1   3437   1626   5.87
20:53:06   0.7   0.0   1.2  98.0   0.0    1   3400   1700   5.94
20:53:09   0.8   0.1   1.3  97.9   0.0    2   3474   1421   5.88
20:53:12   0.7   0.1   1.2  98.0   0.0    1   3317   1441   5.84
20:53:15   1.3   0.1   1.6  97.0   0.0    4   3841   1777   5.83
20:53:18   1.1   0.1   1.6  97.1   0.1    1   4161   1906   5.87
20:53:21   0.7   0.1   1.3  97.9   0.0    1   3422   1505   5.90
20:53:24   1.5   0.1   1.7  96.8   0.0    3   3430   1707   5.91
20:53:27   0.7   0.1   1.3  97.9   0.0    1   3375   1511   6.73
20:53:30   0.7   0.0   1.2  98.0   0.0    1   3572   1563   6.13

It's not nothing—about 1.5 Watt more.

So, with a heavy heart, I decided to disable email notifications—even though I really wanted to keep them—but eliminating the white noise was my priority.

I thought I had “fixed” the problem. Of course, I blamed Microsoft, right?

But the red sound indicator on my i3 status bar kept lighting up occasionally.

And it turned out other websites were also triggering the white noise.

For instance, as soon as I clicked anywhere on x.com, the noise started. Similarly, whenever I listened to a translation on translate.google.com, there was the noise.

And just having the Discord (web app) website open, same ugly effect.

So now I was really curious. What is going on here.

I started to look up how you can play audio with HTML/JavaScript.
There seem to be two ways: Either with the <audio> tag or the WebAudio API.

As Outlook plays sound dynamically, I knew it must use the WebAudio API.
And to do anything with audio, you first have to create an AudioContext.

const audioCtx = new AudioContext();

And already here I realized the problem. Just creating this AudioContext makes my speakers play white noise.

You can test it here: https://editor.43z.one/sqare

The MDN article is pretty clear about it.

AudioContext.suspend()
Suspends the progression of time in the audio context, temporarily halting
audio hardware access and reducing CPU/battery usage in the process. AudioContext.resume() Resumes the progression of time in an audio context that has previously
been suspended.

(easy peasy https://editor.43z.one/13zzt)

Yet, most websites never bother suspending the AudioContext and create one without the immediate need for playing sound.

Chrome stops the battery/CPU waste automatically afte some time. Firefox not. It just keeps playing the whitenoise.

I understand that the websites are to blame here.

But still, Cmon Firefox, protect me from this resource theft?!

Oh and btw I suspect this also wastes my bluetooth headphones battery if they are connected?! Once I do a click on x.com the sending of white noise starts.

To address this total mess, I created an extension that automatically suspends the AudioContext while also tries to resume it if the websites wants to play sound.

It's not perfect as resuming takes a little bit of time and it may not always resume, as there are multiple paths to starting audio. But it's good enough for me.

Some Relevant Bugzilla reports

More fun stuff at h.43z.one.
Unshadow ban me at 𝕏