Bug 992454 - Part 2: Integrate TaskTracer into GeckoProfiler. r=benwa.
authorShelly Lin <slin@mozilla.com>
Tue, 14 Oct 2014 10:56:44 +0800
changeset 210326 d150f12f7e603ec059a76b6b0ffe6fe03d3deaee
parent 210325 6cb2c1756e099c72159ae4d9574956440de6d416
child 210327 3193763d0a3bbe6bfca4a07f73802320e3b8ca07
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbenwa
bugs992454
milestone36.0a1
Bug 992454 - Part 2: Integrate TaskTracer into GeckoProfiler. r=benwa.
tools/profiler/TableTicker.cpp
tools/profiler/TableTicker.h
tools/profiler/platform.cpp
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -31,16 +31,17 @@
 #include "nsServiceManagerUtils.h"
 #include "nsIXULRuntime.h"
 #include "nsIXULAppInfo.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "PlatformMacros.h"
+#include "nsTArray.h"
 
 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   #include "AndroidBridge.h"
 #endif
 
 // JS
 #include "jsfriendapi.h"
 #include "js/ProfilingFrameIterator.h"
@@ -101,16 +102,53 @@ void TableTicker::HandleSaveRequest()
   mSaveRequested = false;
 
   // TODO: Use use the ipc/chromium Tasks here to support processes
   // without XPCOM.
   nsCOMPtr<nsIRunnable> runnable = new SaveProfileTask();
   NS_DispatchToMainThread(runnable);
 }
 
