| Summary: | web process continually eating memory on simple, shared Google Docs spreadsheet | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | WebKit | Reporter: | Matt Lilek <dev+webkit> | ||||||||||||
| Component: | WebCore Misc. | Assignee: | Andreas Kling <kling> | ||||||||||||
| Status: | RESOLVED FIXED | ||||||||||||||
| Severity: | Normal | CC: | andersca, ap, barraclough, cdumez, commit-queue, darin, dbates, dev+webkit, kling, menard, psolanki | ||||||||||||
| Priority: | P2 | Keywords: | InRadar, Performance | ||||||||||||
| Version: | 528+ (Nightly build) | ||||||||||||||
| Hardware: | Mac | ||||||||||||||
| OS: | OS X 10.10 | ||||||||||||||
| Attachments: |
|
||||||||||||||
|
Description
Matt Lilek
2015-07-28 23:25:05 PDT
Created attachment 257740 [details]
Leaks
This appears to happen because the JSC garbage collector expects to be able to schedule work using a CFRunLoopTimer, but when executing inside a web worker thread, there is no CFRunLoop to fire those timers. I'm investigating some different solutions. Alexey says there is some class we have that uses the run loop on the main thread and does something else on other threads that we could possibly use. I was thinking about threadGlobalData().threadTimers(), which has an instance of SharedTimer class that is appropriate for the thread. This is what makes DOM timers function in web workers. But this code is in WebCore. Created attachment 257867 [details]
Patch
This patch fixes the problem by having WorkerRunLoop service the CFRunLoop. It tries to avoid waking up until there's a CFRunLoop timer that would fire, though it doesn't try *that* hard; WebCore timers will also wake it up, since they sit on the same code path.
This is a stopgap fix for ports using CoreFoundation. Other ports that aren't using CF may not have this problem in the first place. I will revisit this down the line and work out a better design where JSC::HeapTimer doesn't muck around directly with the CFRunLoop.
Created attachment 257875 [details]
Patch
Gavin pointed out that it would be excessive to service the CFRunLoop every time a 1000hz DOM timer fires.
This patch makes sure to only call CFRunLoopRunInMode if the next CFRunLoop timer wants to fire now or in the past.
Comment on attachment 257875 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=257875&action=review r=me > Source/WebCore/workers/WorkerRunLoop.cpp:184 > + if (nextCFRunLoopTimerFireDate <= CFAbsoluteTimeGetCurrent()) > + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); I think we want returnAfterSourceHandled to be false (and also in a local variable so the next poor soul who reads this code knows what it means). That way, if more than one source is pending, it will service right away. Created attachment 257880 [details]
Patch for landing
Comment on attachment 257880 [details] Patch for landing Clearing flags on attachment: 257880 Committed r187630: <http://trac.webkit.org/changeset/187630> All reviewed patches have been landed. Closing bug. Safari 9.1.3 still leaks badly when opening a Google Drive/Doc document, using the same repro steps of comment 1. Apparently various people have the same problem : https://discussions.apple.com/thread/6640430?start=0&tstart=0 https://productforums.google.com/forum/#!topic/docs/nLs2qqq-9os https://discussions.apple.com/thread/6857911?start=0&tstart=0 https://www.reddit.com/r/google/comments/30lzym/i_think_weve_got_a_memory_leak_guys/ This comment seems to provide a workaround, not sure that's legitimate : https://forums.developer.apple.com/thread/8497 Firefox (48.0.2) and Chrome (53.0.2785.101) does not exhibit the behavior. |