Open Bug 1387950 Opened 7 years ago Updated 3 months ago

Adjust GC options to avoid (minor) GCs during Firefox startup

Categories

(Core :: JavaScript: GC, enhancement, P3)

enhancement

Tracking

()

Tracking Status
firefox57 --- affected

People

(Reporter: Mardak, Unassigned)

References

Details

sfink, has something like this (adjusting GC settings) been looked at recently? Potentially there could be some settings used for startup and then different settings for the rest of time.

In bug 1386445 comment 4, I got a bit distracted with a minorGC that happened during Firefox startup. Where in that profile, 18ms was spent on 3 minorGCs in the first 2 seconds (where window was drawn in about that time) and 26ms more from 2 minorGCs after first draw but still starting up.

mconley suggests shaving off up to 44ms would be worthwhile, so if there's something simple that can be adjusted, maybe we can get some easy wins.

I tried playing around with the nursery.max_kb pref from bug 1380768 on an clean profile (except perf-html.io add-on), but that didn't seem to avoid the minorGCs.

MOZ_PROFILER_STARTUP=1 ./mach run --setpref javascript.options.mem.nursery.max_kb=4096

Sanity check with a smaller number:
nursery.max_kb=1024 https://perfht.ml/2vFWdQz

T+0.253s: 1.9ms for FULL_WHOLE_CELL_BUFFER
T+0.907s: 5.7ms for FULL_WHOLE_CELL_BUFFER
T+1.391s: _delayedStartup@browser.js finished
T+1.446s: 4.7ms for FULL_WHOLE_CELL_BUFFER
T+1.845s: 3.2ms for FULL_WHOLE_CELL_BUFFER
T+1.996s: 4.4ms for FULL_WHOLE_CELL_BUFFER
T+2.164s: 2.6ms for OUT_OF_NURSERY
T+2.248s: 4.3ms for OUT_OF_NURSERY
T+2.426s: 5.0ms for OUT_OF_NURSERY
T+2.504s: 2.9ms for OUT_OF_NURSERY
T+2.562s: 4.7ms for OUT_OF_NURSERY


Increasing a bit:
nursery.max_kb=4096 https://perfht.ml/2wyGxeE

T+0.318s: 2.3ms for FULL_WHOLE_CELL_BUFFER
T+0.852s: 5.5ms for FULL_WHOLE_CELL_BUFFER
T+1.496s: _delayedStartup@browser.js finished
T+2.255s: 21.ms for FULL_SLOT_BUFFER
T+2.695s: 17.ms for FULL_CELL_PTR_BUFFER


Increasing a lot:
nursery.max_kb=65536 https://perfht.ml/2vFXZkW

T+0.315s: 2.5ms for FULL_WHOLE_CELL_BUFFER
T+0.880s: 5.9ms for FULL_WHOLE_CELL_BUFFER
T+1.488s: _delayedStartup@browser.js finished
T+2.233s: 20.ms for FULL_SLOT_BUFFER
T+2.541s: 19.ms for FULL_CELL_PTR_BUFFER
Flags: needinfo?(sphink)
With the larger nursery size you have managed to avoid triggering a minor collection when the nursery fills up.  But there are several other buffers that fill up and trigger collection (as you can see).  We don't have prefs for these yet, maybe we should?

You could try disabling generational collection (set javascript.options.mem.nursery.max_kb to zero), but measure the total elapsed time, since now the allocation code is completely different (and probably slower) so it might not get any benefit.  The other problem with this is that currently generational collection can not be re-enabled without restarting firefox (it can be disabled without a restart).  I can add that if you'd like.

I've left the needinfo for sfink in case I got any of this wrong or he'd like to comment.
Disabling generational:
nursery.max_kb=0 https://perfht.ml/2wyAh6n

T+0.277s: 2.4ms FULL_WHOLE_CELL_BUFFER
T+1.107s: 6.4ms no reason ?
T+1.546s: _delayedStartup@browser.js finished

Although maybe it's not actually disabling if it's tracing through the nursery? Here's the stack deeper from gcIfRequested for the "no reason":

void DispatchToTracer<JSObject*>(JSTracer*, JSObject**, char const*)
js::TenuringTracer::traceObject(JSObject*)
js::Nursery::collectToFixedPoint(js::TenuringTracer&, js::gc::TenureCountCache&)
js::Nursery::doCollection(JS::gcreason::Reason, js::gc::TenureCountCache&)
js::Nursery::collect
js::Nursery::collect(JS::gcreason::Reason)
js::gc::GCRuntime::minorGC(JS::gcreason::Reason, js::gcstats::PhaseKind)
js::gc::GCRuntime::gcIfRequested()


And doing another nursery.max_kb=0 https://perfht.ml/2wz2z0R
T+0.279s: 2.4ms FULL_WHOLE_CELL_BUFFER
T+0.902s: 6.1ms no reason ?
T+1.392s: _delayedStartup@browser.js finished

So there are fewer minorGCs but probably can't directly compare as you said. Talos can probably provide better timing and memory usage numbers.
Depends on: 1388701
Steve, is it normal for these buffers (FULL_WHOLE_CELL_BUFFER) to be used with the nursery disabled?  How are they used?
It looks like the nursery size or whether it is disabled is being set late during startup.  It is most-likely being set with the "no reason" collection.  I don't know when perfs actually make it to spidermonkey during startup. But I do know that the nursery only updates it's size (including disabled) after each collection.  So it's not getting disabled until that collection at T+1.107s.  The next thing to test might be tweeking the compiled-in defaults for nursery size - which may work natrually well as a startup nursery size.
Priority: -- → P2
Priority: P2 → P3
Severity: normal → S3

It looks like I never answered this question, but I believe pbone's answer was correct. These sizes and the growth logic has been tweaked quite a bit in the last 7 years, including much more aggressive pretenuring heuristics, so I'm not sure if the original behavior observed is still valid. It would be worth regenerating a profile to check.

Flags: needinfo?(sphink)
You need to log in before you can comment on or make changes to this bug.