--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -1348,104 +1348,81 @@ BuildJavaThreadJSObject(SpliceableJSONWr
}
}
}
aWriter.EndArray();
}
#endif
static void
-StreamJSON(PS::LockRef aLock, SpliceableJSONWriter& aWriter, double aSinceTime)
+locked_profiler_stream_json_for_this_process(PS::LockRef aLock, SpliceableJSONWriter& aWriter, double aSinceTime)
{
- LOG("StreamJSON");
+ LOG("locked_profiler_stream_json_for_this_process");
MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(gPS && gPS->IsActive(aLock));
- aWriter.Start(SpliceableJSONWriter::SingleLineStyle);
+ // Put shared library info
+ aWriter.StartArrayProperty("libs");
+ AppendSharedLibraries(aWriter);
+ aWriter.EndArray();
+
+ // Put meta data
+ aWriter.StartObjectProperty("meta");
{
- // Put shared library info
- aWriter.StartArrayProperty("libs");
- AppendSharedLibraries(aWriter);
- aWriter.EndArray();
-
- // Put meta data
- aWriter.StartObjectProperty("meta");
+ StreamMetaJSCustomObject(aLock, aWriter);
+ }
+ aWriter.EndObject();
+
+ // Data of TaskTracer doesn't belong in the circular buffer.
+ if (gPS->FeatureTaskTracer(aLock)) {
+ aWriter.StartObjectProperty("tasktracer");
+ StreamTaskTracer(aLock, aWriter);
+ aWriter.EndObject();
+ }
+
+ // Lists the samples for each thread profile
+ aWriter.StartArrayProperty("threads");
+ {
+ gPS->SetIsPaused(aLock, true);
+
{
- StreamMetaJSCustomObject(aLock, aWriter);
- }
- aWriter.EndObject();
-
- // Data of TaskTracer doesn't belong in the circular buffer.
- if (gPS->FeatureTaskTracer(aLock)) {
- aWriter.StartObjectProperty("tasktracer");
- StreamTaskTracer(aLock, aWriter);
- aWriter.EndObject();
+ const PS::ThreadVector& threads = gPS->Threads(aLock);
+ for (size_t i = 0; i < threads.size(); i++) {
+ // Thread not being profiled, skip it
+ ThreadInfo* info = threads.at(i);
+ if (!info->HasProfile()) {
+ continue;
+ }
+
+ // Note that we intentionally include thread profiles which
+ // have been marked for pending delete.
+
+ info->StreamJSON(gPS->Buffer(aLock), aWriter, gPS->StartTime(aLock),
+ aSinceTime);
+ }
}
- // Lists the samples for each thread profile
- aWriter.StartArrayProperty("threads");
- {
- gPS->SetIsPaused(aLock, true);
-
- {
- const PS::ThreadVector& threads = gPS->Threads(aLock);
- for (size_t i = 0; i < threads.size(); i++) {
- // Thread not being profiled, skip it
- ThreadInfo* info = threads.at(i);
- if (!info->HasProfile()) {
- continue;
- }
-
- // Note that we intentionally include thread profiles which
- // have been marked for pending delete.
-
- info->StreamJSON(gPS->Buffer(aLock), aWriter, gPS->StartTime(aLock),
- aSinceTime);
- }
- }
-
#if defined(PROFILE_JAVA)
- if (gPS->FeatureJava(aLock)) {
- java::GeckoJavaSampler::Pause();
-
- aWriter.Start();
- {
- BuildJavaThreadJSObject(aWriter);
- }
- aWriter.End();
-
- java::GeckoJavaSampler::Unpause();
+ if (gPS->FeatureJava(aLock)) {
+ java::GeckoJavaSampler::Pause();
+
+ aWriter.Start();
+ {
+ BuildJavaThreadJSObject(aWriter);
}
-#endif
-
- gPS->SetIsPaused(aLock, false);
+ aWriter.End();
+
+ java::GeckoJavaSampler::Unpause();
}
- aWriter.EndArray();
-
- aWriter.StartArrayProperty("processes");
- // When notifying observers in other places in this file we are careful
- // to do it when gPSMutex is unlocked, to avoid deadlocks. But that's not
- // necessary here, because "profiler-subprocess" observers just call back
- // into SubprocessCallback, which is simple and doesn't lock gPSMutex.
- if (CanNotifyObservers()) {
- // Send a event asking any subprocesses (plugins) to
- // give us their information
- SubprocessClosure closure(&aWriter);
- nsCOMPtr<nsIObserverService> os =
- mozilla::services::GetObserverService();
- if (os) {
- RefPtr<ProfileSaveEvent> pse =
- new ProfileSaveEvent(SubProcessCallback, &closure);
- os->NotifyObservers(pse, "profiler-subprocess", nullptr);
- }
- }
- aWriter.EndArray();
+#endif
+
+ gPS->SetIsPaused(aLock, false);
}
- aWriter.End();
+ aWriter.EndArray();
}
// END saving/streaming code
////////////////////////////////////////////////////////////////////////
ProfilerMarker::ProfilerMarker(const char* aMarkerName,
ProfilerMarkerPayload* aPayload,
double aTime)
@@ -2123,17 +2100,41 @@ profiler_get_profile(double aSinceTime)
PS::AutoLock lock(gPSMutex);
if (!gPS->IsActive(lock)) {
return nullptr;
}
SpliceableChunkedJSONWriter b;
- StreamJSON(lock, b, aSinceTime);
+ b.Start(SpliceableJSONWriter::SingleLineStyle);
+ {
+ locked_profiler_stream_json_for_this_process(lock, b, aSinceTime);
+
+ b.StartArrayProperty("processes");
+ // When notifying observers in other places in this file we are careful
+ // to do it when gPSMutex is unlocked, to avoid deadlocks. But that's not
+ // necessary here, because "profiler-subprocess" observers just call back
+ // into SubprocessCallback, which is simple and doesn't lock gPSMutex.
+ if (CanNotifyObservers()) {
+ // Send a event asking any subprocesses (plugins) to
+ // give us their information
+ SubprocessClosure closure(&b);
+ nsCOMPtr<nsIObserverService> os =
+ mozilla::services::GetObserverService();
+ if (os) {
+ RefPtr<ProfileSaveEvent> pse =
+ new ProfileSaveEvent(SubProcessCallback, &closure);
+ os->NotifyObservers(pse, "profiler-subprocess", nullptr);
+ }
+ }
+ b.EndArray();
+ }
+ b.End();
+
return b.WriteFunc()->CopyData();
}
void
profiler_get_start_params(int* aEntries, double* aInterval,
mozilla::Vector<const char*>* aFeatures,
mozilla::Vector<const char*>* aFilters)
{
@@ -2170,17 +2171,27 @@ locked_profiler_save_profile_to_file(PS:
MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(gPS && gPS->IsActive(aLock));
std::ofstream stream;
stream.open(aFilename);
if (stream.is_open()) {
SpliceableJSONWriter w(mozilla::MakeUnique<OStreamJSONWriteFunc>(stream));
- StreamJSON(aLock, w, /* sinceTime */ 0);
+ w.Start(SpliceableJSONWriter::SingleLineStyle);
+ {
+ locked_profiler_stream_json_for_this_process(aLock, w, /* sinceTime */ 0);
+
+ // Don't include profiles from other processes because this is a
+ // synchronous function.
+ w.StartArrayProperty("processes");
+ w.EndArray();
+ }
+ w.End();
+
stream.close();
}
}
void
profiler_save_profile_to_file(const char* aFilename)
{
LOG("profiler_save_profile_to_file(%s)", aFilename);