Closed
Bug 1377131
Opened 8 years ago
Closed 7 years ago
Try to trigger collector slices at times which disturb page js less (at least with iframes loaded after the top level page has been loaded)
Categories
(Core :: DOM: HTML Parser, enhancement)
Core
DOM: HTML Parser
Tracking
()
Tracking | Status | |
---|---|---|
firefox57 | --- | fixed |
People
(Reporter: smaug, Assigned: smaug)
References
(Blocks 1 open bug)
Details
Attachments
(2 files, 7 obsolete files)
15.02 KB,
patch
|
mccr8
:
review+
bzbarsky
:
review+
|
Details | Diff | Splinter Review |
15.94 KB,
patch
|
Details | Diff | Splinter Review |
The idea is that if main page has been loaded already, better to not
block user input or refresh driver to be handled. And also give better chance for other idle callbacks to run.
a local test (using the current background parser timer) hints that speedometer could get around 5 points with this.
Assignee | ||
Updated•8 years ago
|
Whiteboard: [qf:p1]
Comment 1•8 years ago
|
||
Will there be some timeout on this? I assume we don't want to delay potentially forever, right?
Comment 2•8 years ago
|
||
Also, what does this mean if a site adds many iframes at once? For example, twitter uses a lot of iframes for the entries in the timeline. I'm just wondering if this could trigger some pathological behavior in sites like that.
Assignee | ||
Comment 3•8 years ago
|
||
If you look at the bug which is blocking this, you see there is the timer.
Assignee | ||
Comment 4•8 years ago
|
||
Note, we would be using idle queue, so if there isn't anything else to process, we'd still create DOM for iframes asap.
Comment 5•8 years ago
|
||
Yea. I only ask because it reminds me of the change I made to setTimeout() so timers always yielded to the main thread. Some sites had problems because they were designed in a way where they needed to force this work through when the thread is busy. Just wondering if sites like twitter with lots of iframes will handle this ok.
Assignee | ||
Updated•8 years ago
|
Summary: Use idle dispatch for foreground iframe parsing if iframe's parent document has been loaded already → Use idle dispatch for foreground iframe dom creation if iframe's parent document has been loaded already
Assignee | ||
Comment 6•8 years ago
|
||
I'm sure I'll see plenty of test failures. I do expect that we have tons of racy tests.
I think I need to still tweak this.
remote: Follow the progress of your build on Treeherder:
remote: https://treeherder.mozilla.org/#/jobs?repo=try&revision=c4e9cda69589fef9d29ab04495e6dddc279bd8de
remote:
remote: It looks like this try push has talos jobs. Compare performance against a baseline revision:
remote: https://treeherder.mozilla.org/perf.html#/comparechooser?newProject=try&newRevision=c4e9cda69589fef9d29ab04495e6dddc279bd8de
remote: recorded changegroup in replication log in 0.092s
Assignee | ||
Comment 7•8 years ago
|
||
remote: Follow the progress of your build on Treeherder:
remote: https://treeherder.mozilla.org/#/jobs?repo=try&revision=52b460272a34a316446235ece5496c5553c34ac4
remote:
remote: It looks like this try push has talos jobs. Compare performance against a baseline revision:
remote: https://treeherder.mozilla.org/perf.html#/comparechooser?newProject=try&newRevision=52b460272a34a316446235ece5496c5553c34ac4
Assignee | ||
Comment 8•8 years ago
|
||
Grr, we have quite some broken tests.
Assignee | ||
Comment 9•8 years ago
|
||
Very different approach. Trying to utilize the time from uri load to necko giving back data, and also start of parsing to parser actually serving data back to main thread.
remote: Follow the progress of your build on Treeherder:
remote: https://treeherder.mozilla.org/#/jobs?repo=try&revision=e0233ffbff21a3491745d437208790335b14dc0d
remote:
remote: It looks like this try push has talos jobs. Compare performance against a baseline revision:
remote: https://treeherder.mozilla.org/perf.html#/comparechooser?newProject=try&newRevision=e0233ffbff21a3491745d437208790335b14dc0d
Assignee | ||
Comment 10•8 years ago
|
||
Comment on attachment 8883046 [details] [diff] [review]
approach 2, v3
Is this crazy enough? With this we should be able to remove some of our explicit collector running in mochitest framework at least.
Note, if user is actually using the web page, this doesn't cause any extra collections.
I don't quite understand ReadyToTriggerExpensiveCollectorTimer anymore given what we do in different slices, so I just removed it.
CCRunnerFired for example isn't expensive, it is the usually very fast forgetSkippable. And GCTimerFired only triggers sInterSliceGCRunner, and does nothing else.
Attachment #8883046 -
Flags: review?(continuation)
Assignee | ||
Comment 11•8 years ago
|
||
And I very much understand the patch is rather controversial, when we in other cases have tried to move to use idle time. But idle time and benchmarks don't really work well together.
Assignee | ||
Updated•8 years ago
|
Summary: Use idle dispatch for foreground iframe dom creation if iframe's parent document has been loaded already → Try to trigger collector slices at times which disturb page js less (at least with iframes loaded after the top level page has been loaded)
Comment 12•8 years ago
|
||
Comment on attachment 8883046 [details] [diff] [review]
approach 2, v3
Review of attachment 8883046 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/base/nsJSEnvironment.cpp
@@ +2216,5 @@
> void
> +nsJSContext::MaybeRunNextCollectorSlice(nsIDocShell* aDocShell,
> + JS::gcreason::Reason aReason)
> +{
> + if (aDocShell && XRE_IsContentProcess()) {
nit: extra space before XRE.
@@ +2234,5 @@
> + uint32_t lastEventTime = 0;
> + vm->GetLastUserEventTime(lastEventTime);
> + uint32_t currentTime =
> + PR_IntervalToMicroseconds(PR_IntervalNow());
> + if ((currentTime - lastEventTime) >
The idea of having the GC do some work when the main thread might be waiting around sounds okay (ideally, wouldn't Quantum DOM deal with this somehow by scheduling stuff then?), but having a special mode that only activates when a page has just been loaded but the user hasn't interacted with the browser doesn't feel to me like it would help actual users.
::: dom/base/nsJSEnvironment.h
@@ +104,5 @@
> // Return the longest CC slice time since ClearMaxCCSliceTime() was last called.
> static uint32_t GetMaxCCSliceTimeSinceClear();
> static void ClearMaxCCSliceTime();
>
> + static void RunNextCollectorTimer(JS::gcreason::Reason aReason = JS::gcreason::DOM_WINDOW_UTILS);
Just make aReason mandatory and pass it in for the one existing call site.
Attachment #8883046 -
Flags: review?(continuation) → review-
Assignee | ||
Comment 13•8 years ago
|
||
Our current setup should be working well with real web when user is interacting with the browser and all (and in which case there is usually plenty of idle time), but it really doesn't work well with benchmarks which trigger page loads and generate garbage a lot faster.
That is the case I'm trying to fix here, at least for iframes. I need to still think cases like window.open etc.
Assignee | ||
Comment 14•8 years ago
|
||
Some background is also in http://logs.glob.uno/?c=content#c451100
Assignee | ||
Comment 15•8 years ago
|
||
(In reply to Andrew McCreight [:mccr8] from comment #12)
> The idea of having the GC do some work when the main thread might be waiting
> around sounds okay (ideally, wouldn't Quantum DOM deal with this somehow by
> scheduling stuff then?),
I don't see how Quantum DOM would help any of this. In this case we have just one docgroup running and it doesn't have much idle time to run background operations, like collectors.
> but having a special mode that only activates when
> a page has just been loaded but the user hasn't interacted with the browser
> doesn't feel to me like it would help actual users.
Page hasn't been loaded yet. This stuff is triggered first when necko is told to load something and then when necko knows there is some data to parse as HTML (but before HTML parser has done anything with the data)
Assignee | ||
Comment 16•8 years ago
|
||
Fixed the handling in parser and made a param non-optional.
remote: Follow the progress of your build on Treeherder:
remote: https://treeherder.mozilla.org/#/jobs?repo=try&revision=51dca6324f21258d74fbc5d90f97771dd1732290
remote:
remote: It looks like this try push has talos jobs. Compare performance against a baseline revision:
remote: https://treeherder.mozilla.org/perf.html#/comparechooser?newProject=try&newRevision=51dca6324f21258d74fbc5d90f97771dd1732290
mccr8, how strongly are you against this kind of setup? :)
I'm having hard time to find other options where collectors wouldn't disturb random benchmarks a lot.
Attachment #8883046 -
Attachment is obsolete: true
Attachment #8883143 -
Flags: review?(continuation)
Assignee | ||
Comment 17•8 years ago
|
||
added missing 'explicit'
Attachment #8883143 -
Attachment is obsolete: true
Attachment #8883143 -
Flags: review?(continuation)
Attachment #8883245 -
Flags: review?(continuation)
Assignee | ||
Comment 18•8 years ago
|
||
One thing to remind we already have similar, but at worse time running hack in AutoEntryScript::~AutoEntryScript(). That is calling MaybeGC while page is already being created in the main thread.
Comment 19•8 years ago
|
||
Comment on attachment 8883245 [details] [diff] [review]
approach 2, v5
This still feels questionable to me. I'll defer to what Boris thinks, once he is back from vacation. He should probably look at that docshell/view manager code anyways.
Attachment #8883245 -
Flags: review?(continuation)
Assignee | ||
Comment 20•8 years ago
|
||
Could you explain a bit what feels questionable in particular?
Flags: needinfo?(continuation)
Assignee | ||
Comment 21•8 years ago
|
||
And sure, a docshell peer would need to take a look at docshell part and a parser peer the parser part.
Assignee | ||
Comment 22•8 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #20)
> Could you explain a bit what feels questionable in particular?
...since the more I think of this, the less weird this feel. This is basically a better version of
http://searchfox.org/mozilla-central/rev/f1472e5b57fea8d4a7bbdd81c44e46958fe3c1ce/dom/script/ScriptSettings.cpp#692
Assignee | ||
Updated•8 years ago
|
Flags: needinfo?(bzbarsky)
Comment 23•8 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #22)
> ...since the more I think of this, the less weird this feel. This is
> basically a better version of
I think it is worse because it means that behavior of the benchmark is different from the behavior a user actually experiences.
Flags: needinfo?(continuation)
Assignee | ||
Comment 24•8 years ago
|
||
How so? Normally GC/CC run during idle time. So user doesn't notice them. But since benchmarks don't have much idle time, GC/CC run at random times affecting the results.
Flags: needinfo?(continuation)
Comment 25•8 years ago
|
||
The code that is run is different depending on whether a benchmark is being run or not. Hopefully this will result in the same behavior as normal user behavior, but it isn't guaranteed in any way.
Flags: needinfo?(continuation)
Assignee | ||
Comment 26•8 years ago
|
||
Sure. Right now it isn't guaranteed either.
Assignee | ||
Updated•8 years ago
|
Attachment #8882890 -
Attachment is obsolete: true
Assignee | ||
Updated•8 years ago
|
Attachment #8882447 -
Attachment is obsolete: true
Assignee | ||
Comment 27•8 years ago
|
||
Comment on attachment 8883245 [details] [diff] [review]
approach 2, v5
I'll try a bit less controversial patch.
Only run collector if its timer should have run, but hasn't because main thread has been busy. (but still check use activity etc.)
Attachment #8883245 -
Attachment is obsolete: true
Updated•8 years ago
|
Flags: needinfo?(bzbarsky)
Assignee | ||
Comment 28•8 years ago
|
||
Assignee | ||
Updated•8 years ago
|
Attachment #8885951 -
Attachment is obsolete: true
Assignee | ||
Comment 29•8 years ago
|
||
remote: Follow the progress of your build on Treeherder:
remote: https://treeherder.mozilla.org/#/jobs?repo=try&revision=6b749e533a0767616f3dc8e43237cba4ebfb455e
remote:
remote: It looks like this try push has talos jobs. Compare performance against a baseline revision:
remote: https://treeherder.mozilla.org/perf.html#/comparechooser?newProject=try&newRevision=6b749e533a0767616f3dc8e43237cba4ebfb455e
remote: recorded changegroup in replication log in 0.126s
Assignee | ||
Comment 30•7 years ago
|
||
remote: View your change here:
remote: https://hg.mozilla.org/try/rev/406dfa798dfdfcf570b231bb15cd330979fe6f42
remote:
remote: Follow the progress of your build on Treeherder:
remote: https://treeherder.mozilla.org/#/jobs?repo=try&revision=406dfa798dfdfcf570b231bb15cd330979fe6f42
Attachment #8888049 -
Attachment is obsolete: true
Assignee | ||
Comment 31•7 years ago
|
||
Comment on attachment 8898351 [details] [diff] [review]
v11
Still trying to sell this.
We used to trigger GC/CC right after tick, this makes us do that occasionally right before, with deadline (deadline is new in this version). And only when user hasn't been interacting with the browser for awhile.
Attachment #8898351 -
Flags: review?(continuation)
Comment 32•7 years ago
|
||
Comment on attachment 8898351 [details] [diff] [review]
v11
Review of attachment 8898351 [details] [diff] [review]:
-----------------------------------------------------------------
Sorry for the delay.
Please make sure that this doesn't cause an increase in oranges in Win32 debug reftests.
You should get Boris or somebody to review nsJSContext::MaybeRunNextCollectorSlice() because I don't understand that code at all and don't know if it is reasonable or not. The rest looks okay to me. You also need a commit message that is explaining what you are trying to do and why.
::: docshell/base/nsDocShell.cpp
@@ +11614,5 @@
> }
> rv = aURILoader->OpenURI(aChannel, openFlags, this);
> NS_ENSURE_SUCCESS(rv, rv);
>
> + // We're about to load a new page and it may take time before necko
Should this be "Necko" not "necko"?
::: dom/base/nsJSEnvironment.cpp
@@ -2007,5 @@
> return;
> }
>
> if (sGCTimer) {
> - if (ReadyToTriggerExpensiveCollectorTimer()) {
I added this because I was concerned about making tests that call into this take too long. Please be sure that this doesn't make reftests time out way more often.
::: js/public/GCAPI.h
@@ +111,5 @@
> D(UNUSED2) \
> D(USER_INACTIVE) \
> + D(XPCONNECT_SHUTDOWN) \
> + D(DOCSHELL) \
> + D(PARSER)
Maybe call this HTML_PARSER? In the JS engine, "parser" would usually refer to parsing JS.
::: parser/html/nsHtml5StreamParser.cpp
@@ +991,5 @@
> do_QueryInterface(mRequest, &rv);
> if (threadRetargetableRequest) {
> rv = threadRetargetableRequest->RetargetDeliveryTo(mEventTarget);
> + if (NS_SUCCEEDED(rv)) {
> + // Parser thread should be now ready to get data from necko and parse it
"Necko"? Also, below.
Attachment #8898351 -
Flags: review?(continuation) → review+
Assignee | ||
Comment 33•7 years ago
|
||
(In reply to Andrew McCreight [:mccr8] from comment #32)
> ::: dom/base/nsJSEnvironment.cpp
> @@ -2007,5 @@
> > return;
> > }
> >
> > if (sGCTimer) {
> > - if (ReadyToTriggerExpensiveCollectorTimer()) {
>
> I added this because I was concerned about making tests that call into this
> take too long. Please be sure that this doesn't make reftests time out way
> more often.
But those timers aren't anymore expensive.
GCTimerFired just starts an idle runner and CCRunnerFired usually just runs forgetskippable
> ::: js/public/GCAPI.h
> @@ +111,5 @@
> > D(UNUSED2) \
> > D(USER_INACTIVE) \
> > + D(XPCONNECT_SHUTDOWN) \
> > + D(DOCSHELL) \
> > + D(PARSER)
>
> Maybe call this HTML_PARSER? In the JS engine, "parser" would usually refer
> to parsing JS.
Indeed
Assignee | ||
Comment 34•7 years ago
|
||
Comment on attachment 8898351 [details] [diff] [review]
v11
bz, could you take a look at MaybeRunNextCollectorSlice.
I'm trying to make us run collector slices at better time when iframes are being loaded in a fast pace - but without disturbing top level page loads.
And if user is active, then better to not do anything special.
And give collectors only up to the next tick time to run themselves.
(We might want to do this all also for top level page loads, but I'm being conservative here first.)
After this I'll look at bug 1378092 again and also perhaps try to remove explicit GC call from InvokeInterruptCallback - hopefully fixing those would lead us to run GC a bit less often at bad times.
(bz is not accepting review requests atm)
Flags: needinfo?(bzbarsky)
Comment 35•7 years ago
|
||
Comment on attachment 8898351 [details] [diff] [review]
v11
This seems fairly reasonable. I just have two requests:
1) A decent commit message. Comment 34 would be a good start, but doesn't describe the parser bits.
2) Some documentation on RunNextCollectorTimer and MaybeRunNextCollectorSlice explaining what they're for (at their declaration sites) and why they do what they do (esp. for MaybeRunNextCollectorSlice) at their implementation sites.
Flags: needinfo?(bzbarsky)
Attachment #8898351 -
Flags: review+
Assignee | ||
Comment 36•7 years ago
|
||
Comment 37•7 years ago
|
||
Pushed by opettay@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/10405ae76f20
Try to trigger collector slices at times which disturb page js less (at least with iframes loaded after the top level page has been loaded), r=mccr8,bz
Comment 38•7 years ago
|
||
bugherder |
Status: NEW → RESOLVED
Closed: 7 years ago
status-firefox57:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla57
Comment 39•7 years ago
|
||
and some performance improvements:
== Change summary for alert #9287 (as of September 06 2017 18:30 UTC) ==
Improvements:
4% kraken summary linux64 pgo e10s 1,439.42 -> 1,380.67
3% kraken summary linux64 opt e10s 1,488.06 -> 1,436.53
3% kraken summary windows10-64 pgo e10s1,473.51 -> 1,423.91
For up to date results, see: https://treeherder.mozilla.org/perf.html#/alerts?id=9287
Updated•3 years ago
|
Performance Impact: --- → P1
Whiteboard: [qf:p1]
You need to log in
before you can comment on or make changes to this bug.
Description
•