commit be499e88c865f308755b115ee8265126a7866b22
parent 7dae6c49915a5eccb3c29b13238ccba445a916c9
Author: Nazım Can Altınova <canaltinova@gmail.com>
Date: Tue, 21 Oct 2025 21:15:33 +0000
Bug 1979114 - Propagate the profile generation information for child processes instead of duplicating them r=mstange,profiler-reviewers
Previously, we were generating the SharedLibraries inside the
profiler_get_profile_json and then we were trying to generate it again
inside the caller instead of using the Result value from it. Now, this
patch changes this to use the additional information we generate inside
the caller instead of generating it multiple times.
That way:
1. We don't generate the same information multiple times.
2. The information that we generated in the profiler calls inside
platform.cpp file is not going to be lost.
Differential Revision: https://phabricator.services.mozilla.com/D259262
Diffstat:
5 files changed, 59 insertions(+), 50 deletions(-)
diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp
@@ -6252,37 +6252,42 @@ void profiler_shutdown(IsFastShutdown aIsFastShutdown) {
ThreadRegistration::UnregisterThread();
}
-static bool WriteProfileToJSONWriter(SpliceableChunkedJSONWriter& aWriter,
- double aSinceTime, bool aIsShuttingDown,
- ProfilerCodeAddressService* aService,
- mozilla::ProgressLogger aProgressLogger) {
+static ProfilerResult<ProfileGenerationAdditionalInformation>
+WriteProfileToJSONWriter(SpliceableChunkedJSONWriter& aWriter,
+ double aSinceTime, bool aIsShuttingDown,
+ ProfilerCodeAddressService* aService,
+ mozilla::ProgressLogger aProgressLogger) {
LOG("WriteProfileToJSONWriter");
MOZ_RELEASE_ASSERT(CorePS::Exists());
aWriter.Start();
- {
- auto rv = profiler_stream_json_for_this_process(
- aWriter, aSinceTime, aIsShuttingDown, aService,
- aProgressLogger.CreateSubLoggerFromTo(
- 0_pc,
- "WriteProfileToJSONWriter: "
- "profiler_stream_json_for_this_process started",
- 100_pc,
- "WriteProfileToJSONWriter: "
- "profiler_stream_json_for_this_process done"));
-
- if (rv.isErr()) {
- return false;
- }
+ auto rv = profiler_stream_json_for_this_process(
+ aWriter, aSinceTime, aIsShuttingDown, aService,
+ aProgressLogger.CreateSubLoggerFromTo(
+ 0_pc,
+ "WriteProfileToJSONWriter: "
+ "profiler_stream_json_for_this_process started",
+ 100_pc,
+ "WriteProfileToJSONWriter: "
+ "profiler_stream_json_for_this_process done"));
- // Don't include profiles from other processes because this is a
- // synchronous function.
- aWriter.StartArrayProperty("processes");
- aWriter.EndArray();
+ if (rv.isErr()) {
+ return rv;
}
+
+ // Don't include profiles from other processes because this is a
+ // synchronous function.
+ aWriter.StartArrayProperty("processes");
+ aWriter.EndArray();
+
aWriter.End();
- return !aWriter.Failed();
+
+ if (aWriter.Failed()) {
+ return Err(ProfilerError::JsonGenerationFailed);
+ }
+
+ return rv;
}
void profiler_set_process_name(const nsACString& aProcessName,
@@ -6305,14 +6310,16 @@ UniquePtr<char[]> profiler_get_profile(double aSinceTime,
FailureLatchSource failureLatch;
SpliceableChunkedJSONWriter b{failureLatch};
- if (!WriteProfileToJSONWriter(b, aSinceTime, aIsShuttingDown, service.get(),
- ProgressLogger{})) {
+ if (WriteProfileToJSONWriter(b, aSinceTime, aIsShuttingDown, service.get(),
+ ProgressLogger{})
+ .isErr()) {
return nullptr;
}
return b.ChunkedWriteFunc().CopyData();
}
-[[nodiscard]] bool profiler_get_profile_json(
+[[nodiscard]] ProfilerResult<ProfileGenerationAdditionalInformation>
+profiler_get_profile_json(
SpliceableChunkedJSONWriter& aSpliceableChunkedJSONWriter,
double aSinceTime, bool aIsShuttingDown,
mozilla::ProgressLogger aProgressLogger) {
diff --git a/tools/profiler/core/platform.h b/tools/profiler/core/platform.h
@@ -45,6 +45,7 @@
#include "mozilla/Vector.h"
#include "nsString.h"
#include "SharedLibraries.h"
+#include "ProfileAdditionalInformation.h"
#include <cstddef>
#include <cstdint>
@@ -158,7 +159,8 @@ void profiler_mark_thread_awake();
void profiler_mark_thread_asleep();
-[[nodiscard]] bool profiler_get_profile_json(
+[[nodiscard]] ProfilerResult<mozilla::ProfileGenerationAdditionalInformation>
+profiler_get_profile_json(
SpliceableChunkedJSONWriter& aSpliceableChunkedJSONWriter,
double aSinceTime, bool aIsShuttingDown,
mozilla::ProgressLogger aProgressLogger);
diff --git a/tools/profiler/gecko/ProfilerChild.cpp b/tools/profiler/gecko/ProfilerChild.cpp
@@ -335,13 +335,14 @@ void ProfilerChild::GatherProfileThreadFunction(
auto writer =
MakeUnique<SpliceableChunkedJSONWriter>(parameters->failureLatchSource);
- if (!profiler_get_profile_json(
- *writer,
- /* aSinceTime */ 0,
- /* aIsShuttingDown */ false,
- progressLogger.CreateSubLoggerFromTo(
- 1_pc, "profiler_get_profile_json started", 99_pc,
- "profiler_get_profile_json done"))) {
+ auto rv =
+ profiler_get_profile_json(*writer,
+ /* aSinceTime */ 0,
+ /* aIsShuttingDown */ false,
+ progressLogger.CreateSubLoggerFromTo(
+ 1_pc, "profiler_get_profile_json started",
+ 99_pc, "profiler_get_profile_json done"));
+ if (rv.isErr()) {
// Failed to get a profile, reset the writer pointer, so that we'll send a
// failure message.
writer.reset();
@@ -355,7 +356,7 @@ void ProfilerChild::GatherProfileThreadFunction(
// that it doesn't get marked as 100% done when this off-thread
// function ends.
progressLogger = std::move(progressLogger),
- writer = std::move(writer)]() mutable {
+ writer = std::move(writer), rv = std::move(rv)]() mutable {
// We are now on the ProfilerChild thread, about to send the
// completed profile. Any incoming progress request will now be
// handled after this task ends, so updating the progress is now
@@ -424,12 +425,10 @@ void ProfilerChild::GatherProfileThreadFunction(
}
}
- SharedLibraryInfo sharedLibraryInfo =
- SharedLibraryInfo::GetInfoForSelf();
+ Maybe<ProfileGenerationAdditionalInformation> additionalInfo =
+ rv.isOk() ? Some(rv.unwrap()) : Nothing();
parameters->resolver(IPCProfileAndAdditionalInformation{
- std::move(shmem),
- Some(ProfileGenerationAdditionalInformation{
- std::move(sharedLibraryInfo)})});
+ std::move(shmem), std::move(additionalInfo)});
// Let's join the gather profile thread now since it's done.
// Note that this gets called inside the ProfilerChild thread
// and not inside the gather profile thread itself.
diff --git a/tools/profiler/public/GeckoProfiler.h b/tools/profiler/public/GeckoProfiler.h
@@ -29,9 +29,8 @@
#include "mozilla/ProfilerState.h"
#include "mozilla/ProfilerThreadSleep.h"
#include "mozilla/ProfilerThreadState.h"
+#include "mozilla/ProfilerUtils.h"
#include "mozilla/ProgressLogger.h"
-#include "mozilla/Result.h"
-#include "mozilla/ResultVariant.h"
#ifndef MOZ_GECKO_PROFILER
@@ -136,14 +135,6 @@ class SpliceableJSONWriter;
} // namespace mozilla
class nsIURI;
-enum class ProfilerError {
- IsInactive,
- JsonGenerationFailed,
-};
-
-template <typename T>
-using ProfilerResult = mozilla::Result<T, ProfilerError>;
-
//---------------------------------------------------------------------------
// Give information to the profiler
//---------------------------------------------------------------------------
diff --git a/tools/profiler/public/ProfilerUtils.h b/tools/profiler/public/ProfilerUtils.h
@@ -12,6 +12,16 @@
#include "mozilla/BaseProfilerUtils.h"
+#include "mozilla/ResultVariant.h"
+
+enum class ProfilerError {
+ IsInactive,
+ JsonGenerationFailed,
+};
+
+template <typename T>
+using ProfilerResult = mozilla::Result<T, ProfilerError>;
+
using ProfilerProcessId = mozilla::baseprofiler::BaseProfilerProcessId;
using ProfilerThreadId = mozilla::baseprofiler::BaseProfilerThreadId;