Bug 785440 - Add AUTO_PROFILER_LABEL_FAST. r?njn draft
authorMarkus Stange <mstange@themasta.com>
Fri, 05 Jan 2018 14:37:42 +0100
changeset 752762 dcbeccca5644c66053c74297a4136a500a61c765
parent 752761 4ff98962d0b9c6e2fed035d36b918d306dca7717
child 752763 b01b4d5d4b1861ef9646c861c6d3393d977c0476
push id98367
push userbmo:mstange@themasta.com
push dateThu, 08 Feb 2018 21:45:52 +0000
reviewersnjn
bugs785440
milestone60.0a1
Bug 785440 - Add AUTO_PROFILER_LABEL_FAST. r?njn This gets the pseudostack from the JSContext instead of using TLS, and only pushes a pseudo stack frame if the profiler is active. MozReview-Commit-ID: IzT4py9H8su
tools/profiler/public/GeckoProfiler.h
--- a/tools/profiler/public/GeckoProfiler.h
+++ b/tools/profiler/public/GeckoProfiler.h
@@ -57,18 +57,19 @@
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/ThreadLocal.h"
 #include "mozilla/UniquePtr.h"
+#include "js/ProfilingStack.h"
+#include "js/RootingAPI.h"
 #include "js/TypeDecls.h"
-#include "js/ProfilingStack.h"
 #include "nscore.h"
 
 // Make sure that we can use std::min here without the Windows headers messing
 // with us.
 #ifdef min
 # undef min
 #endif
 
@@ -500,16 +501,26 @@ PseudoStack* profiler_get_pseudo_stack()
   mozilla::Maybe<NS_LossyConvertUTF16toASCII> asciiStr; \
   mozilla::Maybe<AutoProfilerLabel> raiiObjectLossyNsString; \
   if (profiler_is_active()) { \
     asciiStr.emplace(nsStr); \
     raiiObjectLossyNsString.emplace(label, asciiStr->get(), __LINE__, \
                                     js::ProfileEntry::Category::category); \
   }
 
+// Similar to AUTO_PROFILER_LABEL, but accepting a JSContext* parameter, and a
+// no-op if the profiler is disabled.
+// Used to annotate functions for which overhead in the range of nanoseconds is
+// noticeable. It avoids overhead from the TLS lookup because it can get the
+// PseudoStack from the JS context, and avoids almost all overhead in the case
+// where the profiler is disabled.
+#define AUTO_PROFILER_LABEL_FAST(label, category, ctx) \
+  mozilla::AutoProfilerLabel PROFILER_RAII(ctx, label, nullptr, __LINE__, \
+                                           js::ProfileEntry::Category::category)
+
 // Insert a marker in the profile timeline. This is useful to delimit something
 // important happening such as the first paint. Unlike labels, which are only
 // recorded in the profile buffer if a sample is collected while the label is
 // on the pseudostack, markers will always be recorded in the profile buffer.
 // aMarkerName is copied, so the caller does not need to ensure it lives for a
 // certain length of time. A no-op if the profiler is inactive or in privacy
 // mode.
 #define PROFILER_ADD_MARKER(markerName) \
@@ -655,25 +666,50 @@ private:
 
 // This class creates a non-owning PseudoStack reference. Objects of this class
 // are stack-allocated, and so exist within a thread, and are thus bounded by
 // the lifetime of the thread, which ensures that the references held can't be
 // used after the PseudoStack is destroyed.
 class MOZ_RAII AutoProfilerLabel
 {
 public:
+  // This is the AUTO_PROFILER_LABEL and AUTO_PROFILER_LABEL_DYNAMIC variant.
   AutoProfilerLabel(const char* aLabel, const char* aDynamicString,
                     uint32_t aLine, js::ProfileEntry::Category aCategory
                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
+    // Get the PseudoStack from TLS.
+    Push(sPseudoStack.get(), aLabel, aDynamicString, aLine, aCategory);
+  }
+
+  // This is the AUTO_PROFILER_LABEL_FAST variant. It's guarded on
+  // profiler_is_active() and retrieves the PseudoStack from the JSContext.
+  AutoProfilerLabel(JSContext* aJSContext,
+                    const char* aLabel, const char* aDynamicString,
+                    uint32_t aLine, js::ProfileEntry::Category aCategory
+                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+  {
+    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    if (profiler_is_active()) {
+      Push(js::GetContextProfilingStack(aJSContext),
+           aLabel, aDynamicString, aLine, aCategory);
+    } else {
+      mPseudoStack = nullptr;
+    }
+  }
+
+  void Push(PseudoStack* aPseudoStack,
+            const char* aLabel, const char* aDynamicString,
+            uint32_t aLine, js::ProfileEntry::Category aCategory)
+  {
     // This function runs both on and off the main thread.
 
-    mPseudoStack = sPseudoStack.get();
+    mPseudoStack = aPseudoStack;
     if (mPseudoStack) {
       mPseudoStack->pushCppFrame(aLabel, aDynamicString, this, aLine,
                                  js::ProfileEntry::Kind::CPP_NORMAL, aCategory);
     }
   }
 
   ~AutoProfilerLabel()
   {