diff options
Diffstat (limited to 'mozglue/baseprofiler')
3 files changed, 162 insertions, 28 deletions
diff --git a/mozglue/baseprofiler/build/profiling_categories.yaml b/mozglue/baseprofiler/build/profiling_categories.yaml index 602974db68..0529d7a55d 100644 --- a/mozglue/baseprofiler/build/profiling_categories.yaml +++ b/mozglue/baseprofiler/build/profiling_categories.yaml @@ -139,8 +139,12 @@ label: JIT (ion) - name: JS_Builtin label: Builtin API - - name: JS_Wasm - label: Wasm + - name: JS_WasmIon + label: Wasm (ion) + - name: JS_WasmBaseline + label: Wasm (baseline) + - name: JS_WasmOther + label: Wasm (other) - name: GCCC label: GC / CC diff --git a/mozglue/baseprofiler/public/BaseProfilerMarkers.h b/mozglue/baseprofiler/public/BaseProfilerMarkers.h index d706cefd4a..6d0b4e74e7 100644 --- a/mozglue/baseprofiler/public/BaseProfilerMarkers.h +++ b/mozglue/baseprofiler/public/BaseProfilerMarkers.h @@ -138,45 +138,54 @@ inline ProfileBufferBlockIndex AddMarker(const ProfilerString8View& aName, namespace mozilla::baseprofiler::markers { // Most common marker type. Others are in BaseProfilerMarkerTypes.h. -struct TextMarker { - static constexpr Span<const char> MarkerTypeName() { - return MakeStringSpan("Text"); - } +struct TextMarker : public BaseMarkerType<TextMarker> { + static constexpr const char* Name = "Text"; + static constexpr const char* Description = "Generic text marker"; + + static constexpr bool StoreName = true; + + using MS = MarkerSchema; + static constexpr MS::PayloadField PayloadFields[] = + // XXX - This is confusingly labeled 'name'. We probably want to fix that. + {{"name", MS::InputType::CString, "Details", MS::Format::String, + MS::PayloadFlags::Searchable}}; + + static constexpr MS::Location Locations[] = {MS::Location::MarkerChart, + MS::Location::MarkerTable}; + + static constexpr const char* ChartLabel = "{marker.data.name}"; + static constexpr const char* TableLabel = + "{marker.name} - {marker.data.name}"; + static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter, const ProfilerString8View& aText) { aWriter.StringProperty("name", aText); } - static MarkerSchema MarkerTypeDisplay() { - using MS = MarkerSchema; - MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; - schema.SetChartLabel("{marker.data.name}"); - schema.SetTableLabel("{marker.name} - {marker.data.name}"); - schema.AddKeyLabelFormatSearchable("name", "Details", MS::Format::String, - MS::Searchable::Searchable); - return schema; - } }; // Keep this struct in sync with the `gecko_profiler::marker::Tracing` Rust // counterpart. -struct Tracing { - static constexpr Span<const char> MarkerTypeName() { - return MakeStringSpan("tracing"); - } +struct Tracing : public BaseMarkerType<Tracing> { + static constexpr const char* Name = "tracing"; + static constexpr const char* Description = "Generic tracing marker"; + + static constexpr bool StoreName = true; + + using MS = MarkerSchema; + static constexpr MS::PayloadField PayloadFields[] = { + {"category", MS::InputType::CString, "Type", MS::Format::String, + MS::PayloadFlags::Searchable}}; + + static constexpr MS::Location Locations[] = {MS::Location::MarkerChart, + MS::Location::MarkerTable, + MS::Location::TimelineOverview}; + static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter, const ProfilerString8View& aCategory) { if (aCategory.Length() != 0) { aWriter.StringProperty("category", aCategory); } } - static MarkerSchema MarkerTypeDisplay() { - using MS = MarkerSchema; - MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable, - MS::Location::TimelineOverview}; - schema.AddKeyLabelFormatSearchable("category", "Type", MS::Format::String, - MS::Searchable::Searchable); - return schema; - } }; } // namespace mozilla::baseprofiler::markers diff --git a/mozglue/baseprofiler/public/BaseProfilerMarkersPrerequisites.h b/mozglue/baseprofiler/public/BaseProfilerMarkersPrerequisites.h index 729e17ab0b..c1de8955a7 100644 --- a/mozglue/baseprofiler/public/BaseProfilerMarkersPrerequisites.h +++ b/mozglue/baseprofiler/public/BaseProfilerMarkersPrerequisites.h @@ -352,6 +352,13 @@ class MarkerTiming { [[nodiscard]] const TimeStamp& StartTime() const { return mStartTime; } [[nodiscard]] const TimeStamp& EndTime() const { return mEndTime; } + // The phase differentiates Instant markers from Interval markers. + // Interval markers can either carry both timestamps on a single marker, + // or they can be split into individual Start and End markers, which are + // associated with each other via the marker name. + // + // The numeric representation of this enum value is also exposed in the + // ETW trace event's Phase field. enum class Phase : uint8_t { Instant = 0, Interval = 1, @@ -691,6 +698,7 @@ class MarkerSchema { enum class InputType { Uint64, Uint32, + Uint8, Boolean, CString, String, @@ -776,7 +784,9 @@ class MarkerSchema { Generic = 1, UserMarkers = 1 << 1, Memory = 1 << 2, - Scheduling = 1 << 3 + Scheduling = 1 << 3, + Text = 1 << 4, + Tracing = 1 << 5 }; // Flags which describe additional information for a PayloadField. @@ -963,6 +973,117 @@ class MarkerSchema { std::vector<GraphData> mGraphs; }; +namespace detail { +// GCC doesn't allow this to live inside the class. +template <typename PayloadType> +static void StreamPayload(baseprofiler::SpliceableJSONWriter& aWriter, + const Span<const char> aKey, + const PayloadType& aPayload) { + aWriter.StringProperty(aKey, aPayload); +} + +template <typename PayloadType> +inline void StreamPayload(baseprofiler::SpliceableJSONWriter& aWriter, + const Span<const char> aKey, + const Maybe<PayloadType>& aPayload) { + if (aPayload.isSome()) { + StreamPayload(aWriter, aKey, *aPayload); + } else { + aWriter.NullProperty(aKey); + } +} + +template <> +inline void StreamPayload<bool>(baseprofiler::SpliceableJSONWriter& aWriter, + const Span<const char> aKey, + const bool& aPayload) { + aWriter.BoolProperty(aKey, aPayload); +} + +template <> +inline void StreamPayload<ProfilerString8View>( + baseprofiler::SpliceableJSONWriter& aWriter, const Span<const char> aKey, + const ProfilerString8View& aPayload) { + aWriter.StringProperty(aKey, aPayload); +} +} // namespace detail + +// This helper class is used by MarkerTypes that want to support the general +// MarkerType object schema. When using this the markers will also transmit +// their payload to the ETW tracer as well as requiring less inline code. +// This is a curiously recurring template, the template argument is the child +// class itself. +template <typename T> +struct BaseMarkerType { + static constexpr const char* AllLabels = nullptr; + static constexpr const char* ChartLabel = nullptr; + static constexpr const char* TableLabel = nullptr; + static constexpr const char* TooltipLabel = nullptr; + + // This indicates whether this marker type wants the names passed to the + // individual marker calls stores along with the marker. + static constexpr bool StoreName = false; + + static constexpr MarkerSchema::ETWMarkerGroup Group = + MarkerSchema::ETWMarkerGroup::Generic; + + static MarkerSchema MarkerTypeDisplay() { + using MS = MarkerSchema; + MS schema{T::Locations, std::size(T::Locations)}; + if (T::AllLabels) { + schema.SetAllLabels(T::AllLabels); + } + if (T::ChartLabel) { + schema.SetChartLabel(T::ChartLabel); + } + if (T::TableLabel) { + schema.SetTableLabel(T::TableLabel); + } + if (T::TooltipLabel) { + schema.SetTooltipLabel(T::TooltipLabel); + } + for (const MS::PayloadField field : T::PayloadFields) { + if (field.Label) { + if (uint32_t(field.Flags) & uint32_t(MS::PayloadFlags::Searchable)) { + schema.AddKeyLabelFormatSearchable(field.Key, field.Label, field.Fmt, + MS::Searchable::Searchable); + } else { + schema.AddKeyLabelFormat(field.Key, field.Label, field.Fmt); + } + } else { + if (uint32_t(field.Flags) & uint32_t(MS::PayloadFlags::Searchable)) { + schema.AddKeyFormatSearchable(field.Key, field.Fmt, + MS::Searchable::Searchable); + } else { + schema.AddKeyFormat(field.Key, field.Fmt); + } + } + } + if (T::Description) { + schema.AddStaticLabelValue("Description", T::Description); + } + return schema; + } + + static constexpr Span<const char> MarkerTypeName() { + return MakeStringSpan(T::Name); + } + + // This is called by the child class since the child class version of this + // function is used to infer the argument types by the profile buffer and + // allows the child to do any special data conversion it needs to do. + // Optionally the child can opt not to use this at all and write the data + // out itself. + template <typename... PayloadArguments> + static void StreamJSONMarkerDataImpl( + baseprofiler::SpliceableJSONWriter& aWriter, + const PayloadArguments&... aPayloadArguments) { + size_t i = 0; + (detail::StreamPayload(aWriter, MakeStringSpan(T::PayloadFields[i++].Key), + aPayloadArguments), + ...); + } +}; } // namespace mozilla #endif // BaseProfilerMarkersPrerequisites_h |