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
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"
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
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
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()) {
103 return ::mozilla::baseprofiler::AddMarkerToBuffer(
104 coreBuffer
, aName
, aCategory
, std::move(aOptions
), aMarkerType
,
105 aPayloadArguments
...);
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, ...) \
122 AUTO_PROFILER_STATS(BASE_PROFILER_MARKER_UNTYPED); \
123 ::mozilla::baseprofiler::AddMarker( \
124 markerName, ::mozilla::baseprofiler::category::categoryName, \
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, \
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__); \
139 namespace mozilla::baseprofiler::markers
{
140 // Most common marker type. Others are in BaseProfilerMarkerTypes.h.
142 static constexpr Span
<const char> MarkerTypeName() {
143 return MakeStringSpan("Text");
145 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter
& aWriter
,
146 const ProfilerString8View
& aText
) {
147 aWriter
.StringProperty("name", aText
);
149 static MarkerSchema
MarkerTypeDisplay() {
150 using MS
= MarkerSchema
;
151 MS schema
{MS::Location::MarkerChart
, MS::Location::MarkerTable
};
152 schema
.SetChartLabel("{marker.data.name}");
153 schema
.SetTableLabel("{marker.name} - {marker.data.name}");
154 schema
.AddKeyLabelFormatSearchable("name", "Details", MS::Format::String
,
155 MS::Searchable::Searchable
);
160 // Keep this struct in sync with the `gecko_profiler::marker::Tracing` Rust
163 static constexpr Span
<const char> MarkerTypeName() {
164 return MakeStringSpan("tracing");
166 static void StreamJSONMarkerData(SpliceableJSONWriter
& aWriter
,
167 const ProfilerString8View
& aCategory
) {
168 if (aCategory
.Length() != 0) {
169 aWriter
.StringProperty("category", aCategory
);
172 static MarkerSchema
MarkerTypeDisplay() {
173 using MS
= MarkerSchema
;
174 MS schema
{MS::Location::MarkerChart
, MS::Location::MarkerTable
,
175 MS::Location::TimelineOverview
};
176 schema
.AddKeyLabelFormatSearchable("category", "Type", MS::Format::String
,
177 MS::Searchable::Searchable
);
181 } // namespace mozilla::baseprofiler::markers
183 // Add a text marker. This macro is safe to use even if MOZ_GECKO_PROFILER is
185 #define BASE_PROFILER_MARKER_TEXT(markerName, categoryName, options, text) \
187 AUTO_PROFILER_STATS(BASE_PROFILER_MARKER_TEXT); \
188 ::mozilla::baseprofiler::AddMarker( \
189 markerName, ::mozilla::baseprofiler::category::categoryName, options, \
190 ::mozilla::baseprofiler::markers::TextMarker{}, text); \
193 namespace mozilla::baseprofiler
{
195 // RAII object that adds a BASE_PROFILER_MARKER_TEXT when destroyed; the
196 // marker's timing will be the interval from construction (unless an instant or
197 // start time is already specified in the provided options) until destruction.
198 class MOZ_RAII AutoProfilerTextMarker
{
200 AutoProfilerTextMarker(const char* aMarkerName
,
201 const MarkerCategory
& aCategory
,
202 MarkerOptions
&& aOptions
, const std::string
& aText
)
203 : mMarkerName(aMarkerName
),
204 mCategory(aCategory
),
205 mOptions(std::move(aOptions
)),
207 MOZ_ASSERT(mOptions
.Timing().EndTime().IsNull(),
208 "AutoProfilerTextMarker options shouldn't have an end time");
209 if (profiler_is_active_and_unpaused() &&
210 mOptions
.Timing().StartTime().IsNull()) {
211 mOptions
.Set(MarkerTiming::InstantNow());
215 ~AutoProfilerTextMarker() {
216 if (profiler_is_active_and_unpaused()) {
217 mOptions
.TimingRef().SetIntervalEnd();
218 AUTO_PROFILER_STATS(AUTO_BASE_PROFILER_MARKER_TEXT
);
219 AddMarker(ProfilerString8View::WrapNullTerminatedString(mMarkerName
),
220 mCategory
, std::move(mOptions
), markers::TextMarker
{}, mText
);
225 const char* mMarkerName
;
226 MarkerCategory mCategory
;
227 MarkerOptions mOptions
;
231 #ifdef MOZ_GECKO_PROFILER
232 extern template MFBT_API ProfileBufferBlockIndex
233 AddMarker(const ProfilerString8View
&, const MarkerCategory
&, MarkerOptions
&&,
234 markers::TextMarker
, const std::string
&);
236 extern template MFBT_API ProfileBufferBlockIndex
237 AddMarkerToBuffer(ProfileChunkedBuffer
&, const ProfilerString8View
&,
238 const MarkerCategory
&, MarkerOptions
&&, markers::NoPayload
);
240 extern template MFBT_API ProfileBufferBlockIndex
AddMarkerToBuffer(
241 ProfileChunkedBuffer
&, const ProfilerString8View
&, const MarkerCategory
&,
242 MarkerOptions
&&, markers::TextMarker
, const std::string
&);
243 #endif // MOZ_GECKO_PROFILER
245 } // namespace mozilla::baseprofiler
247 // Creates an AutoProfilerTextMarker RAII object. This macro is safe to use
248 // even if MOZ_GECKO_PROFILER is not #defined.
249 #define AUTO_BASE_PROFILER_MARKER_TEXT(markerName, categoryName, options, \
251 ::mozilla::baseprofiler::AutoProfilerTextMarker PROFILER_RAII( \
252 markerName, ::mozilla::baseprofiler::category::categoryName, options, \
255 #endif // BaseProfilerMarkers_h