Bug 185575 - Overly aggressive timer throttling in service workers
Summary: Overly aggressive timer throttling in service workers
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Service Workers (show other bugs)
Version: Safari Technology Preview
Hardware: Mac macOS 10.13
: P2 Normal
Assignee: Chris Dumez
URL:
Keywords: InRadar
Depends on:
Blocks: 185626
  Show dependency treegraph
 
Reported: 2018-05-11 19:35 PDT by Zach Bjornson
Modified: 2018-05-15 08:45 PDT (History)
6 users (show)

See Also:


Attachments
Patch (20.33 KB, patch)
2018-05-14 14:09 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (20.44 KB, patch)
2018-05-14 14:27 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Zach Bjornson 2018-05-11 19:35:37 PDT
Safari seems to throttle timers extremely aggressively in service workers. If I run this code:

    let previous = Date.now();
    const interval = 1000;
    setInterval(() => {
        const now = Date.now();
        const separation = now - previous;
        previous = now;
        console.log("tick", separation);
    }, interval);

most ticks run after [interval + 10,000 ms] -- e.g. 1000 ms runs at 11,000 ms and 100 ms runs at 10,100 ms. Sometimes they run closer to the actual [interval], when the main page is doing work. Disabling "DOM Timer Throttling" and "Hidden Page Timer Throttling" has no effect.

The same code in the main browser thread runs when expected (just after [interval]). Edge, Firefox and Chrome run the timers when expected in service workers.

This is a problem for our application because we use timers to batch multiple HTTP requests into fewer HTTP requests. Consequently, our batched HTTP requests are delayed up to 10 seconds.

(Safari v 11.1 / 13605.1.33.1.4)
Comment 1 Chris Dumez 2018-05-14 09:05:26 PDT
Probably our timer throttling code that kicks in because the service worker does not have any visible page.
Comment 2 Radar WebKit Bug Importer 2018-05-14 09:05:53 PDT
<rdar://problem/40219038>
Comment 3 Radar WebKit Bug Importer 2018-05-14 09:05:53 PDT
<rdar://problem/40219039>
Comment 4 Chris Dumez 2018-05-14 12:41:12 PDT
Do you have a test page? I have trouble reproducing. I see there interval very very close to 1000:
CONSOLE MESSAGE: line 14: 1004
CONSOLE MESSAGE: line 14: 1000
CONSOLE MESSAGE: line 14: 1002
CONSOLE MESSAGE: line 14: 1003
CONSOLE MESSAGE: line 14: 1000
CONSOLE MESSAGE: line 14: 1006
Comment 5 Chris Dumez 2018-05-14 12:45:33 PDT
I suspect this could be throttling outside WebKit known as AppNap. If I look at Activity Monitor, I see that the service worker process gets App Napped after ~30 seconds, I believe this impacts our timers as well. I'll look into preventing App Nap.
Comment 6 Chris Dumez 2018-05-14 12:53:52 PDT
(In reply to Chris Dumez from comment #5)
> I suspect this could be throttling outside WebKit known as AppNap. If I look
> at Activity Monitor, I see that the service worker process gets App Napped
> after ~30 seconds, I believe this impacts our timers as well. I'll look into
> preventing App Nap.

To confirm that this is the issue you are experiencing, you can disable App Nap via:
defaults write NSGlobalDomain NSAppSleepDisabled -bool YES
Comment 7 Chris Dumez 2018-05-14 14:09:16 PDT
Created attachment 340355 [details]
Patch
Comment 8 Geoffrey Garen 2018-05-14 14:19:07 PDT
Comment on attachment 340355 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=340355&action=review

> Source/WebKit/UIProcess/ServiceWorkerProcessProxy.cpp:113
> +    // Prevent App Nap for Service Worker processes.
> +    setProcessSuppressionEnabled(false);

I think we want a FIXME with a link to a bugzilla bug that says Service Workers should nap if all their clients are napping. It's not a high priority bug, but it's good to clarify that's the design that we think would be best.
Comment 9 Chris Dumez 2018-05-14 14:27:42 PDT
Created attachment 340359 [details]
Patch
Comment 10 WebKit Commit Bot 2018-05-14 15:31:47 PDT
Comment on attachment 340359 [details]
Patch

Clearing flags on attachment: 340359

Committed r231771: <https://trac.webkit.org/changeset/231771>
Comment 11 WebKit Commit Bot 2018-05-14 15:31:49 PDT
All reviewed patches have been landed.  Closing bug.
Comment 12 Zach Bjornson 2018-05-14 20:18:40 PDT
Thanks for the fast fix! `NSGlobalDomain NSAppSleepDisabled -bool YES` fixes the issue, so I assume the patch works as well.
Comment 13 Chris Dumez 2018-05-15 08:45:30 PDT
(In reply to Zach Bjornson from comment #12)
> Thanks for the fast fix! `NSGlobalDomain NSAppSleepDisabled -bool YES` fixes
> the issue, so I assume the patch works as well.

If you'd like, you can verify my fix by resetting this defaults and try this build:
https://s3-us-west-2.amazonaws.com/minified-archives.webkit.org/mac-highsierra-x86_64-release/231772.zip which contains my fix.

It'd be useful to make sure everything behaves as expected now.