Bug 1856577 - Consider to trigger minor GC before a page load, r=jonco

This doesn't cover all the page loads, need to run some more performance tests before using this everywhere.

Depends on D189917

Differential Revision: https://phabricator.services.mozilla.com/D189918
This commit is contained in:
Olli Pettay 2023-10-05 18:11:36 +00:00
parent debecf0861
commit 1708a8a34d
5 changed files with 34 additions and 5 deletions

View File

@ -1696,9 +1696,17 @@ void nsJSContext::MaybeRunNextCollectorSlice(nsIDocShell* aDocShell,
Maybe<TimeStamp> next = nsRefreshDriver::GetNextTickHint();
// Try to not delay the next RefreshDriver tick, so give a reasonable
// deadline for collectors.
if (next.isSome() &&
(sScheduler.InIncrementalGC() || sScheduler.IsCollectingCycles())) {
sScheduler.RunNextCollectorTimer(aReason, next.value());
if (next.isSome()) {
if (sScheduler.InIncrementalGC() || sScheduler.IsCollectingCycles()) {
sScheduler.RunNextCollectorTimer(aReason, next.value());
} else {
// In order to improve performance on the next page, run a minor GC.
// The 16ms limit ensures it isn't called all the time if there are for
// example multiple iframes loading at the same time.
JS::RunNurseryCollection(CycleCollectedJSRuntime::Get()->Runtime(),
JS::GCReason::PREPARE_FOR_PAGELOAD,
mozilla::TimeDuration::FromMilliseconds(16));
}
}
}
}

View File

@ -639,6 +639,7 @@ namespace JS {
D(DOCSHELL, 54) \
D(HTML_PARSER, 55) \
D(DOM_TESTUTILS, 56) \
D(PREPARE_FOR_PAGELOAD, 57) \
\
/* Reasons reserved for embeddings. */ \
D(RESERVED1, FIRST_RESERVED_REASON) \
@ -1299,6 +1300,10 @@ extern JS_PUBLIC_API GCReason WantEagerMajorGC(JSRuntime* rt);
extern JS_PUBLIC_API void MaybeRunNurseryCollection(JSRuntime* rt,
JS::GCReason reason);
extern JS_PUBLIC_API void RunNurseryCollection(
JSRuntime* rt, JS::GCReason reason,
mozilla::TimeDuration aSinceLastMinorGC);
extern JS_PUBLIC_API void SetHostCleanupFinalizationRegistryCallback(
JSContext* cx, JSHostCleanupFinalizationRegistryCallback cb, void* data);

View File

@ -1050,7 +1050,7 @@ inline TimeStamp js::Nursery::collectionStartTime() const {
return startTimes_[ProfileKey::Total];
}
inline TimeStamp js::Nursery::lastCollectionEndTime() const {
TimeStamp js::Nursery::lastCollectionEndTime() const {
return previousGC.endTime;
}
@ -1871,6 +1871,10 @@ size_t js::Nursery::targetSize(JS::GCOptions options, JS::GCReason reason) {
TimeStamp now = TimeStamp::Now();
if (reason == JS::GCReason::PREPARE_FOR_PAGELOAD) {
return roundSize(tunables().gcMaxNurseryBytes());
}
// If the nursery is completely unused then minimise it.
if (hasRecentGrowthData && previousGC.nurseryUsedBytes == 0 &&
now - lastCollectionEndTime() >

View File

@ -409,6 +409,8 @@ class Nursery {
return mallocedBlockCache_.sizeOfExcludingThis(mallocSizeOf);
}
mozilla::TimeStamp lastCollectionEndTime() const;
private:
// Fields used during allocation fast path are grouped first:
@ -703,7 +705,6 @@ class Nursery {
Sprinter& sprinter);
mozilla::TimeStamp collectionStartTime() const;
mozilla::TimeStamp lastCollectionEndTime() const;
friend class gc::GCRuntime;
friend class gc::TenuringTracer;

View File

@ -1304,6 +1304,17 @@ JS_PUBLIC_API void JS::MaybeRunNurseryCollection(JSRuntime* rt,
}
}
JS_PUBLIC_API void JS::RunNurseryCollection(
JSRuntime* rt, JS::GCReason reason,
mozilla::TimeDuration aSinceLastMinorGC) {
gc::GCRuntime& gc = rt->gc;
if (!gc.nursery().lastCollectionEndTime() ||
(mozilla::TimeStamp::Now() - gc.nursery().lastCollectionEndTime() >
aSinceLastMinorGC)) {
gc.minorGC(reason);
}
}
JS_PUBLIC_API void JS_GC(JSContext* cx, JS::GCReason reason) {
AssertHeapIsIdle();
JS::PrepareForFullGC(cx);