Backed out changeset a5ff95602119 (bug 1905021) as requested for causing accessibilit...
[gecko.git] / mozglue / baseprofiler / public / BaseProfilerMarkers.h
blob00ed8c1ed8e80e24e513f64b144b05df1bf4c282
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 // Markers are useful to delimit something important happening such as the first
8 // paint. Unlike labels, which are only recorded in the profile buffer if a
9 // sample is collected while the label is on the label stack, markers will
10 // always be recorded in the profile buffer.
12 // This header contains basic definitions necessary to create marker types, and
13 // to add markers to the profiler buffers.
15 // If basic marker types are needed, #include
16 // "mozilla/BaseProfilerMarkerTypes.h" instead.
18 // But if you want to create your own marker type locally, you can #include this
19 // header only; look at mozilla/BaseProfilerMarkerTypes.h for examples of how to
20 // define types, and mozilla/BaseProfilerMarkerPrerequisites.h for some
21 // supporting types.
23 // To then record markers:
24 // - Use `baseprofiler::AddMarker(...)` from mozglue or other libraries that
25 // are outside of xul, especially if they may happen outside of xpcom's
26 // lifetime (typically startup, shutdown, or tests).
27 // - Otherwise #include "ProfilerMarkers.h" instead, and use
28 // `profiler_add_marker(...)`.
29 // See these functions for more details.
31 #ifndef BaseProfilerMarkers_h
32 #define BaseProfilerMarkers_h
34 #include "mozilla/BaseProfilerMarkersDetail.h"
35 #include "mozilla/BaseProfilerLabels.h"
36 #include "mozilla/TimeStamp.h"
37 #include "mozilla/Unused.h"
39 #include <functional>
40 #include <string>
41 #include <utility>
43 namespace mozilla::baseprofiler {
45 #ifdef MOZ_GECKO_PROFILER
46 // Forward-declaration. TODO: Move to more common header, see bug 1681416.
47 MFBT_API bool profiler_capture_backtrace_into(
48 ProfileChunkedBuffer& aChunkedBuffer, StackCaptureOptions aCaptureOptions);
50 // Add a marker to a given buffer. `AddMarker()` and related macros should be
51 // used in most cases, see below for more information about them and the
52 // parameters; This function may be useful when markers need to be recorded in a
53 // local buffer outside of the main profiler buffer.
54 template <typename MarkerType, typename... PayloadArguments>
55 ProfileBufferBlockIndex AddMarkerToBuffer(
56 ProfileChunkedBuffer& aBuffer, const ProfilerString8View& aName,
57 const MarkerCategory& aCategory, MarkerOptions&& aOptions,
58 MarkerType aMarkerType, const PayloadArguments&... aPayloadArguments) {
59 Unused << aMarkerType; // Only the empty object type is useful.
60 AUTO_BASE_PROFILER_LABEL("baseprofiler::AddMarkerToBuffer", PROFILER);
61 return base_profiler_markers_detail::AddMarkerToBuffer<MarkerType>(
62 aBuffer, aName, aCategory, std::move(aOptions),
63 // Do not capture a stack if the NoMarkerStacks feature is set.
64 profiler_active_without_feature(ProfilerFeature::NoMarkerStacks)
65 ? ::mozilla::baseprofiler::profiler_capture_backtrace_into
66 : nullptr,
67 aPayloadArguments...);
70 // Add a marker (without payload) to a given buffer.
71 inline ProfileBufferBlockIndex AddMarkerToBuffer(
72 ProfileChunkedBuffer& aBuffer, const ProfilerString8View& aName,
73 const MarkerCategory& aCategory, MarkerOptions&& aOptions = {}) {
74 return AddMarkerToBuffer(aBuffer, aName, aCategory, std::move(aOptions),
75 markers::NoPayload{});
77 #endif // MOZ_GECKO_PROFILER
79 // Add a marker to the Base Profiler buffer.
80 // - aName: Main name of this marker.
81 // - aCategory: Category for this marker.
82 // - aOptions: Optional settings (such as timing, inner window id,
83 // backtrace...), see `MarkerOptions` for details.
84 // - aMarkerType: Empty object that specifies the type of marker.
85 // - aPayloadArguments: Arguments expected by this marker type's
86 // ` StreamJSONMarkerData` function.
87 template <typename MarkerType, typename... PayloadArguments>
88 ProfileBufferBlockIndex AddMarker(
89 const ProfilerString8View& aName, const MarkerCategory& aCategory,
90 MarkerOptions&& aOptions, MarkerType aMarkerType,
91 const PayloadArguments&... aPayloadArguments) {
92 #ifndef MOZ_GECKO_PROFILER
93 return {};
94 #else
95 // Record base markers whenever the core buffer is in session.
96 // TODO: When profiler_thread_is_being_profiled becomes available from
97 // mozglue, use it instead.
98 ProfileChunkedBuffer& coreBuffer =
99 ::mozilla::baseprofiler::profiler_get_core_buffer();
100 if (!coreBuffer.IsInSession()) {
101 return {};
103 return ::mozilla::baseprofiler::AddMarkerToBuffer(
104 coreBuffer, aName, aCategory, std::move(aOptions), aMarkerType,
105 aPayloadArguments...);
106 #endif
109 // Add a marker (without payload) to the Base Profiler buffer.
110 inline ProfileBufferBlockIndex AddMarker(const ProfilerString8View& aName,
111 const MarkerCategory& aCategory,
112 MarkerOptions&& aOptions = {}) {
113 return AddMarker(aName, aCategory, std::move(aOptions), markers::NoPayload{});
116 } // namespace mozilla::baseprofiler
118 // Same as `AddMarker()` (without payload). This macro is safe to use even if
119 // MOZ_GECKO_PROFILER is not #defined.
120 #define BASE_PROFILER_MARKER_UNTYPED(markerName, categoryName, ...) \
121 do { \
122 AUTO_PROFILER_STATS(BASE_PROFILER_MARKER_UNTYPED); \
123 ::mozilla::baseprofiler::AddMarker( \
124 markerName, ::mozilla::baseprofiler::category::categoryName, \
125 ##__VA_ARGS__); \
126 } while (false)
128 // Same as `AddMarker()` (with payload). This macro is safe to use even if
129 // MOZ_GECKO_PROFILER is not #defined.
130 #define BASE_PROFILER_MARKER(markerName, categoryName, options, MarkerType, \
131 ...) \
132 do { \
133 AUTO_PROFILER_STATS(BASE_PROFILER_MARKER_with_##MarkerType); \
134 ::mozilla::baseprofiler::AddMarker( \
135 markerName, ::mozilla::baseprofiler::category::categoryName, options, \
136 ::mozilla::baseprofiler::markers::MarkerType{}, ##__VA_ARGS__); \
137 } while (false)
139 namespace mozilla::baseprofiler::markers {
140 // Most common marker type. Others are in BaseProfilerMarkerTypes.h.
141 struct TextMarker : public BaseMarkerType<TextMarker> {
142 static constexpr const char* Name = "Text";
143 // It's not possible to add a single meaningful description to this marker
144 // type since it can be used by various different markers.
145 static constexpr const char* Description = nullptr;
147 static constexpr bool StoreName = true;
149 using MS = MarkerSchema;
150 static constexpr MS::PayloadField PayloadFields[] =
151 // XXX - This is confusingly labeled 'name'. We probably want to fix that.
152 {{"name", MS::InputType::CString, "Details", MS::Format::String,
153 MS::PayloadFlags::Searchable}};
155 static constexpr MS::Location Locations[] = {MS::Location::MarkerChart,
156 MS::Location::MarkerTable};
158 static constexpr const char* ChartLabel = "{marker.data.name}";
159 static constexpr const char* TableLabel =
160 "{marker.name} - {marker.data.name}";
162 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
163 const ProfilerString8View& aText) {
164 aWriter.StringProperty("name", aText);
168 // Keep this struct in sync with the `gecko_profiler::marker::Tracing` Rust
169 // counterpart.
170 struct Tracing : public BaseMarkerType<Tracing> {
171 static constexpr const char* Name = "tracing";
172 // It's not possible to add a single meaningful description to this marker
173 // type since it can be used by various different markers.
174 static constexpr const char* Description = nullptr;
176 static constexpr bool StoreName = true;
178 using MS = MarkerSchema;
179 static constexpr MS::PayloadField PayloadFields[] = {
180 {"category", MS::InputType::CString, "Type", MS::Format::String,
181 MS::PayloadFlags::Searchable}};
183 static constexpr MS::Location Locations[] = {MS::Location::MarkerChart,
184 MS::Location::MarkerTable,
185 MS::Location::TimelineOverview};
187 static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter,
188 const ProfilerString8View& aCategory) {
189 if (aCategory.Length() != 0) {
190 aWriter.StringProperty("category", aCategory);
194 } // namespace mozilla::baseprofiler::markers
196 // Add a text marker. This macro is safe to use even if MOZ_GECKO_PROFILER is
197 // not #defined.
198 #define BASE_PROFILER_MARKER_TEXT(markerName, categoryName, options, text) \
199 do { \
200 AUTO_PROFILER_STATS(BASE_PROFILER_MARKER_TEXT); \
201 ::mozilla::baseprofiler::AddMarker( \
202 markerName, ::mozilla::baseprofiler::category::categoryName, options, \
203 ::mozilla::baseprofiler::markers::TextMarker{}, text); \
204 } while (false)
206 namespace mozilla::baseprofiler {
208 // RAII object that adds a BASE_PROFILER_MARKER_TEXT when destroyed; the
209 // marker's timing will be the interval from construction (unless an instant or
210 // start time is already specified in the provided options) until destruction.
211 class MOZ_RAII AutoProfilerTextMarker {
212 public:
213 AutoProfilerTextMarker(const char* aMarkerName,
214 const MarkerCategory& aCategory,
215 MarkerOptions&& aOptions, const std::string& aText)
216 : mMarkerName(aMarkerName),
217 mCategory(aCategory),
218 mOptions(std::move(aOptions)),
219 mText(aText) {
220 MOZ_ASSERT(mOptions.Timing().EndTime().IsNull(),
221 "AutoProfilerTextMarker options shouldn't have an end time");
222 if (profiler_is_active_and_unpaused() &&
223 mOptions.Timing().StartTime().IsNull()) {
224 mOptions.Set(MarkerTiming::InstantNow());
228 ~AutoProfilerTextMarker() {
229 if (profiler_is_active_and_unpaused()) {
230 mOptions.TimingRef().SetIntervalEnd();
231 AUTO_PROFILER_STATS(AUTO_BASE_PROFILER_MARKER_TEXT);
232 AddMarker(ProfilerString8View::WrapNullTerminatedString(mMarkerName),
233 mCategory, std::move(mOptions), markers::TextMarker{}, mText);
237 protected:
238 const char* mMarkerName;
239 MarkerCategory mCategory;
240 MarkerOptions mOptions;
241 std::string mText;
244 #ifdef MOZ_GECKO_PROFILER
245 extern template MFBT_API ProfileBufferBlockIndex
246 AddMarker(const ProfilerString8View&, const MarkerCategory&, MarkerOptions&&,
247 markers::TextMarker, const std::string&);
249 extern template MFBT_API ProfileBufferBlockIndex
250 AddMarkerToBuffer(ProfileChunkedBuffer&, const ProfilerString8View&,
251 const MarkerCategory&, MarkerOptions&&, markers::NoPayload);
253 extern template MFBT_API ProfileBufferBlockIndex AddMarkerToBuffer(
254 ProfileChunkedBuffer&, const ProfilerString8View&, const MarkerCategory&,
255 MarkerOptions&&, markers::TextMarker, const std::string&);
256 #endif // MOZ_GECKO_PROFILER
258 } // namespace mozilla::baseprofiler
260 // Creates an AutoProfilerTextMarker RAII object. This macro is safe to use
261 // even if MOZ_GECKO_PROFILER is not #defined.
262 #define AUTO_BASE_PROFILER_MARKER_TEXT(markerName, categoryName, options, \
263 text) \
264 ::mozilla::baseprofiler::AutoProfilerTextMarker PROFILER_RAII( \
265 markerName, ::mozilla::baseprofiler::category::categoryName, options, \
266 text)
268 #endif // BaseProfilerMarkers_h