Bug 1321617 - Don't store profiles on the CPPC; pass them right to the ProfileGatherer. r?njn
MozReview-Commit-ID: 6gaP8Ltm7ms
--- 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