diff options
Diffstat (limited to 'tools/profiler/public')
-rw-r--r-- | tools/profiler/public/ETWTools.h | 207 | ||||
-rw-r--r-- | tools/profiler/public/GeckoProfiler.h | 3 | ||||
-rw-r--r-- | tools/profiler/public/GeckoTraceEvent.h | 13 | ||||
-rw-r--r-- | tools/profiler/public/ProfilerMarkers.h | 108 | ||||
-rw-r--r-- | tools/profiler/public/ProfilerThreadRegistrationInfo.h | 5 |
5 files changed, 137 insertions, 199 deletions
diff --git a/tools/profiler/public/ETWTools.h b/tools/profiler/public/ETWTools.h index a1d986a6fd..cbd73004ba 100644 --- a/tools/profiler/public/ETWTools.h +++ b/tools/profiler/public/ETWTools.h @@ -22,6 +22,8 @@ namespace ETW { extern std::atomic<ULONGLONG> gETWCollectionMask; +constexpr const char* kNameKey = "MarkerName"; + // Forward-declare the g_hMyComponentProvider variable that you will use for // tracing in this component TRACELOGGING_DECLARE_PROVIDER(kFirefoxTraceLoggingProvider); @@ -29,32 +31,46 @@ TRACELOGGING_DECLARE_PROVIDER(kFirefoxTraceLoggingProvider); void Init(); void Shutdown(); +template <typename T, typename = void> +struct MarkerHasPayload : std::false_type {}; +template <typename T> +struct MarkerHasPayload<T, std::void_t<decltype(T::PayloadFields)>> + : std::true_type {}; + // This describes the base fields for all markers (information extracted from // MarkerOptions. struct BaseMarkerDescription { + static constexpr bool StoreName = false; using MS = mozilla::MarkerSchema; static constexpr MS::PayloadField PayloadFields[] = { {"StartTime", MS::InputType::TimeStamp, "Start Time"}, {"EndTime", MS::InputType::TimeStamp, "End Time"}, + {"Phase", MS::InputType::Uint8, "Phase"}, {"InnerWindowId", MS::InputType::Uint64, "Inner Window ID"}, {"CategoryPair", MS::InputType::Uint32, "Category Pair"}}; }; // This is the MarkerType object for markers with no statically declared type, // their name is written dynamically. -struct SimpleMarkerType { +struct SimpleMarkerType : public mozilla::BaseMarkerType<SimpleMarkerType> { using MS = mozilla::MarkerSchema; + static constexpr const char* Name = "SimpleMarker"; - static constexpr MS::PayloadField PayloadFields[] = { - {"MarkerName", MS::InputType::CString, "Simple Marker Name"}}; + static constexpr bool StoreName = true; }; // This gets the space required in the Tlg static struct to pack the fields. template <typename T> constexpr std::size_t GetPackingSpace() { size_t length = 0; - for (size_t i = 0; i < std::size(T::PayloadFields); i++) { - length += std::string_view{T::PayloadFields[i].Key}.size() + 1; + if constexpr (MarkerHasPayload<T>::value) { + for (size_t i = 0; i < std::size(T::PayloadFields); i++) { + length += std::string_view{T::PayloadFields[i].Key}.size() + 1; + length += sizeof(uint8_t); + } + } + if (T::StoreName) { + length += std::string_view{kNameKey}.size() + 1; length += sizeof(uint8_t); } return length; @@ -65,6 +81,7 @@ constexpr uint8_t GetTlgInputType(mozilla::MarkerSchema::InputType aInput) { using InputType = mozilla::MarkerSchema::InputType; switch (aInput) { case InputType::Boolean: + case InputType::Uint8: return TlgInUINT8; case InputType::Uint32: return TlgInUINT32; @@ -121,12 +138,20 @@ struct StaticMetaData { fieldStorage[pos++] = GetTlgInputType(BaseMarkerDescription::PayloadFields[i].InputTy); } - for (uint32_t i = 0; i < std::size(T::PayloadFields); i++) { - for (size_t c = 0; - c < std::string_view{T::PayloadFields[i].Key}.size() + 1; c++) { - fieldStorage[pos++] = T::PayloadFields[i].Key[c]; + if (T::StoreName) { + for (size_t c = 0; c < std::string_view{kNameKey}.size() + 1; c++) { + fieldStorage[pos++] = kNameKey[c]; + } + fieldStorage[pos++] = TlgInANSISTRING; + } + if constexpr (MarkerHasPayload<T>::value) { + for (uint32_t i = 0; i < std::size(T::PayloadFields); i++) { + for (size_t c = 0; + c < std::string_view{T::PayloadFields[i].Key}.size() + 1; c++) { + fieldStorage[pos++] = T::PayloadFields[i].Key[c]; + } + fieldStorage[pos++] = GetTlgInputType(T::PayloadFields[i].InputTy); } - fieldStorage[pos++] = GetTlgInputType(T::PayloadFields[i].InputTy); } } }; @@ -146,10 +171,11 @@ struct PayloadBuffer { // Theoretically we could probably avoid these assignments when passed a POD // variable we know is going to be alive but that would require some more // template magic. + template <typename T> -static void CreateDataDescForPayload(PayloadBuffer& aBuffer, - EVENT_DATA_DESCRIPTOR& aDescriptor, - const T& aPayload) { +void CreateDataDescForPayloadPOD(PayloadBuffer& aBuffer, + EVENT_DATA_DESCRIPTOR& aDescriptor, + const T& aPayload) { static_assert(std::is_pod<T>::value, "Writing a non-POD payload requires template specialization."); @@ -164,16 +190,22 @@ static void CreateDataDescForPayload(PayloadBuffer& aBuffer, EventDataDescCreate(&aDescriptor, storedValue, sizeof(T)); } -template <> -inline void CreateDataDescForPayload<mozilla::ProfilerString8View>( +static inline void CreateDataDescForPayloadNonPOD( PayloadBuffer& aBuffer, EVENT_DATA_DESCRIPTOR& aDescriptor, const mozilla::ProfilerString8View& aPayload) { EventDataDescCreate(&aDescriptor, aPayload.StringView().data(), aPayload.StringView().size() + 1); } -template <> -inline void CreateDataDescForPayload<mozilla::TimeStamp>( +template <typename T> +static inline void CreateDataDescForPayloadNonPOD( + PayloadBuffer& aBuffer, EVENT_DATA_DESCRIPTOR& aDescriptor, + const mozilla::detail::nsTStringRepr<T>& aPayload) { + EventDataDescCreate(&aDescriptor, aPayload.BeginReading(), + (aPayload.Length() + 1) * sizeof(T)); +} + +static inline void CreateDataDescForPayloadNonPOD( PayloadBuffer& aBuffer, EVENT_DATA_DESCRIPTOR& aDescriptor, const mozilla::TimeStamp& aPayload) { if (aPayload.RawQueryPerformanceCounterValue().isNothing()) { @@ -182,32 +214,25 @@ inline void CreateDataDescForPayload<mozilla::TimeStamp>( return; } - CreateDataDescForPayload(aBuffer, aDescriptor, - aPayload.RawQueryPerformanceCounterValue().value()); + CreateDataDescForPayloadPOD( + aBuffer, aDescriptor, aPayload.RawQueryPerformanceCounterValue().value()); } -template <> -inline void CreateDataDescForPayload<mozilla::TimeDuration>( +static inline void CreateDataDescForPayloadNonPOD( PayloadBuffer& aBuffer, EVENT_DATA_DESCRIPTOR& aDescriptor, const mozilla::TimeDuration& aPayload) { - CreateDataDescForPayload(aBuffer, aDescriptor, aPayload.ToMilliseconds()); + CreateDataDescForPayloadPOD(aBuffer, aDescriptor, aPayload.ToMilliseconds()); } -// For reasons that are beyond me if this isn't marked inline it generates an -// unused function warning despite being a template specialization. -template <typename T> -inline void CreateDataDescForPayload(PayloadBuffer& aBuffer, - EVENT_DATA_DESCRIPTOR& aDescriptor, - const nsTString<T>& aPayload) { - EventDataDescCreate(&aDescriptor, aPayload.BeginReading(), - (aPayload.Length() + 1) * sizeof(T)); -} template <typename T> -inline void CreateDataDescForPayload(PayloadBuffer& aBuffer, - EVENT_DATA_DESCRIPTOR& aDescriptor, - const nsTSubstring<T>& aPayload) { - EventDataDescCreate(&aDescriptor, aPayload.BeginReading(), - (aPayload.Length() + 1) * sizeof(T)); +static inline void CreateDataDescForPayload(PayloadBuffer& aBuffer, + EVENT_DATA_DESCRIPTOR& aDescriptor, + const T& aPayload) { + if constexpr (std::is_pod<T>::value) { + CreateDataDescForPayloadPOD(aBuffer, aDescriptor, aPayload); + } else { + CreateDataDescForPayloadNonPOD(aBuffer, aDescriptor, aPayload); + } } // Template specialization that writes out empty data descriptors for an empty @@ -223,11 +248,17 @@ void CreateDataDescForPayload(PayloadBuffer& aBuffer, } } +template <size_t N> +void CreateDataDescForPayload(PayloadBuffer& aBuffer, + EVENT_DATA_DESCRIPTOR& aDescriptor, + const char (&aPayload)[N]) { + EventDataDescCreate(&aDescriptor, aPayload, N + 1); +} + template <typename T, typename = void> struct MarkerSupportsETW : std::false_type {}; template <typename T> -struct MarkerSupportsETW<T, std::void_t<decltype(T::PayloadFields)>> - : std::true_type {}; +struct MarkerSupportsETW<T, std::void_t<decltype(T::Name)>> : std::true_type {}; template <typename T, typename = void> struct MarkerHasTranslator : std::false_type {}; @@ -239,6 +270,7 @@ struct MarkerHasTranslator< struct BaseEventStorage { uint64_t mStartTime; uint64_t mEndTime; + uint8_t mPhase; uint64_t mWindowID; uint32_t mCategoryPair; }; @@ -247,11 +279,16 @@ static inline void StoreBaseEventDataDesc( BaseEventStorage& aStorage, EVENT_DATA_DESCRIPTOR* aDescriptors, const mozilla::MarkerCategory& aCategory, const mozilla::MarkerOptions& aOptions) { - if (!aOptions.IsTimingUnspecified()) { + if (aOptions.IsTimingUnspecified()) { + aStorage.mStartTime = + mozilla::TimeStamp::Now().RawQueryPerformanceCounterValue().value(); + aStorage.mPhase = 0; + } else { aStorage.mStartTime = aOptions.Timing().StartTime().RawQueryPerformanceCounterValue().value(); aStorage.mEndTime = aOptions.Timing().EndTime().RawQueryPerformanceCounterValue().value(); + aStorage.mPhase = uint8_t(aOptions.Timing().MarkerPhase()); } if (!aOptions.InnerWindowId().IsUnspecified()) { aStorage.mWindowID = aOptions.InnerWindowId().Id(); @@ -259,37 +296,22 @@ static inline void StoreBaseEventDataDesc( aStorage.mCategoryPair = uint32_t(aCategory.CategoryPair()); EventDataDescCreate(&aDescriptors[2], &aStorage.mStartTime, sizeof(uint64_t)); EventDataDescCreate(&aDescriptors[3], &aStorage.mEndTime, sizeof(uint64_t)); - EventDataDescCreate(&aDescriptors[4], &aStorage.mWindowID, sizeof(uint64_t)); - EventDataDescCreate(&aDescriptors[5], &aStorage.mCategoryPair, + EventDataDescCreate(&aDescriptors[4], &aStorage.mPhase, sizeof(uint8_t)); + EventDataDescCreate(&aDescriptors[5], &aStorage.mWindowID, sizeof(uint64_t)); + EventDataDescCreate(&aDescriptors[6], &aStorage.mCategoryPair, sizeof(uint32_t)); } -// This is used for markers with no explicit type or markers which have not -// been converted to the updated schema yet. -static inline void EmitETWMarker(const mozilla::ProfilerString8View& aName, - const mozilla::MarkerCategory& aCategory, - const mozilla::MarkerOptions& aOptions = {}) { - if (!(gETWCollectionMask & - uint64_t(mozilla::MarkerSchema::ETWMarkerGroup::Generic))) { - return; +template <typename MarkerType> +constexpr size_t GetETWDescriptorCount() { + size_t count = 2 + std::size(BaseMarkerDescription::PayloadFields); + if (MarkerType::StoreName) { + count++; } - - static const __declspec(allocate(_tlgSegMetadataEvents)) __declspec( - align(1)) constexpr StaticMetaData<SimpleMarkerType> - staticData; - - std::array<EVENT_DATA_DESCRIPTOR, 7> descriptors = {}; - - // This is storage space allocated on the stack for POD values. - BaseEventStorage dataStorage = {}; - - StoreBaseEventDataDesc(dataStorage, descriptors.data(), aCategory, - std::move(aOptions)); - - EventDataDescCreate(&descriptors[6], aName.StringView().data(), - aName.StringView().size() + 1); - _tlgWriteTransfer(kFirefoxTraceLoggingProvider, &staticData.metaData.Channel, - NULL, NULL, descriptors.size(), descriptors.data()); + if constexpr (MarkerHasPayload<MarkerType>::value) { + count += std::size(MarkerType::PayloadFields); + } + return count; } template <typename MarkerType, typename... PayloadArguments> @@ -301,7 +323,7 @@ static inline void EmitETWMarker(const mozilla::ProfilerString8View& aName, // If our MarkerType has not been made to support ETW, emit only the base // event. Avoid attempting to compile the rest of the function. if constexpr (!MarkerSupportsETW<MarkerType>::value) { - return EmitETWMarker(aName, aCategory, aOptions); + return EmitETWMarker(aName, aCategory, aOptions, SimpleMarkerType{}); } else { if (!(gETWCollectionMask & uint64_t(MarkerType::Group))) { return; @@ -312,9 +334,7 @@ static inline void EmitETWMarker(const mozilla::ProfilerString8View& aName, staticData; // Allocate the exact amount of descriptors required by this event. - std::array<EVENT_DATA_DESCRIPTOR, - 2 + std::size(MarkerType::PayloadFields) + - std::size(BaseMarkerDescription::PayloadFields)> + std::array<EVENT_DATA_DESCRIPTOR, GetETWDescriptorCount<MarkerType>()> descriptors = {}; // Memory allocated on the stack for storing intermediate values. @@ -324,23 +344,33 @@ static inline void EmitETWMarker(const mozilla::ProfilerString8View& aName, StoreBaseEventDataDesc(dataStorage, descriptors.data(), aCategory, aOptions); - if constexpr (MarkerHasTranslator<MarkerType>::value) { - // When this function is implemented the arguments are passed back to the - // MarkerType object which is expected to call OutputMarkerSchema with - // the correct argument format. - buffer.mDescriptors = descriptors.data() + 2 + - std::size(BaseMarkerDescription::PayloadFields); - MarkerType::TranslateMarkerInputToSchema(&buffer, aPayloadArguments...); - } else { - const size_t argCount = sizeof...(PayloadArguments); - static_assert( - argCount == std::size(MarkerType::PayloadFields), - "Number and type of fields must be equal to number and type of " - "payload arguments. If this is not the case a " - "TranslateMarkerInputToSchema function must be defined."); - size_t i = 2 + std::size(BaseMarkerDescription::PayloadFields); - (CreateDataDescForPayload(buffer, descriptors[i++], aPayloadArguments), - ...); + if constexpr (MarkerType::StoreName) { + EventDataDescCreate(&descriptors[7], aName.StringView().data(), + aName.StringView().size() + 1); + } + + if constexpr (MarkerHasPayload<MarkerType>::value) { + if constexpr (MarkerHasTranslator<MarkerType>::value) { + // When this function is implemented the arguments are passed back to + // the MarkerType object which is expected to call OutputMarkerSchema + // with the correct argument format. + buffer.mDescriptors = descriptors.data() + 2 + + std::size(BaseMarkerDescription::PayloadFields) + + (MarkerType::StoreName ? 1 : 0); + + MarkerType::TranslateMarkerInputToSchema(&buffer, aPayloadArguments...); + } else { + const size_t argCount = sizeof...(PayloadArguments); + static_assert( + argCount == std::size(MarkerType::PayloadFields), + "Number and type of fields must be equal to number and type of " + "payload arguments. If this is not the case a " + "TranslateMarkerInputToSchema function must be defined."); + size_t i = 2 + std::size(BaseMarkerDescription::PayloadFields) + + (MarkerType::StoreName ? 1 : 0); + (CreateDataDescForPayload(buffer, descriptors[i++], aPayloadArguments), + ...); + } } _tlgWriteTransfer(kFirefoxTraceLoggingProvider, @@ -372,9 +402,6 @@ void OutputMarkerSchema(void* aContext, MarkerType aMarkerType, namespace ETW { static inline void Init() {} static inline void Shutdown() {} -static inline void EmitETWMarker(const mozilla::ProfilerString8View& aName, - const mozilla::MarkerCategory& aCategory, - const mozilla::MarkerOptions& aOptions = {}) {} template <typename MarkerType, typename... PayloadArguments> static inline void EmitETWMarker(const mozilla::ProfilerString8View& aName, const mozilla::MarkerCategory& aCategory, diff --git a/tools/profiler/public/GeckoProfiler.h b/tools/profiler/public/GeckoProfiler.h index f7c045297e..6b819addd8 100644 --- a/tools/profiler/public/GeckoProfiler.h +++ b/tools/profiler/public/GeckoProfiler.h @@ -269,7 +269,8 @@ class ProfilerStackCollector { virtual void CollectJitReturnAddr(void* aAddr) = 0; - virtual void CollectWasmFrame(const char* aLabel) = 0; + virtual void CollectWasmFrame(JS::ProfilingCategoryPair aCategory, + const char* aLabel) = 0; virtual void CollectProfilingStackFrame( const js::ProfilingStackFrame& aFrame) = 0; diff --git a/tools/profiler/public/GeckoTraceEvent.h b/tools/profiler/public/GeckoTraceEvent.h index 75affaf9c8..0887f74ac5 100644 --- a/tools/profiler/public/GeckoTraceEvent.h +++ b/tools/profiler/public/GeckoTraceEvent.h @@ -627,7 +627,18 @@ # else # define MOZ_INTERNAL_UPROFILER_SIMPLE_EVENT(phase, category_enabled, name, \ id, num_args, arg_names, \ - arg_types, arg_values, flags) + arg_types, arg_values, flags) \ + do { \ + (void)phase; \ + (void)category_enabled; \ + (void)name; \ + (void)id; \ + (void)num_args; \ + (void)arg_names; \ + (void)arg_types; \ + (void)arg_values; \ + (void)flags; \ + } while (0); # endif // Notes regarding the following definitions: diff --git a/tools/profiler/public/ProfilerMarkers.h b/tools/profiler/public/ProfilerMarkers.h index b1ba8c762f..cddb0fc307 100644 --- a/tools/profiler/public/ProfilerMarkers.h +++ b/tools/profiler/public/ProfilerMarkers.h @@ -389,34 +389,10 @@ extern template mozilla::ProfileBufferBlockIndex profiler_add_marker_impl( #endif // MOZ_GECKO_PROFILER namespace mozilla { - 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); -} +// Implement this here to prevent BaseProfilerMarkersPrerequisites from pulling +// in nsString.h template <> inline void StreamPayload<ProfilerString16View>( baseprofiler::SpliceableJSONWriter& aWriter, const Span<const char> aKey, @@ -424,86 +400,6 @@ inline void StreamPayload<ProfilerString16View>( aWriter.StringProperty(aKey, NS_ConvertUTF16toUTF8(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; - - 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 // ProfilerMarkers_h diff --git a/tools/profiler/public/ProfilerThreadRegistrationInfo.h b/tools/profiler/public/ProfilerThreadRegistrationInfo.h index e116c3059e..18a1c8fbaf 100644 --- a/tools/profiler/public/ProfilerThreadRegistrationInfo.h +++ b/tools/profiler/public/ProfilerThreadRegistrationInfo.h @@ -46,7 +46,10 @@ class ThreadRegistrationInfo { private: static TimeStamp ExistingRegisterTimeOrNow() { - TimeStamp registerTime = baseprofiler::detail::GetThreadRegistrationTime(); + TimeStamp registerTime; +#ifdef MOZ_GECKO_PROFILER + registerTime = baseprofiler::detail::GetThreadRegistrationTime(); +#endif if (!registerTime) { registerTime = TimeStamp::Now(); } |