cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
user-004
New member
Status: New idea

"Total cookie protection" from Firefox is a great step in the right direction of putting user interest above those who are actively trying to invade our privacy. Thank you for pioneering this.

Sadly, that horse has long left the barn.
The FF multi-account containers extension and Firefox Focus were popular for years for a good reason.

The battle lines have now moved to stealing our CPU cycles, network bandwidth & memory.

We now need client-side resource protection, with full user control.

Many sites and extensions/apps have taken the liberty of using our computers against our wishes.

CPU is the biggest pain-point. The client-server DDoS pattern has now been completely inverted. 
Many Firefox processes are taking too much CPU.  I'm seeing processes that are taking 100% CPU for hours.

The service providers are now the biggest abusers and we're being DoSed and charged for electricity we don't really use.

100% CPU utilization for hours, all night, when the (desktop) browser isn't even used is wasted energy and a great contributor to climate change as well. A double whammy.

The band-aid I now use is a cronjob to periodically check for abuse and kill Firefox CPU hogging processes. 

Users should have full control over what every site gets in terms of resources, with some good defaults:

  • Option: completely freeze/suspend apps that are not in use (unexposed tabs & minimized windows)
  • If a tab needs to work in "the background" (e.g. a mail tab to check whether I have new mail or calendar app to update new appointments) I want to be able to limit it to what is in my interest, e.g.:
       - Foreground processes: active tabs:
                  Never consume more than P% CPU and never more than X CPU seconds (cumulative)
       - Background processes: non active tabs and minimized windows:
                 - Get a CPU time slice only once every N seconds, no more
                 - When given a time-slice: never work continuously for more than M seconds
                   (unless explicitly allowed)

Thoughts/ideas for defaults:
- When FF is minimized, freeze the CPU for everything. Including web sockets / async updates.
- Processes in tabs that aren't exposed should NEVER be taking 100 %pct CPU.  If they do, they should be considered misbehaving and the user should have an option to restrict them.
- Even for an active/visible tabs: more than X% CPU for more than N minutes/seconds (both user settable), should be considered abusive.

IOW: users need the FF CPU/task scheduler to be in their full control.


Thanks for listening.

6 Comments
Status changed to: New idea
Jon
Community Manager
Community Manager

Thanks for submitting an idea to the Mozilla Connect community! Your idea is now open to votes (aka kudos) and comments.

user-004
New member

Just wanted to add that often the site we go to, is not what's hogging the CPU.

There can be many 3rd party JS components: ad-trackers, crypto-miners, performance trackers & even legit microservices embedded in every page.  They might be malicious or not. This goes way beyond just cookies and privacy.

If all 3rd party JS components are disabled, the page might not work as expected.
That makes sense, but only when the tab/page is exposed.

But enabling them when the browser is minimized and/or the tab is not exposed (background mode) is what's allowing them to hog the client resources without any ability of the user to override.

heaversm
Employee
Employee

@user-004  - do you have a specific example of a service that attempts to maximize the CPU? (or a page on which this occurs).

I'd like to actually do some tests with the firefox profiler and document this for Mozilla.

user-004
New member

Thank you @heaversm!
I really appreciate the support.

Ironically, I just managed to type something and edit my response
in this Comment dialog to trigger a 'unresponsive script' dialog
This happened on this very page:

https://connect.mozilla.org/t5/ideas/client-side-resource-cpu-memory-network-ban
dwidth-protection/idc-p/18849/emcs_t/...

I got into a 105% sustained CPU utilization state (more than one core/thread in some busy loop)
and a dialog telling me that a script on this page has become unresponsive asking me to wait or exit.
This was in chromium, not FF (I had FF minimized) so now I have to type my response all over again 🙂

Some of the most common cases of pages I've seen sustaining high CPU are:

- Google cloud console, big query page
- Google calendar
- Gmail

But the issue is often some ads/widgets (e.g. an animated gif/ad or
a moving updating data ticker) regardless of the main page.

And I suspect it is also related to the FF subprocess scheduler itself.

