Bug 1462784 - Annotate idle stacks in the native event loop on macOS. r?spohl draft
authorMarkus Stange <mstange@themasta.com>
Wed, 16 May 2018 13:31:02 -0400
changeset 803069 250e414943defae2578ff532a35bb5e5a42faa8b
parent 803068 4eecd1d054e6342f2a1e9f039e77a8dd582d5f31
child 803070 5ea1be35e1849f82c84003d11fde9d1fc18040ea
push id112022
push userbmo:mstange@themasta.com
push dateFri, 01 Jun 2018 21:00:49 +0000
reviewersspohl
bugs1462784
milestone62.0a1
Bug 1462784 - Annotate idle stacks in the native event loop on macOS. r?spohl MozReview-Commit-ID: HD48iBTT8EN
widget/cocoa/nsAppShell.mm
--- a/widget/cocoa/nsAppShell.mm
+++ b/widget/cocoa/nsAppShell.mm
@@ -126,16 +126,21 @@ private:
 extern int32_t             gXULModalLevel;
 
 static bool gAppShellMethodsSwizzled = false;
 
 @implementation GeckoNSApplication
 
 - (void)sendEvent:(NSEvent *)anEvent
 {
+  // Mark this function as non-idle because it's one of the exit points from
+  // the event loop (running inside of -[GeckoNSApplication nextEventMatchingMask:...])
+  // into non-idle code. So we basically unset the IDLE category from the inside.
+  AUTO_PROFILER_LABEL("-[GeckoNSApplication sendEvent:]", OTHER);
+
   mozilla::HangMonitor::NotifyActivity();
   if ([anEvent type] == NSApplicationDefined &&
       [anEvent subtype] == kEventSubtypeTrace) {
     mozilla::SignalTracerThread();
     return;
   }
   [super sendEvent:anEvent];
 }
@@ -147,16 +152,30 @@ static bool gAppShellMethodsSwizzled = f
 - (NSEvent*)nextEventMatchingMask:(NSEventMask)mask
 #else
 - (NSEvent*)nextEventMatchingMask:(NSUInteger)mask
 #endif
                         untilDate:(NSDate*)expiration
                            inMode:(NSString*)mode
                           dequeue:(BOOL)flag
 {
+  // When we're waiting in the event loop, this is the last function under our
+  // control that's on the stack, so this is the function that we mark with the
+  // IDLE category.
+  // However, when we're processing an event or when our CFRunLoopSource runs,
+  // this function is still on the stack - "the event loop calls us". So we
+  // need to mark functions that enter non-idle code with a different profiler
+  // category, usually OTHER. This gives the profiler a rough approximation of
+  // idleness but isn't perfect. For example, sometimes there's some Cocoa-
+  // internal activity that's triggered from the event loop, and we'll
+  // misidentify the stacks for that activity as idle because there's no Gecko
+  // code on the stack that can change the stack's category to something
+  // non-idle.
+  AUTO_PROFILER_LABEL("-[GeckoNSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]", IDLE);
+
   if (expiration) {
     mozilla::HangMonitor::Suspend();
   }
   NSEvent* nextEvent = [super nextEventMatchingMask:mask
                         untilDate:expiration inMode:mode dequeue:flag];
   if (expiration) {
     mozilla::HangMonitor::NotifyActivity();
   }