RESOLVED FIXED 145773
Allow one sync GC per gcTimer interval on critical memory pressure warning
https://bugs.webkit.org/show_bug.cgi?id=145773
Summary Allow one sync GC per gcTimer interval on critical memory pressure warning
Chris Dumez
Reported 2015-06-08 15:02:46 PDT
On critical memory pressure warning, we currently call GCController::garbageCollectSoon(), which does not offer any guarantee on when the garbage collection will actually take place. On critical memory pressure, we need to free up memory as soon as possible to avoid getting killed so this is an issue. Also, the fact that we clear the PageCache on critical memory pressure means a GC would likely be useful, even it is did not do much work the last time the gcTimer fired. As a result, the proposal is to allow one synchronous GC per gcTimer interval on critical memory pressure warning. This makes us more responsive to critical memory pressure and avoids doing synchronous GCs too often.
Attachments
Patch (10.51 KB, patch)
2015-06-08 20:08 PDT, Chris Dumez
no flags
Patch (10.69 KB, patch)
2015-06-08 20:26 PDT, Chris Dumez
no flags
Patch (12.52 KB, patch)
2015-06-09 14:05 PDT, Chris Dumez
no flags
Chris Dumez
Comment 1 2015-06-08 20:08:45 PDT
Chris Dumez
Comment 2 2015-06-08 20:26:42 PDT
Darin Adler
Comment 3 2015-06-09 11:28:41 PDT
Comment on attachment 254541 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=254541&action=review > Source/JavaScriptCore/heap/Heap.cpp:1422 > + collectAllGarbage(); What is the rationale for not setting m_didSyncGCRecently true here?
Chris Dumez
Comment 4 2015-06-09 11:41:32 PDT
Comment on attachment 254541 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=254541&action=review >> Source/JavaScriptCore/heap/Heap.cpp:1422 >> + collectAllGarbage(); > > What is the rationale for not setting m_didSyncGCRecently true here? m_didSyncGCRecently is only reset to false when the m_fullActivityCallback timer fires so if this timer is disabled (m_fullActivityCallback is null) it will never be reset to false. Geoff can correct me but I don't think this (m_fullActivityCallback being null) normally happens in practice though as I don't see any call sites to JSDisableGCTimer().
Geoffrey Garen
Comment 5 2015-06-09 13:13:06 PDT
r=me Perhaps it would be nice to refactor this to be a feature of the timer, rather than a feature of the Heap object. That would help clarify the behavior in the case where there is not timer.
Chris Dumez
Comment 6 2015-06-09 14:05:47 PDT
Chris Dumez
Comment 7 2015-06-09 14:06:16 PDT
(In reply to comment #5) > r=me > > Perhaps it would be nice to refactor this to be a feature of the timer, > rather than a feature of the Heap object. That would help clarify the > behavior in the case where there is not timer. I reuploaded another iteration doing this. Please take another look.
Geoffrey Garen
Comment 8 2015-06-09 14:21:33 PDT
Comment on attachment 254600 [details] Patch r=me
Andreas Kling
Comment 9 2015-06-09 14:43:13 PDT
v.nice
WebKit Commit Bot
Comment 10 2015-06-09 15:16:09 PDT
Comment on attachment 254600 [details] Patch Clearing flags on attachment: 254600 Committed r185387: <http://trac.webkit.org/changeset/185387>
WebKit Commit Bot
Comment 11 2015-06-09 15:16:15 PDT
All reviewed patches have been landed. Closing bug.
Joseph Pecoraro
Comment 12 2015-08-19 23:59:15 PDT
Comment on attachment 254600 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=254600&action=review > Source/WebCore/bindings/js/GCController.cpp:101 > +#if USE(CF) > + JSLockHolder lock(JSDOMWindow::commonVM()); > + if (!JSDOMWindow::commonVM().heap.isBusy()) > + JSDOMWindow::commonVM().heap.collectAllGarbageIfNotDoneRecently(); > +#else > + garbageCollectSoon(); > +#endif Why is this different for USE(CF) and not? Heap::collectAllGarbageIfNotDoneRecently appears to be available for all ports so it seems they could both have the same implementation, is there a reason I'm overlooking?
Chris Dumez
Comment 13 2015-08-20 09:15:14 PDT
Comment on attachment 254600 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=254600&action=review >> Source/WebCore/bindings/js/GCController.cpp:101 >> +#endif > > Why is this different for USE(CF) and not? Heap::collectAllGarbageIfNotDoneRecently appears to be available for all ports so it seems they could both have the same implementation, is there a reason I'm overlooking? Maybe Heap::collectAllGarbageIfNotDoneRecently() should be behind USE(CF) then. What we do in Heap::collectAllGarbageIfNotDoneRecently(): if (wasGCdRecenty) garbageCollectSoon(); else garbageCollectNow(); Note that in Heap::collectAllGarbageIfNotDoneRecently(), we call reportAbandonedObjectGraph() to do the garbageCollectSoon(). However, if you look at the implementation of GCController::garbageCollectSoon(), it looks like: // We only use reportAbandonedObjectGraph on systems with CoreFoundation // since it uses a run-loop-based timer that is currently only available on // systems with CoreFoundation. If and when the notion of a run loop is pushed // down into WTF so that more platforms can take advantage of it, we will be // able to use reportAbandonedObjectGraph on more platforms. #if USE(CF) JSLockHolder lock(JSDOMWindow::commonVM()); JSDOMWindow::commonVM().heap.reportAbandonedObjectGraph(); #else garbageCollectOnNextRunLoop(); #endif So to make Heap::collectAllGarbageIfNotDoneRecently() work for !USE(CF), it looks like we would need to use a Timer instead of calling simply reportAbandonedObjectGraph().
Note You need to log in before you can comment on or make changes to this bug.