Right now I have FF minimized (37 tabs) so no window is visible.
And I still see FF oscillating between ~3% to 22% CPU with occasional
spikes over 50% CPU. I wish it was near 0% when minimized, regardless
of which pages are in the tabs. Freeze everything (like CTRL-Z in the
terminal and switch the FF scheduler to a deep-sleep mode: with hard
sleeps of 1.0 sec every time-slice to give processes a chance to deal
with any async events.

For reference, here's the bash script (started from cron every
few minutes at night) that helps fight climate change and save
on electricity bills.

#------------------------------------------------------------------------
#!/bin/bash
#
# Kill CPU hogging processes (mainly browser tabs) to conserve energy
#

#
# Adjust these to taste:
#   How many total cumulative seconds of CPU to tolerate?
#   How much current %CPU to tolerate?
#
MAX_CPU_SECS=1200
MAX_CPU_PCT=5

function process_list() {
   local psfields='pid,ppid,user,pri,pcpu,pmem,time,stime,tty,wchan,cmd'
   /bin/ps -A -o "$psfields" | grep -Pi -- "$1"
}

function terminate-hogs() {
   perl -wne '
       # Read the process data, one line at a time
       my $MAX_CPU_SECS = '"$MAX_CPU_SECS"';
       my $MAX_CPU_PCT   = '"$MAX_CPU_PCT"';

       s/^\s+//;   # small PIDs are space padded

       my ($pid, $ppid, $user, $pri, $cpu, $mem, $time) = split(" ");
       my ($hh, $mm, $ss) = split(/\D+/, $time);
       my $cpu_secs = 3600*$hh + 60*$mm + $ss;
       next if ($cpu_secs < $MAX_CPU_SECS);   # Not a CPU hog, skip
       next if ($cpu < $MAX_CPU_PCT);          # Not a CPU hog, skip

       # If we get here, we found a CPU hogging process tab
       print "Killing CPU hogging process (Secs: $cpu_secs, %CPU: $cpu):\n$_";
       kill "TERM", $pid;
       sleep 3;    # give FF time to handle the signal
   '
}

process_list '[/]firefox -contentproc -childID.*tab$' | terminate-hogs
process_list '[/]chrom(e|ium) --type=(renderer|utility)' | terminate-hogs
process_list '[/]signal-desktop --type' | terminate-hogs
process_list '[/]slack --type' | terminate-hogs
#------------------------------------------------------------------------

 

heaversm
Employee
Employee

@user-004- wow - I am going to attempt to understand all this. May follow up with some questions. Thanks for sharing!

user-004
New member

Some more information to help save energy when firefox is idle/minimized.

When I strace the firefox main process (not individual content tabs) while firefox is closed/minimized

I see it is busy looping as follows (process & strace output details below):

=== Process info:

PID     PPID  USER   PRI %CPU %MEM     TIME     STIME  TT      WCHAN        COMMAND
4898  4478  user    18       7.9        0.8    00:07:15 08:18   ?         do_sys_poll   /usr/lib/firefox/firefox --sm-client-id <long-id>

stracing this process shows a loop with some blocking calls (poll, recvmsg) that is repeated in high frequency:

=== Loop repeated a several times per second:

poll([{fd=4, events=POLLIN}, {fd=9, events=POLLIN}, {fd=11, events=POLLIN}, {fd=12, events=POLLIN}, {fd=29, events=POLLIN}, {fd=30, events=POLLIN}], 6, 0) = 1 ([{fd=30, revents=POLLIN}])
read(30, "\372", 1)                     = 1
recvmsg(4, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(4, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=4, events=POLLIN}, {fd=9, events=POLLIN}, {fd=11, events=POLLIN}, {fd=12, events=POLLIN}, {fd=29, events=POLLIN}, {fd=30, events=POLLIN}], 6, 0) = 0 (Timeout)
write(31, "\372", 1)                    = 1
recvmsg(4, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(4, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)

When I open firefox and hover my mouse over any page, I can see the activity growing with strace printing syscalls at a much higher frequency.

However: even while minimized and getting no pointer events, firefox is still the top CPU consuming process on my desktop according to htop.  Why does it take so much CPU when idle/minimized?

Could firefox change its behavior and poll less frequently (even once per second would go a long way towards saving energy) when minimized or otherwise idle (no user-activity/mouse pointer detected over any tab/page) ?