Bug 2065408 - Add profiler markers for shutdown phases. r=xpcom-reviewers,profiler-reviewers,nika,canova
AdvanceShutdownPhaseInternal emits no profiler markers, so shutdown phases are only indirectly visible through the NotifyObservers marker of the topic each phase fires. XPCOMShutdownFinal and CCPostLastCycleCollection have no observer topic at all, and the notification covers only a part of the phase advance: the two NS_ProcessPendingEvents drains and KillClearOnShutdown run outside it, so runnables processed there show up with no enclosing context. Add an interval marker over the whole advance, plus one for each drain and for KillClearOnShutdown, all carrying the phase name. Differential Revision: https://phabricator.services.mozilla.com/D320446
This commit is contained in:
committed by
jstutte@mozilla.com
parent
f827f59b17
commit
15522dafef
@@ -18,6 +18,7 @@
|
||||
#include "mozilla/LateWriteChecks.h"
|
||||
#include "mozilla/PoisonIOInterposer.h"
|
||||
#include "mozilla/Printf.h"
|
||||
#include "mozilla/ProfilerMarkers.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/SpinEventLoopUntil.h"
|
||||
#include "mozilla/StartupTimeline.h"
|
||||
@@ -354,6 +355,37 @@ bool AppShutdown::IsNoOrLegalShutdownTopic(const char* aTopic) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// AUTO_PROFILER_MARKER_TEXT only adds its marker once the scope ends, so a
|
||||
// profile dumped from inside that scope, as AsyncShutdown does when a blocker
|
||||
// times out, loses it. Emitting the two halves separately survives that.
|
||||
class MOZ_RAII AutoShutdownPhaseMarker {
|
||||
public:
|
||||
AutoShutdownPhaseMarker(const char* aMarkerName, const char* aPhaseName)
|
||||
: mMarkerName(aMarkerName), mPhaseName(aPhaseName) {
|
||||
if (profiler_is_active_and_unpaused()) {
|
||||
Emit(MarkerTiming::IntervalStart());
|
||||
}
|
||||
}
|
||||
|
||||
~AutoShutdownPhaseMarker() {
|
||||
if (profiler_is_active_and_unpaused()) {
|
||||
Emit(MarkerTiming::IntervalEnd());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Only to be called while the profiler is active, MarkerTiming's factories
|
||||
// take a TimeStamp::Now unconditionally.
|
||||
void Emit(MarkerTiming aTiming) {
|
||||
PROFILER_MARKER_TEXT(
|
||||
ProfilerString8View::WrapNullTerminatedString(mMarkerName), OTHER,
|
||||
MarkerOptions(std::move(aTiming)), nsDependentCString(mPhaseName));
|
||||
}
|
||||
|
||||
const char* mMarkerName;
|
||||
const char* mPhaseName;
|
||||
};
|
||||
|
||||
void AppShutdown::AdvanceShutdownPhaseInternal(
|
||||
ShutdownPhase aPhase, bool doNotify, const char16_t* aNotificationData,
|
||||
const nsCOMPtr<nsISupports>& aNotificationSubject) {
|
||||
@@ -373,6 +405,9 @@ void AppShutdown::AdvanceShutdownPhaseInternal(
|
||||
return;
|
||||
}
|
||||
|
||||
const char* phaseName = AppShutdown::GetShutdownPhaseName(aPhase);
|
||||
AutoShutdownPhaseMarker phaseMarker("AdvanceShutdownPhase", phaseName);
|
||||
|
||||
// In case we missed the earlier Init (in the parent) or notification (in
|
||||
// content processes), we ensure the flag is set from now.
|
||||
// This should only ever be needed in some test environments, but it's cheap
|
||||
@@ -402,6 +437,7 @@ void AppShutdown::AdvanceShutdownPhaseInternal(
|
||||
// way of ensuring shutdown processing remains to have an async shutdown
|
||||
// blocker.
|
||||
if (mayProcessPending && thread) {
|
||||
AutoShutdownPhaseMarker drainMarker("ShutdownDrainBeforePhase", phaseName);
|
||||
NS_ProcessPendingEvents(thread);
|
||||
}
|
||||
|
||||
@@ -420,10 +456,15 @@ void AppShutdown::AdvanceShutdownPhaseInternal(
|
||||
// Note that we keep the old order here to avoid breakage, so be aware that
|
||||
// the notifications fired below will find these already cleared in case
|
||||
// you expected the opposite.
|
||||
mozilla::KillClearOnShutdown(aPhase);
|
||||
{
|
||||
AutoShutdownPhaseMarker killMarker("KillClearOnShutdown", phaseName);
|
||||
mozilla::KillClearOnShutdown(aPhase);
|
||||
}
|
||||
|
||||
// Empty our MT event queue to process any side effects thereof.
|
||||
if (mayProcessPending && thread) {
|
||||
AutoShutdownPhaseMarker drainMarker("ShutdownDrainAfterKillClearOnShutdown",
|
||||
phaseName);
|
||||
NS_ProcessPendingEvents(thread);
|
||||
}
|
||||
|
||||
@@ -437,10 +478,18 @@ void AppShutdown::AdvanceShutdownPhaseInternal(
|
||||
sNotifyingShutdownObservers = true;
|
||||
auto reset = MakeScopeExit([] { sNotifyingShutdownObservers = false; });
|
||||
#endif
|
||||
obsService->NotifyObservers(aNotificationSubject, aTopic,
|
||||
aNotificationData);
|
||||
{
|
||||
// nsObserverService emits its own marker with the topic, but that
|
||||
// one is scope bound and vanishes if we hang in here.
|
||||
AutoShutdownPhaseMarker notifyMarker("ShutdownNotifyObservers",
|
||||
phaseName);
|
||||
obsService->NotifyObservers(aNotificationSubject, aTopic,
|
||||
aNotificationData);
|
||||
}
|
||||
// Empty our MT event queue again after the notification has finished
|
||||
if (mayProcessPending && thread) {
|
||||
AutoShutdownPhaseMarker drainMarker("ShutdownDrainAfterNotification",
|
||||
phaseName);
|
||||
NS_ProcessPendingEvents(thread);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user