diff --git a/Libraries/WebPerformance/PerformanceEntryReporter.cpp b/Libraries/WebPerformance/PerformanceEntryReporter.cpp index f3913f41896..fc5bfa0c5a6 100644 --- a/Libraries/WebPerformance/PerformanceEntryReporter.cpp +++ b/Libraries/WebPerformance/PerformanceEntryReporter.cpp @@ -10,7 +10,7 @@ #include #include "NativePerformanceObserver.h" -#include +#include // All the unflushed entries beyond this amount will get discarded, with // the amount of discarded ones sent back to the observers' callbacks as @@ -167,14 +167,14 @@ double PerformanceEntryReporter::getMarkTime( } void PerformanceEntryReporter::event( - const std::string &name, + std::string name, double startTime, double duration, double processingStart, double processingEnd, uint32_t interactionId) { logEntry( - {name, + {std::move(name), static_cast(PerformanceEntryType::EVENT), startTime, duration, @@ -203,31 +203,89 @@ void PerformanceEntryReporter::scheduleFlushBuffer() { } } -static bool isDiscreteEvent(const char *name) { - return !std::strstr(name, "Move") && !std::strstr(name, "Layout"); -} +struct StrKey { + uint32_t key; + constexpr StrKey(const char *s) + : key(folly::hash::fnv32_buf(s, std::strlen(s))) {} + + constexpr bool operator==(const StrKey &rhs) const { + return key == rhs.key; + } +}; + +struct StrKeyHash { + constexpr size_t operator()(const StrKey &strKey) const { + return static_cast(strKey.key); + } +}; + +// Supported events for reporting, see +// https://www.w3.org/TR/event-timing/#sec-events-exposed +// Not all of these are currently supported by RN, but we map them anyway for +// future-proofing. +static const std::unordered_map + SUPPORTED_EVENTS = { + {"topAuxClick", "auxclick"}, + {"topClick", "click"}, + {"topContextMenu", "contextmenu"}, + {"topDblClick", "dblclick"}, + {"topMouseDown", "mousedown"}, + {"topMouseEnter", "mouseenter"}, + {"topMouseLeave", "mouseleave"}, + {"topMouseOut", "mouseout"}, + {"topMouseOver", "mouseover"}, + {"topMouseUp", "mouseup"}, + {"topPointerOver", "pointerover"}, + {"topPointerEnter", "pointerenter"}, + {"topPointerDown", "pointerdown"}, + {"topPointerUp", "pointerup"}, + {"topPointerCancel", "pointercancel"}, + {"topPointerOut", "pointerout"}, + {"topPointerLeave", "pointerleave"}, + {"topGotPointerCapture", "gotpointercapture"}, + {"topLostPointerCapture", "lostpointercapture"}, + {"topTouchStart", "touchstart"}, + {"topTouchEnd", "touchend"}, + {"topTouchCancel", "touchcancel"}, + {"topKeyDown", "keydown"}, + {"topKeyPress", "keypress"}, + {"topKeyUp", "keyup"}, + {"topBeforeInput", "beforeinput"}, + {"topInput", "input"}, + {"topCompositionStart", "compositionstart"}, + {"topCompositionUpdate", "compositionupdate"}, + {"topCompositionEnd", "compositionend"}, + {"topDragStart", "dragstart"}, + {"topDragEnd", "dragend"}, + {"topDragEnter", "dragenter"}, + {"topDragLeave", "dragleave"}, + {"topDragOver", "dragover"}, + {"topDrop", "drop"}, +}; EventTag PerformanceEntryReporter::onEventStart(const char *name) { - if (!isReportingEvents() || !isDiscreteEvent(name)) { + if (!isReportingEvents()) { return 0; } + auto it = SUPPORTED_EVENTS.find(name); + if (it == SUPPORTED_EVENTS.end()) { + return 0; + } + + const char *reportedName = it->second; + sCurrentEventTag_++; if (sCurrentEventTag_ == 0) { // The tag wrapped around (which is highly unlikely, but still) sCurrentEventTag_ = 1; } - if (std::strstr(name, "top") == name) { - // Skip the "top" prefix if present - name += 3; - } - auto timeStamp = JSExecutor::performanceNow(); { std::lock_guard lock(eventsInFlightMutex_); - eventsInFlight_.emplace( - std::make_pair(sCurrentEventTag_, EventEntry{name, timeStamp, 0.0})); + eventsInFlight_.emplace(std::make_pair( + sCurrentEventTag_, EventEntry{reportedName, timeStamp, 0.0})); } return sCurrentEventTag_; } @@ -259,13 +317,12 @@ void PerformanceEntryReporter::onEventEnd(EventTag tag) { } auto &entry = it->second; auto &name = entry.name; - std::transform(name.begin(), name.end(), name.begin(), ::tolower); // TODO: Define the way to assign interaction IDs to the event chains // (T141358175) const uint32_t interactionId = 0; event( - std::move(name), + name, entry.startTime, timeStamp - entry.startTime, entry.dispatchTime, diff --git a/Libraries/WebPerformance/PerformanceEntryReporter.h b/Libraries/WebPerformance/PerformanceEntryReporter.h index 183e801e12a..5a0cd35c7c1 100644 --- a/Libraries/WebPerformance/PerformanceEntryReporter.h +++ b/Libraries/WebPerformance/PerformanceEntryReporter.h @@ -91,7 +91,7 @@ class PerformanceEntryReporter : public EventLogger { void clearMeasures(const std::optional &measureName); void event( - const std::string &name, + std::string name, double startTime, double duration, double processingStart, @@ -125,7 +125,7 @@ class PerformanceEntryReporter : public EventLogger { uint32_t droppedEntryCount_{0}; struct EventEntry { - std::string name; + const char *name; double startTime{0.0}; double dispatchTime{0.0}; };