/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // Markers are useful to delimit something important happening such as the first // paint. Unlike labels, which are only recorded in the profile buffer if a // sample is collected while the label is on the label stack, markers will // always be recorded in the profile buffer. // // This header contains definitions necessary to add markers to the Gecko // Profiler buffer. // // It #include's "mozilla/BaseProfilerMarkers.h", see that header for base // definitions necessary to create marker types. // // If common marker types are needed, #include "ProfilerMarkerTypes.h" instead. // // But if you want to create your own marker type locally, you can #include this // header only; look at ProfilerMarkerTypes.h for examples of how to define // types. // // To then record markers: // - Use `baseprofiler::AddMarker(...)` from mozglue or other libraries that are // outside of xul, especially if they may happen outside of xpcom's lifetime // (typically startup, shutdown, or tests). // - Otherwise #include "ProfilerMarkers.h" instead, and use // `profiler_add_marker(...)`. // See these functions for more details. #ifndef ProfilerMarkers_h #define ProfilerMarkers_h #include "mozilla/BaseProfilerMarkers.h" #include "mozilla/ProfilerMarkersDetail.h" #ifndef MOZ_GECKO_PROFILER # define PROFILER_MARKER_UNTYPED(markerName, categoryName, ...) # define PROFILER_MARKER(markerName, categoryName, options, MarkerType, ...) # define PROFILER_MARKER_TEXT(markerName, categoryName, options, text) # define AUTO_PROFILER_MARKER_TEXT(markerName, categoryName, options, text) # define AUTO_PROFILER_TRACING_MARKER(categoryString, markerName, categoryPair) # define AUTO_PROFILER_TRACING_MARKER_DOCSHELL(categoryString, markerName, \ categoryPair, docShell) #else // ndef MOZ_GECKO_PROFILER namespace mozilla { class ProfileChunkedBuffer; } bool profiler_can_accept_markers(); bool profiler_capture_backtrace_into( mozilla::ProfileChunkedBuffer& aChunkedBuffer); // Bring category names from Base Profiler into the geckoprofiler::category // namespace, for consistency with other Gecko Profiler identifiers. namespace geckoprofiler::category { using namespace ::mozilla::baseprofiler::category; } // Add a marker to a given buffer. `AddMarker()` and related macros should be // used in most cases, see below for more information about them and the // paramters; This function may be useful when markers need to be recorded in a // local buffer outside of the main profiler buffer. template mozilla::ProfileBufferBlockIndex AddMarkerToBuffer( mozilla::ProfileChunkedBuffer& aBuffer, const mozilla::ProfilerString8View& aName, const mozilla::MarkerCategory& aCategory, mozilla::MarkerOptions&& aOptions, MarkerType aMarkerType, const PayloadArguments&... aPayloadArguments) { mozilla::Unused << aMarkerType; // Only the empty object type is useful. return mozilla::base_profiler_markers_detail::AddMarkerToBuffer( aBuffer, aName, aCategory, std::move(aOptions), ::profiler_capture_backtrace_into, aPayloadArguments...); } // Add a marker (without payload) to a given buffer. inline mozilla::ProfileBufferBlockIndex AddMarkerToBuffer( mozilla::ProfileChunkedBuffer& aBuffer, const mozilla::ProfilerString8View& aName, const mozilla::MarkerCategory& aCategory, mozilla::MarkerOptions&& aOptions = {}) { return AddMarkerToBuffer(aBuffer, aName, aCategory, std::move(aOptions), mozilla::baseprofiler::markers::NoPayload{}); } // Add a marker to the Gecko Profiler buffer. // - aName: Main name of this marker. // - aCategory: Category for this marker. // - aOptions: Optional settings (such as timing, inner window id, // backtrace...), see `MarkerOptions` for details. // - aMarkerType: Empty object that specifies the type of marker. // - aPayloadArguments: Arguments expected by this marker type's // ` StreamJSONMarkerData` function. template mozilla::ProfileBufferBlockIndex profiler_add_marker( const mozilla::ProfilerString8View& aName, const mozilla::MarkerCategory& aCategory, mozilla::MarkerOptions&& aOptions, MarkerType aMarkerType, const PayloadArguments&... aPayloadArguments) { if (!profiler_can_accept_markers()) { return {}; } return ::AddMarkerToBuffer(profiler_markers_detail::CachedCoreBuffer(), aName, aCategory, std::move(aOptions), aMarkerType, aPayloadArguments...); } // Add a marker (without payload) to the Gecko Profiler buffer. inline mozilla::ProfileBufferBlockIndex profiler_add_marker( const mozilla::ProfilerString8View& aName, const mozilla::MarkerCategory& aCategory, mozilla::MarkerOptions&& aOptions = {}) { return profiler_add_marker(aName, aCategory, std::move(aOptions), mozilla::baseprofiler::markers::NoPayload{}); } // Same as `profiler_add_marker()` (without payload). This macro is safe to use // even if MOZ_GECKO_PROFILER is not #defined. # define PROFILER_MARKER_UNTYPED(markerName, categoryName, ...) \ do { \ AUTO_PROFILER_STATS(PROFILER_MARKER_UNTYPED); \ ::profiler_add_marker( \ markerName, ::geckoprofiler::category::categoryName, ##__VA_ARGS__); \ } while (false) // Same as `profiler_add_marker()` (with payload). This macro is safe to use // even if MOZ_GECKO_PROFILER is not #defined. # define PROFILER_MARKER(markerName, categoryName, options, MarkerType, ...) \ do { \ AUTO_PROFILER_STATS(PROFILER_MARKER_with_##MarkerType); \ ::profiler_add_marker( \ markerName, ::geckoprofiler::category::categoryName, options, \ ::geckoprofiler::markers::MarkerType{}, ##__VA_ARGS__); \ } while (false) namespace geckoprofiler::markers { // Most common marker types. Others are in ProfilerMarkerTypes.h. using TextMarker = ::mozilla::baseprofiler::markers::TextMarker; using Tracing = mozilla::baseprofiler::markers::Tracing; } // namespace geckoprofiler::markers // Add a text marker. This macro is safe to use even if MOZ_GECKO_PROFILER is // not #defined. # define PROFILER_MARKER_TEXT(markerName, categoryName, options, text) \ do { \ AUTO_PROFILER_STATS(PROFILER_MARKER_TEXT); \ ::profiler_add_marker(markerName, \ ::geckoprofiler::category::categoryName, options, \ ::geckoprofiler::markers::TextMarker{}, text); \ } while (false) // RAII object that adds a PROFILER_MARKER_TEXT when destroyed; the marker's // timing will be the interval from construction (unless an instant or start // time is already specified in the provided options) until destruction. class MOZ_RAII AutoProfilerTextMarker { public: AutoProfilerTextMarker(const char* aMarkerName, const mozilla::MarkerCategory& aCategory, mozilla::MarkerOptions&& aOptions, const nsACString& aText) : mMarkerName(aMarkerName), mCategory(aCategory), mOptions(std::move(aOptions)), mText(aText) { MOZ_ASSERT(mOptions.Timing().EndTime().IsNull(), "AutoProfilerTextMarker options shouldn't have an end time"); if (mOptions.Timing().StartTime().IsNull()) { mOptions.Set(mozilla::MarkerTiming::InstantNow()); } } ~AutoProfilerTextMarker() { mOptions.TimingRef().SetIntervalEnd(); AUTO_PROFILER_STATS(AUTO_PROFILER_MARKER_TEXT); profiler_add_marker( mozilla::ProfilerString8View::WrapNullTerminatedString(mMarkerName), mCategory, std::move(mOptions), geckoprofiler::markers::TextMarker{}, mText); } protected: const char* mMarkerName; mozilla::MarkerCategory mCategory; mozilla::MarkerOptions mOptions; nsCString mText; }; // Creates an AutoProfilerTextMarker RAII object. This macro is safe to use // even if MOZ_GECKO_PROFILER is not #defined. # define AUTO_PROFILER_MARKER_TEXT(markerName, categoryName, options, text) \ AutoProfilerTextMarker PROFILER_RAII( \ markerName, ::mozilla::baseprofiler::category::categoryName, options, \ text) class MOZ_RAII AutoProfilerTracing { public: AutoProfilerTracing(const char* aCategoryString, const char* aMarkerName, mozilla::MarkerCategory aCategoryPair, const mozilla::Maybe& aInnerWindowID) : mCategoryString(aCategoryString), mMarkerName(aMarkerName), mCategoryPair(aCategoryPair), mInnerWindowID(aInnerWindowID) { profiler_add_marker( mozilla::ProfilerString8View::WrapNullTerminatedString(mMarkerName), mCategoryPair, {mozilla::MarkerTiming::IntervalStart(), mozilla::MarkerInnerWindowId(mInnerWindowID)}, geckoprofiler::markers::Tracing{}, mozilla::ProfilerString8View::WrapNullTerminatedString( mCategoryString)); } AutoProfilerTracing( const char* aCategoryString, const char* aMarkerName, mozilla::MarkerCategory aCategoryPair, mozilla::UniquePtr aBacktrace, const mozilla::Maybe& aInnerWindowID) : mCategoryString(aCategoryString), mMarkerName(aMarkerName), mCategoryPair(aCategoryPair), mInnerWindowID(aInnerWindowID) { profiler_add_marker( mozilla::ProfilerString8View::WrapNullTerminatedString(mMarkerName), mCategoryPair, {mozilla::MarkerTiming::IntervalStart(), mozilla::MarkerInnerWindowId(mInnerWindowID), mozilla::MarkerStack::TakeBacktrace(std::move(aBacktrace))}, geckoprofiler::markers::Tracing{}, mozilla::ProfilerString8View::WrapNullTerminatedString( mCategoryString)); } ~AutoProfilerTracing() { profiler_add_marker( mozilla::ProfilerString8View::WrapNullTerminatedString(mMarkerName), mCategoryPair, {mozilla::MarkerTiming::IntervalEnd(), mozilla::MarkerInnerWindowId(mInnerWindowID)}, geckoprofiler::markers::Tracing{}, mozilla::ProfilerString8View::WrapNullTerminatedString( mCategoryString)); } protected: const char* mCategoryString; const char* mMarkerName; const mozilla::MarkerCategory mCategoryPair; const mozilla::Maybe mInnerWindowID; }; // Adds a START/END pair of tracing markers. # define AUTO_PROFILER_TRACING_MARKER(categoryString, markerName, \ categoryPair) \ AutoProfilerTracing PROFILER_RAII(categoryString, markerName, \ geckoprofiler::category::categoryPair, \ mozilla::Nothing()) # define AUTO_PROFILER_TRACING_MARKER_DOCSHELL(categoryString, markerName, \ categoryPair, docShell) \ AutoProfilerTracing PROFILER_RAII( \ categoryString, markerName, geckoprofiler::category::categoryPair, \ profiler_get_inner_window_id_from_docshell(docShell)) extern template mozilla::ProfileBufferBlockIndex AddMarkerToBuffer( mozilla::ProfileChunkedBuffer&, const mozilla::ProfilerString8View&, const mozilla::MarkerCategory&, mozilla::MarkerOptions&&, mozilla::baseprofiler::markers::NoPayload); extern template mozilla::ProfileBufferBlockIndex AddMarkerToBuffer( mozilla::ProfileChunkedBuffer&, const mozilla::ProfilerString8View&, const mozilla::MarkerCategory&, mozilla::MarkerOptions&&, mozilla::baseprofiler::markers::TextMarker, const std::string&); extern template mozilla::ProfileBufferBlockIndex profiler_add_marker( const mozilla::ProfilerString8View&, const mozilla::MarkerCategory&, mozilla::MarkerOptions&&, mozilla::baseprofiler::markers::TextMarker, const std::string&); extern template mozilla::ProfileBufferBlockIndex profiler_add_marker( const mozilla::ProfilerString8View&, const mozilla::MarkerCategory&, mozilla::MarkerOptions&&, mozilla::baseprofiler::markers::TextMarker, const nsCString&); extern template mozilla::ProfileBufferBlockIndex profiler_add_marker( const mozilla::ProfilerString8View&, const mozilla::MarkerCategory&, mozilla::MarkerOptions&&, mozilla::baseprofiler::markers::Tracing, const mozilla::ProfilerString8View&); #endif // nfed MOZ_GECKO_PROFILER else #endif // ProfilerMarkers_h