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.
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
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
198 #define BASE_PROFILER_MARKER_TEXT(markerName, categoryName, options, text) \
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); \
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
{
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
)),
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
);
238 const char* mMarkerName
;
239 MarkerCategory mCategory
;
240 MarkerOptions mOptions
;
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, \
264 ::mozilla::baseprofiler::AutoProfilerTextMarker PROFILER_RAII( \
265 markerName, ::mozilla::baseprofiler::category::categoryName, options, \
268 #endif // BaseProfilerMarkers_h