Bug 1321617 - Don't store profiles on the CPPC; pass them right to the ProfileGatherer. r?njn draft
authorMarkus Stange <mstange@themasta.com>
Sat, 08 Apr 2017 21:54:16 -0400
changeset 559163 fc23b15ea50cb435790be2e4f79ad78d02335776
parent 559162 1569eb0b6973fedef10d79bc3356d208306fc653
child 559164 a579a9e7e6a76ecf0a6e948f45a974fed5ed4dd5
push id53008
push userbmo:mstange@themasta.com
push dateSun, 09 Apr 2017 03:27:44 +0000
reviewersnjn
bugs1321617
milestone55.0a1
Bug 1321617 - Don't store profiles on the CPPC; pass them right to the ProfileGatherer. r?njn MozReview-Commit-ID: 6gaP8Ltm7ms
tools/profiler/gecko/CrossProcessProfilerController.cpp
tools/profiler/gecko/ProfileGatherer.cpp
tools/profiler/gecko/ProfileGatherer.h
tools/profiler/gecko/nsProfiler.cpp
tools/profiler/gecko/nsProfiler.h
tools/profiler/public/CrossProcessProfilerController.h
--- a/tools/profiler/gecko/CrossProcessProfilerController.cpp
+++ b/tools/profiler/gecko/CrossProcessProfilerController.cpp
@@ -2,31 +2,29 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CrossProcessProfilerController.h"
 
 #include "mozilla/Move.h"
 #include "mozilla/ProfilerTypes.h"
 #include "nsIProfiler.h"
-#include "nsIProfileSaveEvent.h"
 #include "nsISupports.h"
 #include "nsIObserver.h"
 #include "nsProfiler.h"
 #include "ProfilerControllingProcess.h"
 
 namespace mozilla {
 
 static const char* sObserverTopics[] = {
   "profiler-started",
   "profiler-stopped",
   "profiler-paused",
   "profiler-resumed",
   "profiler-subprocess-gather",
-  "profiler-subprocess",
 };
 
 // ProfilerObserver is a refcounted class that gets registered with the
 // observer service and just forwards Observe() calls to mController.
 // This indirection makes the CrossProcessProfilerController API nicer because
 // it doesn't require a separate Init() method to register with the observer
 // service, and because not being refcounted allows CPPC to be managed with a
 // UniquePtr.
@@ -80,20 +78,16 @@ CrossProcessProfilerController::CrossPro
     for (size_t i = 0; i < length; ++i) {
       obs->AddObserver(mObserver, sObserverTopics[i], false);
     }
   }
 }
 
 CrossProcessProfilerController::~CrossProcessProfilerController()
 {
-  if (!mProfile.IsEmpty()) {
-    nsProfiler::GetOrCreate()->OOPExitProfile(mProfile);
-  }
-
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     size_t length = ArrayLength(sObserverTopics);
     for (size_t i = 0; i < length; ++i) {
       obs->RemoveObserver(mObserver, sObserverTopics[i]);
     }
   }
 }
@@ -123,29 +117,16 @@ CrossProcessProfilerController::Observe(
   if (!strcmp(aTopic, "profiler-subprocess-gather")) {
     // profiler-subprocess-gather is the request to capture the profile. We
     // need to tell the other process that we're interested in its profile,
     // and we tell the gatherer that we've forwarded the request, so that it
     // can keep track of the number of pending profiles.
     nsProfiler::GetOrCreate()->WillGatherOOPProfile();
     mProcess->SendGatherProfile();
   }
-  else if (!strcmp(aTopic, "profiler-subprocess")) {
-    // profiler-subprocess is sent once the gatherer knows that all other
-    // processes have replied with their profiles. It's sent during the final
-    // assembly of the parent process profile, and this is where we pass the
-    // subprocess profile along.
-    nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
-    if (pse) {
-      if (!mProfile.IsEmpty()) {
-        pse->AddSubProfile(mProfile.get());
-        mProfile.Truncate();
-      }
-    }
-  }
   // These four notifications are sent by the profiler when its corresponding
   // methods are called inside this process. These state changes just need to
   // be forwarded to the other process.
   else if (!strcmp(aTopic, "profiler-started")) {
     nsCOMPtr<nsIProfilerStartParams> params(do_QueryInterface(aSubject));
     StartProfiler(params);
   }
   else if (!strcmp(aTopic, "profiler-stopped")) {
@@ -160,18 +141,17 @@ CrossProcessProfilerController::Observe(
 }
 
 // This is called in response to a SendGatherProfile request, or when the
 // other process exits while the profiler is running.
 void
 CrossProcessProfilerController::RecvProfile(const nsCString& aProfile,
                                             bool aIsExitProfile)
 {
-  // Store the profile on this object.
-  mProfile = aProfile;
-  // Tell the gatherer that we've received the profile from this process, but
-  // don't actually give it the profile. It will request the profile once all
-  // processes have replied, through the "profiler-subprocess" observer
-  // notification.
-  nsProfiler::GetOrCreate()->GatheredOOPProfile();
+  // Pass our process's profile along to nsProfiler.
+  if (aIsExitProfile) {
+    nsProfiler::GetOrCreate()->OOPExitProfile(aProfile);
+  } else {
+    nsProfiler::GetOrCreate()->GatheredOOPProfile(aProfile);
+  }
 }
 
 } // namespace mozilla
--- a/tools/profiler/gecko/ProfileGatherer.cpp
+++ b/tools/profiler/gecko/ProfileGatherer.cpp
@@ -36,33 +36,35 @@ ProfileGatherer::ProfileGatherer()
 }
 
 ProfileGatherer::~ProfileGatherer()
 {
   Cancel();
 }
 
 void
