Bug 1882468 - Add BUG_COMPONENT for migrated monorepo files in mobile/android/moz...
[gecko.git] / mozglue / baseprofiler / core / ProfiledThreadData.cpp
blob62cb994ae2e75de901e4a67ee47d0d85fea9ff65
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ProfiledThreadData.h"
9 #include "BaseProfiler.h"
10 #include "ProfileBuffer.h"
12 #include "mozilla/BaseProfileJSONWriter.h"
14 #if defined(GP_OS_darwin)
15 # include <pthread.h>
16 #endif
18 namespace mozilla {
19 namespace baseprofiler {
21 ProfiledThreadData::ProfiledThreadData(ThreadInfo* aThreadInfo)
22 : mThreadInfo(aThreadInfo) {}
24 ProfiledThreadData::~ProfiledThreadData() {}
26 void ProfiledThreadData::StreamJSON(const ProfileBuffer& aBuffer,
27 SpliceableJSONWriter& aWriter,
28 const std::string& aProcessName,
29 const std::string& aETLDplus1,
30 const TimeStamp& aProcessStartTime,
31 double aSinceTime) {
32 UniqueStacks uniqueStacks;
34 aWriter.SetUniqueStrings(uniqueStacks.UniqueStrings());
36 aWriter.Start();
38 StreamSamplesAndMarkers(mThreadInfo->Name(), mThreadInfo->ThreadId(),
39 aBuffer, aWriter, aProcessName, aETLDplus1,
40 aProcessStartTime, mThreadInfo->RegisterTime(),
41 mUnregisterTime, aSinceTime, uniqueStacks);
43 aWriter.StartObjectProperty("stackTable");
46 JSONSchemaWriter schema(aWriter);
47 schema.WriteField("prefix");
48 schema.WriteField("frame");
51 aWriter.StartArrayProperty("data");
52 { uniqueStacks.SpliceStackTableElements(aWriter); }
53 aWriter.EndArray();
55 aWriter.EndObject();
57 aWriter.StartObjectProperty("frameTable");
60 JSONSchemaWriter schema(aWriter);
61 schema.WriteField("location");
62 schema.WriteField("relevantForJS");
63 schema.WriteField("innerWindowID");
64 schema.WriteField("implementation");
65 schema.WriteField("line");
66 schema.WriteField("column");
67 schema.WriteField("category");
68 schema.WriteField("subcategory");
71 aWriter.StartArrayProperty("data");
72 { uniqueStacks.SpliceFrameTableElements(aWriter); }
73 aWriter.EndArray();
75 aWriter.EndObject();
77 aWriter.StartArrayProperty("stringTable");
79 std::move(uniqueStacks.UniqueStrings())
80 .SpliceStringTableElements(aWriter);
82 aWriter.EndArray();
84 aWriter.End();
86 aWriter.ResetUniqueStrings();
89 BaseProfilerThreadId StreamSamplesAndMarkers(
90 const char* aName, BaseProfilerThreadId aThreadId,
91 const ProfileBuffer& aBuffer, SpliceableJSONWriter& aWriter,
92 const std::string& aProcessName, const std::string& aETLDplus1,
93 const TimeStamp& aProcessStartTime, const TimeStamp& aRegisterTime,
94 const TimeStamp& aUnregisterTime, double aSinceTime,
95 UniqueStacks& aUniqueStacks) {
96 BaseProfilerThreadId processedThreadId;
98 aWriter.StringProperty(
99 "processType",
100 "(unknown)" /* XRE_GeckoProcessTypeToString(XRE_GetProcessType()) */);
103 std::string name = aName;
104 // We currently need to distinguish threads output by Base Profiler from
105 // those in Gecko Profiler, as the frontend could get confused and lose
106 // tracks with the same name.
107 // TODO: As part of the profilers de-duplication, thread data from both
108 // profilers should end up in the same track, at which point this won't be
109 // necessary anymore. See meta bug 1557566.
110 name += " (pre-xul)";
111 aWriter.StringProperty("name", name);
114 // Use given process name (if any).
115 if (!aProcessName.empty()) {
116 aWriter.StringProperty("processName", aProcessName);
118 if (!aETLDplus1.empty()) {
119 aWriter.StringProperty("eTLD+1", aETLDplus1);
122 if (aRegisterTime) {
123 aWriter.DoubleProperty(
124 "registerTime", (aRegisterTime - aProcessStartTime).ToMilliseconds());
125 } else {
126 aWriter.NullProperty("registerTime");
129 if (aUnregisterTime) {
130 aWriter.DoubleProperty(
131 "unregisterTime",
132 (aUnregisterTime - aProcessStartTime).ToMilliseconds());
133 } else {
134 aWriter.NullProperty("unregisterTime");
137 aWriter.StartObjectProperty("samples");
140 JSONSchemaWriter schema(aWriter);
141 schema.WriteField("stack");
142 schema.WriteField("time");
143 schema.WriteField("eventDelay");
146 aWriter.StartArrayProperty("data");
148 processedThreadId = aBuffer.StreamSamplesToJSON(
149 aWriter, aThreadId, aSinceTime, aUniqueStacks);
151 aWriter.EndArray();
153 aWriter.EndObject();
155 aWriter.StartObjectProperty("markers");
158 JSONSchemaWriter schema(aWriter);
159 schema.WriteField("name");
160 schema.WriteField("startTime");
161 schema.WriteField("endTime");
162 schema.WriteField("phase");
163 schema.WriteField("category");
164 schema.WriteField("data");
167 aWriter.StartArrayProperty("data");
169 aBuffer.StreamMarkersToJSON(aWriter, aThreadId, aProcessStartTime,
170 aSinceTime, aUniqueStacks);
172 aWriter.EndArray();
174 aWriter.EndObject();
176 // Tech note: If `ToNumber()` returns a uint64_t, the conversion to int64_t is
177 // "implementation-defined" before C++20. This is acceptable here, because
178 // this is a one-way conversion to a unique identifier that's used to visually
179 // separate data by thread on the front-end.
180 aWriter.IntProperty(
181 "pid", static_cast<int64_t>(profiler_current_process_id().ToNumber()));
182 aWriter.IntProperty("tid",
183 static_cast<int64_t>(aThreadId.IsSpecified()
184 ? aThreadId.ToNumber()
185 : processedThreadId.ToNumber()));
187 return processedThreadId;
190 } // namespace baseprofiler
191 } // namespace mozilla