+
+void TableTicker::StreamTaskTracer(JSStreamWriter& b)
+{
+  b.BeginObject();
+#ifdef MOZ_TASK_TRACER
+    b.Name("data");
+    b.BeginArray();
+      nsAutoPtr<nsTArray<nsCString>> data(
+        mozilla::tasktracer::GetLoggedData(sStartTime));
+      for (uint32_t i = 0; i < data->Length(); ++i) {
+        b.Value((data->ElementAt(i)).get());
+      }
+      mozilla::tasktracer::StartLogging();
+    b.EndArray();
+
+    b.Name("threads");
+    b.BeginArray();
+      mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
+      for (size_t i = 0; i < sRegisteredThreads->size(); i++) {
+        // Thread meta data
+        ThreadInfo* info = sRegisteredThreads->at(i);
+        b.BeginObject();
+        if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
+          // TODO Add the proper plugin name
+          b.NameValue("name", "Plugin");
+        } else {
+          b.NameValue("name", info->Name());
+        }
+        b.NameValue("tid", static_cast<int>(info->ThreadId()));
+        b.EndObject();
+      }
+    b.EndArray();
+#endif
+  b.EndObject();
+}
+
+
 void TableTicker::StreamMetaJSCustomObject(JSStreamWriter& b)
 {
   b.BeginObject();
 
     b.NameValue("version", 2);
     b.NameValue("interval", interval());
     b.NameValue("stackwalk", mUseStackWalk);
     b.NameValue("jank", mJankOnly);
@@ -265,16 +303,22 @@ void TableTicker::StreamJSObject(JSStrea
   b.BeginObject();
     // Put shared library info
     b.NameValue("libs", GetSharedLibraryInfoString().c_str());
 
     // Put meta data
     b.Name("meta");
     StreamMetaJSCustomObject(b);
 
+    // Data of TaskTracer doesn't belong in the circular buffer.
+    if (TaskTracer()) {
+      b.Name("tasktracer");
+      StreamTaskTracer(b);
+    }
+
     // Lists the samples for each ThreadProfile
     b.Name("threads");
     b.BeginArray();
 
       SetPaused(true);
 
       {
         mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
--- a/tools/profiler/TableTicker.h
+++ b/tools/profiler/TableTicker.h
@@ -5,16 +5,19 @@
 
 #ifndef TableTicker_h
 #define TableTicker_h
 
 #include "platform.h"
 #include "ProfileEntry.h"
 #include "mozilla/Mutex.h"
 #include "IntelPowerGadget.h"
+#ifdef MOZ_TASK_TRACER
+#include "GeckoTaskTracer.h"
+#endif
 
 static bool
 hasFeature(const char** aFeatures, uint32_t aFeatureCount, const char* aFeature) {
   for(size_t i = 0; i < aFeatureCount; i++) {
     if (strcmp(aFeatures[i], aFeature) == 0)
       return true;
   }
   return false;
@@ -68,16 +71,17 @@ class TableTicker: public Sampler {
     // Users sometimes ask to filter by a list of threads but forget to request
     // profiling non main threads. Let's make it implificit if we have a filter
     mProfileThreads = hasFeature(aFeatures, aFeatureCount, "threads") || aFilterCount > 0;
     mUnwinderThread = hasFeature(aFeatures, aFeatureCount, "unwinder") || sps_version2();
     mAddLeafAddresses = hasFeature(aFeatures, aFeatureCount, "leaf");
     mPrivacyMode = hasFeature(aFeatures, aFeatureCount, "privacy");
     mAddMainThreadIO = hasFeature(aFeatures, aFeatureCount, "mainthreadio");
     mProfileMemory = hasFeature(aFeatures, aFeatureCount, "memory");
+    mTaskTracer = hasFeature(aFeatures, aFeatureCount, "tasktracer");
 
 #if defined(XP_WIN)
     if (mProfilePower) {
       mIntelPowerGadget = new IntelPowerGadget();
       mProfilePower = mIntelPowerGadget->Init();
     }
 #endif
 
@@ -96,16 +100,22 @@ class TableTicker: public Sampler {
       for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
         ThreadInfo* info = sRegisteredThreads->at(i);
 
         RegisterThread(info);
       }
 
       SetActiveSampler(this);
     }
+
+#ifdef MOZ_TASK_TRACER
+    if (mTaskTracer) {
+      mozilla::tasktracer::StartLogging();
+    }
+#endif
   }
 
   ~TableTicker() {
     if (IsActive())
       Stop();
 
     SetActiveSampler(nullptr);
 
@@ -152,16 +162,21 @@ class TableTicker: public Sampler {
 
   // Immediately captures the calling thread's call stack and returns it.
   virtual SyncProfile* GetBacktrace();
 
   // Called within a signal. This function must be reentrant
   virtual void RequestSave()
   {
     mSaveRequested = true;
+#ifdef MOZ_TASK_TRACER
+    if (mTaskTracer) {
+      mozilla::tasktracer::StopLogging();
+    }
+#endif
   }
 
   virtual void HandleSaveRequest();
 
   ThreadProfile* GetPrimaryThreadProfile()
   {
     if (!mPrimaryThreadProfile) {
       mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
@@ -176,24 +191,26 @@ class TableTicker: public Sampler {
     }
 
     return mPrimaryThreadProfile;
   }
 
   void ToStreamAsJSON(std::ostream& stream);
   virtual JSObject *ToJSObject(JSContext *aCx);
   void StreamMetaJSCustomObject(JSStreamWriter& b);
+  void StreamTaskTracer(JSStreamWriter& b);
   bool HasUnwinderThread() const { return mUnwinderThread; }
   bool ProfileJS() const { return mProfileJS; }
   bool ProfileJava() const { return mProfileJava; }
   bool ProfilePower() const { return mProfilePower; }
   bool ProfileThreads() const { return mProfileThreads; }
   bool InPrivacyMode() const { return mPrivacyMode; }
   bool AddMainThreadIO() const { return mAddMainThreadIO; }
   bool ProfileMemory() const { return mProfileMemory; }
+  bool TaskTracer() const { return mTaskTracer; }
 
 protected:
   // Called within a signal. This function must be reentrant
   virtual void UnwinderTick(TickSample* sample);
 
   // Called within a signal. This function must be reentrant
   virtual void InplaceTick(TickSample* sample);
 
@@ -216,15 +233,16 @@ protected:
 
   // Keep the thread filter to check against new thread that
   // are started while profiling
   char** mThreadNameFilters;
   uint32_t mFilterCount;
   bool mPrivacyMode;
   bool mAddMainThreadIO;
   bool mProfileMemory;
+  bool mTaskTracer;
 #if defined(XP_WIN)
   IntelPowerGadget* mIntelPowerGadget;
 #endif
 };
 
 #endif
 
--- a/tools/profiler/platform.cpp
+++ b/tools/profiler/platform.cpp
@@ -684,16 +684,20 @@ const char** mozilla_sampler_get_feature
     // Profile the registered secondary threads.
     "threads",
     // Do not include user-identifiable information
     "privacy",
     // Add main thread I/O to the profile
     "mainthreadio",
     // Add RSS collection
     "memory",
+#ifdef MOZ_TASK_TRACER
+    // Start profiling with feature TaskTracer.
+    "tasktracer",
+#endif
 #if defined(XP_WIN)
     // Add power collection
     "power",
 #endif
     nullptr
   };
 
   return features;