зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1372042 - Add telemetry about running collectors during idle time, r=mccr8
This commit is contained in:
Родитель
294999ca3a
Коммит
0bb08227bb
|
@ -227,6 +227,8 @@ static bool sIsCompactingOnUserInactive = false;
|
||||||
static int32_t sExpensiveCollectorPokes = 0;
|
static int32_t sExpensiveCollectorPokes = 0;
|
||||||
static const int32_t kPokesBetweenExpensiveCollectorTriggers = 5;
|
static const int32_t kPokesBetweenExpensiveCollectorTriggers = 5;
|
||||||
|
|
||||||
|
static TimeDuration sGCUnnotifiedTotalTime;
|
||||||
|
|
||||||
// Return true if some meaningful work was done.
|
// Return true if some meaningful work was done.
|
||||||
typedef bool (*CollectorRunnerCallback) (TimeStamp aDeadline, void* aData);
|
typedef bool (*CollectorRunnerCallback) (TimeStamp aDeadline, void* aData);
|
||||||
|
|
||||||
|
@ -1434,6 +1436,7 @@ FireForgetSkippable(uint32_t aSuspected, bool aRemoveChildless,
|
||||||
AutoProfilerTracing
|
AutoProfilerTracing
|
||||||
tracing("CC", aDeadline.IsNull() ? "ForgetSkippable" : "IdleForgetSkippable");
|
tracing("CC", aDeadline.IsNull() ? "ForgetSkippable" : "IdleForgetSkippable");
|
||||||
PRTime startTime = PR_Now();
|
PRTime startTime = PR_Now();
|
||||||
|
TimeStamp startTimeStamp = TimeStamp::Now();
|
||||||
FinishAnyIncrementalGC();
|
FinishAnyIncrementalGC();
|
||||||
bool earlyForgetSkippable =
|
bool earlyForgetSkippable =
|
||||||
sCleanupsSinceLastGC < NS_MAJOR_FORGET_SKIPPABLE_CALLS;
|
sCleanupsSinceLastGC < NS_MAJOR_FORGET_SKIPPABLE_CALLS;
|
||||||
|
@ -1450,6 +1453,24 @@ FireForgetSkippable(uint32_t aSuspected, bool aRemoveChildless,
|
||||||
sTotalForgetSkippableTime += delta;
|
sTotalForgetSkippableTime += delta;
|
||||||
sRemovedPurples += (aSuspected - sPreviousSuspectedCount);
|
sRemovedPurples += (aSuspected - sPreviousSuspectedCount);
|
||||||
++sForgetSkippableBeforeCC;
|
++sForgetSkippableBeforeCC;
|
||||||
|
|
||||||
|
TimeStamp now = TimeStamp::Now();
|
||||||
|
TimeDuration duration = now - startTimeStamp;
|
||||||
|
if (duration.ToSeconds()) {
|
||||||
|
TimeDuration idleDuration;
|
||||||
|
if (!aDeadline.IsNull()) {
|
||||||
|
if (aDeadline < now) {
|
||||||
|
// This slice overflowed the idle period.
|
||||||
|
idleDuration = aDeadline - startTimeStamp;
|
||||||
|
} else {
|
||||||
|
idleDuration = duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t percent =
|
||||||
|
uint32_t(idleDuration.ToSeconds() / duration.ToSeconds() * 100);
|
||||||
|
Telemetry::Accumulate(Telemetry::FORGET_SKIPPABLE_DURING_IDLE, percent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE
|
MOZ_ALWAYS_INLINE
|
||||||
|
@ -1518,7 +1539,8 @@ struct CycleCollectorStats
|
||||||
mExtraForgetSkippableCalls = 0;
|
mExtraForgetSkippableCalls = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrepareForCycleCollectionSlice(int32_t aExtraForgetSkippableCalls = 0);
|
void PrepareForCycleCollectionSlice(TimeStamp aDeadline = TimeStamp(),
|
||||||
|
int32_t aExtraForgetSkippableCalls = 0);
|
||||||
|
|
||||||
void FinishCycleCollectionSlice()
|
void FinishCycleCollectionSlice()
|
||||||
{
|
{
|
||||||
|
@ -1528,6 +1550,25 @@ struct CycleCollectorStats
|
||||||
}
|
}
|
||||||
|
|
||||||
mEndSliceTime = TimeStamp::Now();
|
mEndSliceTime = TimeStamp::Now();
|
||||||
|
TimeDuration duration = mEndSliceTime - mBeginSliceTime;
|
||||||
|
|
||||||
|
if (duration.ToSeconds()) {
|
||||||
|
TimeDuration idleDuration;
|
||||||
|
if (!mIdleDeadline.IsNull()) {
|
||||||
|
if (mIdleDeadline < mEndSliceTime) {
|
||||||
|
// This slice overflowed the idle period.
|
||||||
|
idleDuration = mIdleDeadline - mBeginSliceTime;
|
||||||
|
} else {
|
||||||
|
idleDuration = duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t percent =
|
||||||
|
uint32_t(idleDuration.ToSeconds() / duration.ToSeconds() * 100);
|
||||||
|
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_SLICE_DURING_IDLE,
|
||||||
|
percent);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t sliceTime = TimeBetween(mBeginSliceTime, mEndSliceTime);
|
uint32_t sliceTime = TimeBetween(mBeginSliceTime, mEndSliceTime);
|
||||||
mMaxSliceTime = std::max(mMaxSliceTime, sliceTime);
|
mMaxSliceTime = std::max(mMaxSliceTime, sliceTime);
|
||||||
mMaxSliceTimeSinceClear = std::max(mMaxSliceTimeSinceClear, sliceTime);
|
mMaxSliceTimeSinceClear = std::max(mMaxSliceTimeSinceClear, sliceTime);
|
||||||
|
@ -1576,14 +1617,20 @@ struct CycleCollectorStats
|
||||||
|
|
||||||
// A file to dump CC activity to; set by MOZ_CCTIMER environment variable.
|
// A file to dump CC activity to; set by MOZ_CCTIMER environment variable.
|
||||||
FILE* mFile;
|
FILE* mFile;
|
||||||
|
|
||||||
|
// In case CC slice was triggered during idle time, set to the end of the idle
|
||||||
|
// period.
|
||||||
|
TimeStamp mIdleDeadline;
|
||||||
};
|
};
|
||||||
|
|
||||||
CycleCollectorStats gCCStats;
|
CycleCollectorStats gCCStats;
|
||||||
|
|
||||||
void
|
void
|
||||||
CycleCollectorStats::PrepareForCycleCollectionSlice(int32_t aExtraForgetSkippableCalls)
|
CycleCollectorStats::PrepareForCycleCollectionSlice(TimeStamp aDeadline,
|
||||||
|
int32_t aExtraForgetSkippableCalls)
|
||||||
{
|
{
|
||||||
mBeginSliceTime = TimeStamp::Now();
|
mBeginSliceTime = TimeStamp::Now();
|
||||||
|
mIdleDeadline = aDeadline;
|
||||||
|
|
||||||
// Before we begin the cycle collection, make sure there is no active GC.
|
// Before we begin the cycle collection, make sure there is no active GC.
|
||||||
if (sCCLockedOut) {
|
if (sCCLockedOut) {
|
||||||
|
@ -1636,7 +1683,8 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
|
||||||
PROFILER_LABEL("nsJSContext", "CycleCollectNow",
|
PROFILER_LABEL("nsJSContext", "CycleCollectNow",
|
||||||
js::ProfileEntry::Category::CC);
|
js::ProfileEntry::Category::CC);
|
||||||
|
|
||||||
gCCStats.PrepareForCycleCollectionSlice(aExtraForgetSkippableCalls);
|
gCCStats.PrepareForCycleCollectionSlice(TimeStamp(),
|
||||||
|
aExtraForgetSkippableCalls);
|
||||||
nsCycleCollector_collect(aListener);
|
nsCycleCollector_collect(aListener);
|
||||||
gCCStats.FinishCycleCollectionSlice();
|
gCCStats.FinishCycleCollectionSlice();
|
||||||
}
|
}
|
||||||
|
@ -1655,7 +1703,7 @@ nsJSContext::RunCycleCollectorSlice(TimeStamp aDeadline)
|
||||||
PROFILER_LABEL("nsJSContext", "RunCycleCollectorSlice",
|
PROFILER_LABEL("nsJSContext", "RunCycleCollectorSlice",
|
||||||
js::ProfileEntry::Category::CC);
|
js::ProfileEntry::Category::CC);
|
||||||
|
|
||||||
gCCStats.PrepareForCycleCollectionSlice();
|
gCCStats.PrepareForCycleCollectionSlice(aDeadline);
|
||||||
|
|
||||||
// Decide how long we want to budget for this slice. By default,
|
// Decide how long we want to budget for this slice. By default,
|
||||||
// use an unlimited budget.
|
// use an unlimited budget.
|
||||||
|
@ -1946,6 +1994,8 @@ InterSliceGCRunnerFired(TimeStamp aDeadline, void* aData)
|
||||||
budget = int64_t((aDeadline - TimeStamp::Now()).ToMilliseconds());
|
budget = int64_t((aDeadline - TimeStamp::Now()).ToMilliseconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimeStamp startTimeStamp = TimeStamp::Now();
|
||||||
|
|
||||||
uintptr_t reason = reinterpret_cast<uintptr_t>(aData);
|
uintptr_t reason = reinterpret_cast<uintptr_t>(aData);
|
||||||
nsJSContext::GarbageCollectNow(aData ?
|
nsJSContext::GarbageCollectNow(aData ?
|
||||||
static_cast<JS::gcreason::Reason>(reason) :
|
static_cast<JS::gcreason::Reason>(reason) :
|
||||||
|
@ -1953,6 +2003,28 @@ InterSliceGCRunnerFired(TimeStamp aDeadline, void* aData)
|
||||||
nsJSContext::IncrementalGC,
|
nsJSContext::IncrementalGC,
|
||||||
nsJSContext::NonShrinkingGC,
|
nsJSContext::NonShrinkingGC,
|
||||||
budget);
|
budget);
|
||||||
|
|
||||||
|
TimeDuration duration = sGCUnnotifiedTotalTime;
|
||||||
|
sGCUnnotifiedTotalTime = TimeDuration();
|
||||||
|
|
||||||
|
if (duration.ToSeconds()) {
|
||||||
|
TimeDuration idleDuration;
|
||||||
|
if (!aDeadline.IsNull()) {
|
||||||
|
TimeStamp now = TimeStamp::Now();
|
||||||
|
if (aDeadline < now) {
|
||||||
|
// This slice overflowed the idle period.
|
||||||
|
idleDuration = aDeadline - startTimeStamp;
|
||||||
|
} else {
|
||||||
|
// Note, we don't want to use duration here, since it may contain
|
||||||
|
// data also from JS engine triggered GC slices.
|
||||||
|
idleDuration = now - startTimeStamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t percent =
|
||||||
|
uint32_t(idleDuration.ToSeconds() / duration.ToSeconds() * 100);
|
||||||
|
Telemetry::Accumulate(Telemetry::GC_SLICE_DURING_IDLE, percent);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2424,6 +2496,8 @@ DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress, const JS::GCDescrip
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JS::GC_SLICE_END:
|
case JS::GC_SLICE_END:
|
||||||
|
sGCUnnotifiedTotalTime +=
|
||||||
|
aDesc.lastSliceEnd(aCx) - aDesc.lastSliceStart(aCx);
|
||||||
|
|
||||||
// Schedule another GC slice if the GC has more work to do.
|
// Schedule another GC slice if the GC has more work to do.
|
||||||
nsJSContext::KillInterSliceGCRunner();
|
nsJSContext::KillInterSliceGCRunner();
|
||||||
|
|
|
@ -867,6 +867,15 @@
|
||||||
"n_buckets": 50,
|
"n_buckets": 50,
|
||||||
"description": "Time spent on one asynchronous SnowWhite freeing (ms)"
|
"description": "Time spent on one asynchronous SnowWhite freeing (ms)"
|
||||||
},
|
},
|
||||||
|
"CYCLE_COLLECTOR_SLICE_DURING_IDLE": {
|
||||||
|
"record_in_processes": ["main", "content"],
|
||||||
|
"alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
|
||||||
|
"expires_in_version": "62",
|
||||||
|
"kind": "linear",
|
||||||
|
"high": 100,
|
||||||
|
"n_buckets": 50,
|
||||||
|
"description": "Percent of cycle collector slice done during idle time"
|
||||||
|
},
|
||||||
"DEFERRED_FINALIZE_ASYNC": {
|
"DEFERRED_FINALIZE_ASYNC": {
|
||||||
"record_in_processes": ["main", "content"],
|
"record_in_processes": ["main", "content"],
|
||||||
"expires_in_version": "never",
|
"expires_in_version": "never",
|
||||||
|
@ -923,6 +932,15 @@
|
||||||
"n_buckets": 50,
|
"n_buckets": 50,
|
||||||
"description": "Max time spent on one forget skippable (ms)"
|
"description": "Max time spent on one forget skippable (ms)"
|
||||||
},
|
},
|
||||||
|
"FORGET_SKIPPABLE_DURING_IDLE": {
|
||||||
|
"record_in_processes": ["main", "content"],
|
||||||
|
"alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
|
||||||
|
"expires_in_version": "62",
|
||||||
|
"kind": "linear",
|
||||||
|
"high": 100,
|
||||||
|
"n_buckets": 50,
|
||||||
|
"description": "Percent of the cycle collector's forget skippable done during idle time"
|
||||||
|
},
|
||||||
"FULLSCREEN_TRANSITION_BLACK_MS": {
|
"FULLSCREEN_TRANSITION_BLACK_MS": {
|
||||||
"record_in_processes": ["main", "content"],
|
"record_in_processes": ["main", "content"],
|
||||||
"alert_emails": ["xquan@mozilla.com"],
|
"alert_emails": ["xquan@mozilla.com"],
|
||||||
|
@ -1189,6 +1207,15 @@
|
||||||
"bug_numbers": [1293262],
|
"bug_numbers": [1293262],
|
||||||
"description": "How many objects groups were selected for pretenuring by a minor GC"
|
"description": "How many objects groups were selected for pretenuring by a minor GC"
|
||||||
},
|
},
|
||||||
|
"GC_SLICE_DURING_IDLE": {
|
||||||
|
"record_in_processes": ["main", "content"],
|
||||||
|
"alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
|
||||||
|
"expires_in_version": "62",
|
||||||
|
"kind": "linear",
|
||||||
|
"high": 100,
|
||||||
|
"n_buckets": 50,
|
||||||
|
"description": "Percent of GC slice done during idle time"
|
||||||
|
},
|
||||||
"GEOLOCATION_ACCURACY_EXPONENTIAL": {
|
"GEOLOCATION_ACCURACY_EXPONENTIAL": {
|
||||||
"record_in_processes": ["main", "content"],
|
"record_in_processes": ["main", "content"],
|
||||||
"expires_in_version": "default",
|
"expires_in_version": "default",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче