Bug 1193838 - Expose ProfileGatherer as an nsISupports through nsIProfiler for process parent actors. r=BenWa

We need to let ContentParent and PluginModuleParent get a reference to the ProfileGatherer
during the window of time that we're profiling so that if they start to die (the actor is
starting to go away), they have a gatherer they can send their last profile data to.
This commit is contained in:
Mike Conley 2015-08-12 14:20:26 -04:00
parent a4a9e691fa
commit 374f39cebf
10 changed files with 143 additions and 25 deletions

View File

@ -1569,6 +1569,11 @@ ContentParent::Init()
rv = profiler->GetStartParams(getter_AddRefs(currentProfilerParams));
MOZ_ASSERT(NS_SUCCEEDED(rv));
nsCOMPtr<nsISupports> gatherer;
rv = profiler->GetProfileGatherer(getter_AddRefs(gatherer));
MOZ_ASSERT(NS_SUCCEEDED(rv));
mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
StartProfiler(currentProfilerParams);
}
#endif
@ -3293,6 +3298,7 @@ ContentParent::Observe(nsISupports* aSubject,
StartProfiler(params);
}
else if (!strcmp(aTopic, "profiler-stopped")) {
mGatherer = nullptr;
Unused << SendStopProfiler();
}
else if (!strcmp(aTopic, "profiler-paused")) {
@ -3302,9 +3308,10 @@ ContentParent::Observe(nsISupports* aSubject,
Unused << SendPauseProfiler(false);
}
else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
mGatherer = static_cast<ProfileGatherer*>(aSubject);
mGatherer->WillGatherOOPProfile();
Unused << SendGatherProfile();
if (mGatherer) {
mGatherer->WillGatherOOPProfile();
Unused << SendGatherProfile();
}
}
else if (!strcmp(aTopic, "profiler-subprocess")) {
nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
@ -5656,7 +5663,6 @@ ContentParent::RecvProfile(const nsCString& aProfile)
}
mProfile = aProfile;
mGatherer->GatheredOOPProfile();
mGatherer = nullptr;
#endif
return true;
}
@ -5747,6 +5753,14 @@ ContentParent::StartProfiler(nsIProfilerStartParams* aParams)
ipcParams.threadFilters() = aParams->GetThreadFilterNames();
Unused << SendStartProfiler(ipcParams);
nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
if (NS_WARN_IF(!profiler)) {
return;
}
nsCOMPtr<nsISupports> gatherer;
profiler->GetProfileGatherer(getter_AddRefs(gatherer));
mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
#endif
}

View File

@ -627,6 +627,25 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
}
#endif
}
#ifdef MOZ_ENABLE_PROFILER_SPS
nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
bool profilerActive = false;
DebugOnly<nsresult> rv = profiler->IsActive(&profilerActive);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (profilerActive) {
nsCOMPtr<nsIProfilerStartParams> currentProfilerParams;
rv = profiler->GetStartParams(getter_AddRefs(currentProfilerParams));
MOZ_ASSERT(NS_SUCCEEDED(rv));
nsCOMPtr<nsISupports> gatherer;
rv = profiler->GetProfileGatherer(getter_AddRefs(gatherer));
MOZ_ASSERT(NS_SUCCEEDED(rv));
mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
StartProfiler(currentProfilerParams);
}
#endif
}
bool
@ -3162,23 +3181,9 @@ PluginProfilerObserver::Observe(nsISupports *aSubject,
{
if (!strcmp(aTopic, "profiler-started")) {
nsCOMPtr<nsIProfilerStartParams> params(do_QueryInterface(aSubject));
uint32_t entries;
double interval;
params->GetEntries(&entries);
params->GetInterval(&interval);
const nsTArray<nsCString>& features = params->GetFeatures();
const nsTArray<nsCString>& threadFilterNames = params->GetThreadFilterNames();
ProfilerInitParams ipcParams;
ipcParams.enabled() = true;
ipcParams.entries() = entries;
ipcParams.interval() = interval;
ipcParams.features() = features;
ipcParams.threadFilters() = threadFilterNames;
Unused << mPmp->SendStartProfiler(ipcParams);
mPmp->StartProfiler(params);
} else if (!strcmp(aTopic, "profiler-stopped")) {
Unused << mPmp->SendStopProfiler();
mPmp->StopProfiler();
} else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
RefPtr<ProfileGatherer> gatherer = static_cast<ProfileGatherer*>(aSubject);
mPmp->GatherAsyncProfile(gatherer);
@ -3215,9 +3220,44 @@ PluginModuleChromeParent::ShutdownPluginProfiling()
}
void
PluginModuleChromeParent::GatherAsyncProfile(ProfileGatherer* aGatherer)
PluginModuleChromeParent::StartProfiler(nsIProfilerStartParams* aParams)
{
mGatherer = aGatherer;
if (NS_WARN_IF(!aParams)) {
return;
}
ProfilerInitParams ipcParams;
ipcParams.enabled() = true;
aParams->GetEntries(&ipcParams.entries());
aParams->GetInterval(&ipcParams.interval());
ipcParams.features() = aParams->GetFeatures();
ipcParams.threadFilters() = aParams->GetThreadFilterNames();
Unused << SendStartProfiler(ipcParams);
nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
if (NS_WARN_IF(!profiler)) {
return;
}
nsCOMPtr<nsISupports> gatherer;
profiler->GetProfileGatherer(getter_AddRefs(gatherer));
mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
}
void
PluginModuleChromeParent::StopProfiler()
{
mGatherer = nullptr;
Unused << SendStopProfiler();
}
void
PluginModuleChromeParent::GatherAsyncProfile()
{
if (NS_WARN_IF(!mGatherer)) {
return;
}
mGatherer->WillGatherOOPProfile();
Unused << SendGatherProfile();
}
@ -3242,7 +3282,6 @@ PluginModuleChromeParent::RecvProfile(const nsCString& aProfile)
mProfile = aProfile;
mGatherer->GatheredOOPProfile();
mGatherer = nullptr;
#endif
return true;
}

View File

@ -456,8 +456,10 @@ class PluginModuleChromeParent
void OnExitedSyncSend() override;
#ifdef MOZ_ENABLE_PROFILER_SPS
void GatherAsyncProfile(mozilla::ProfileGatherer* aGatherer);
void GatherAsyncProfile();
void GatheredAsyncProfile(nsIProfileSaveEvent* aSaveEvent);
void StartProfiler(nsIProfilerStartParams* aParams);
void StopProfiler();
#endif
virtual bool

View File

@ -410,6 +410,14 @@ JSObject* GeckoSampler::ToJSObject(JSContext *aCx, double aSinceTime)
}
return &val.toObject();
}
void GeckoSampler::GetGatherer(nsISupports** aRetVal)
{
if (!aRetVal || NS_WARN_IF(!mGatherer)) {
return;
}
NS_ADDREF(*aRetVal = mGatherer);
}
#endif
UniquePtr<char[]> GeckoSampler::ToJSON(double aSinceTime)

View File

@ -104,6 +104,7 @@ class GeckoSampler: public Sampler {
void ToStreamAsJSON(std::ostream& stream, double aSinceTime = 0);
#ifndef SPS_STANDALONE
virtual JSObject *ToJSObject(JSContext *aCx, double aSinceTime = 0);
void GetGatherer(nsISupports** aRetVal);
#endif
mozilla::UniquePtr<char[]> ToJSON(double aSinceTime = 0);
virtual void ToJSObjectAsync(double aSinceTime = 0, mozilla::dom::Promise* aPromise = 0);

View File

@ -642,6 +642,26 @@ void mozilla_sampler_get_profiler_start_params(int* aEntrySize,
}
}
void mozilla_sampler_get_gatherer(nsISupports** aRetVal)
{
if (!aRetVal) {
return;
}
if (NS_WARN_IF(!profiler_is_active())) {
*aRetVal = nullptr;
return;
}
GeckoSampler *t = tlsTicker.get();
if (NS_WARN_IF(!t)) {
*aRetVal = nullptr;
return;
}
t->GetGatherer(aRetVal);
}
#endif
void mozilla_sampler_save_profile_to_file(const char* aFilename)

View File

@ -27,7 +27,7 @@ interface nsIProfilerStartParams : nsISupports
[noscript, notxpcom, nostdcall] StringArrayRef getThreadFilterNames();
};
[scriptable, uuid(b373b360-c997-448a-b60d-4985b70dc810)]
[scriptable, uuid(ead3f75c-0e0e-4fbb-901c-1e5392ef5b2a)]
interface nsIProfiler : nsISupports
{
boolean CanProfile();
@ -66,6 +66,12 @@ interface nsIProfiler : nsISupports
*/
readonly attribute nsIProfilerStartParams startParams;
/**
* The profileGatherer will be null if the profiler is not currently
* active.
*/
readonly attribute nsISupports profileGatherer;
void GetBufferInfo(out uint32_t aCurrentPosition, out uint32_t aTotalSize,
out uint32_t aGeneration);

View File

@ -288,3 +288,21 @@ nsProfiler::GetBufferInfo(uint32_t *aCurrentPosition, uint32_t *aTotalSize, uint
profiler_get_buffer_info(aCurrentPosition, aTotalSize, aGeneration);
return NS_OK;
}
NS_IMETHODIMP
nsProfiler::GetProfileGatherer(nsISupports** aRetVal)
{
if (!aRetVal) {
return NS_ERROR_INVALID_POINTER;
}
// If we're not profiling, there will be no gatherer.
if (!profiler_is_active()) {
*aRetVal = nullptr;
} else {
nsCOMPtr<nsISupports> gatherer;
profiler_get_gatherer(getter_AddRefs(gatherer));
gatherer.forget(aRetVal);
}
return NS_OK;
}

View File

@ -14,6 +14,8 @@
#include "mozilla/Vector.h"
#include <stdint.h>
class nsISupports;
namespace mozilla {
class TimeStamp;
@ -73,6 +75,7 @@ void mozilla_sampler_get_profiler_start_params(int* aEntrySize,
double* aInterval,
mozilla::Vector<const char*>* aFilters,
mozilla::Vector<const char*>* aFeatures);
void mozilla_sampler_get_gatherer(nsISupports** aRetVal);
#endif
// Make this function easily callable from a debugger in a build without

View File

@ -179,6 +179,13 @@ void profiler_get_start_params(int* aEntrySize,
{
mozilla_sampler_get_profiler_start_params(aEntrySize, aInterval, aFilters, aFeatures);
}
static inline
void profiler_get_gatherer(nsISupports** aRetVal)
{
mozilla_sampler_get_gatherer(aRetVal);
}
#endif
static inline