-ProfileGatherer::GatheredOOPProfile()
+ProfileGatherer::GatheredOOPProfile(const nsACString& aProfile)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   if (!mGathering) {
     // If we're not actively gathering, then we don't actually
     // care that we gathered a profile here. This can happen for
     // processes that exit while profiling.
     return;
   }
 
   if (NS_WARN_IF(!mPromise && !mFile)) {
     // If we're not holding on to a Promise, then someone is
     // calling us erroneously.
     return;
   }
 
+  mResponseProfiles.AppendElement(aProfile);
+
   mPendingProfiles--;
 
   if (mPendingProfiles == 0) {
     // We've got all of the async profiles now. Let's
     // finish off the profile and resolve the Promise.
     Finish();
   }
 }
@@ -251,14 +253,20 @@ ProfileGatherer::Observe(nsISupports* aS
     nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
     if (pse) {
       for (size_t i = 0; i < mExitProfiles.Length(); ++i) {
         if (!mExitProfiles[i].IsEmpty()) {
           pse->AddSubProfile(mExitProfiles[i].get());
         }
       }
       mExitProfiles.Clear();
+      for (size_t i = 0; i < mResponseProfiles.Length(); ++i) {
+        if (!mResponseProfiles[i].IsEmpty()) {
+          pse->AddSubProfile(mResponseProfiles[i].get());
+        }
+      }
+      mResponseProfiles.Clear();
     }
   }
   return NS_OK;
 }
 
 } // namespace mozilla
--- a/tools/profiler/gecko/ProfileGatherer.h
+++ b/tools/profiler/gecko/ProfileGatherer.h
@@ -14,28 +14,29 @@ namespace mozilla {
 class ProfileGatherer final : public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   explicit ProfileGatherer();
   void WillGatherOOPProfile();
-  void GatheredOOPProfile();
+  void GatheredOOPProfile(const nsACString& aProfile);
   void Start(double aSinceTime, mozilla::dom::Promise* aPromise);
   void Start(double aSinceTime, const nsACString& aFileName);
   void Cancel();
   void OOPExitProfile(const nsACString& aProfile);
 
 private:
   ~ProfileGatherer();
   void Finish();
   void Reset();
   void Start2(double aSinceTime);
 
+  nsTArray<nsCString> mResponseProfiles;
   nsTArray<nsCString> mExitProfiles;
   RefPtr<mozilla::dom::Promise> mPromise;
   nsCOMPtr<nsIFile> mFile;
   double mSinceTime;
   uint32_t mPendingProfiles;
   bool mGathering;
 };
 
--- a/tools/profiler/gecko/nsProfiler.cpp
+++ b/tools/profiler/gecko/nsProfiler.cpp
@@ -356,25 +356,25 @@ nsProfiler::WillGatherOOPProfile()
   if (!mGatherer) {
     return;
   }
 
   mGatherer->WillGatherOOPProfile();
 }
 
 void
-nsProfiler::GatheredOOPProfile()
+nsProfiler::GatheredOOPProfile(const nsACString& aProfile)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   if (!mGatherer) {
     return;
   }
 
-  mGatherer->GatheredOOPProfile();
+  mGatherer->GatheredOOPProfile(aProfile);
 }
 
 void
 nsProfiler::OOPExitProfile(const nsACString& aProfile)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   if (!mGatherer) {
--- a/tools/profiler/gecko/nsProfiler.h
+++ b/tools/profiler/gecko/nsProfiler.h
@@ -28,17 +28,17 @@ public:
     static nsProfiler* GetOrCreate()
     {
 	nsCOMPtr<nsIProfiler> iprofiler =
 	    do_GetService("@mozilla.org/tools/profiler;1");
 	return static_cast<nsProfiler*>(iprofiler.get());
     }
 
     void WillGatherOOPProfile();
-    void GatheredOOPProfile();
+    void GatheredOOPProfile(const nsACString& aProfile);
     void OOPExitProfile(const nsACString& aProfile);
 
 private:
     ~nsProfiler();
 
     RefPtr<ProfileGatherer> mGatherer;
     bool mLockedForPrivateBrowsing;
 };
--- a/tools/profiler/public/CrossProcessProfilerController.h
+++ b/tools/profiler/public/CrossProcessProfilerController.h
@@ -30,14 +30,13 @@ public:
 private:
   void StartProfiler(nsIProfilerStartParams* aParams);
   void Observe(nsISupports* aSubject, const char* aTopic);
 
   friend class ProfilerObserver;
 
   ProfilerControllingProcess* mProcess;
   RefPtr<ProfilerObserver> mObserver;
-  nsCString mProfile;
 };
 
 } // namespace mozilla
 
 #endif