Use a more robust method of finding out which events to report
Summary: [Changelog][Internal] Use the [list of supported events](https://www.w3.org/TR/event-timing/#sec-events-exposed) explicitly to both filter and transform reported event types, which makes this both more robust and less ambiguous. The mapping is using a compile-time hash/lookup, similarly to how we do it with the ViewProps in the RN core. Reviewed By: rubennorte Differential Revision: D42342655 fbshipit-source-id: 3d0b2465fd5611db110c4792913e0a92e76cd067
This commit is contained in:
Родитель
3aea05651d
Коммит
21dbc67c03
|
@ -10,7 +10,7 @@
|
||||||
#include <react/renderer/core/EventLogger.h>
|
#include <react/renderer/core/EventLogger.h>
|
||||||
#include "NativePerformanceObserver.h"
|
#include "NativePerformanceObserver.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <unordered_map>
|
||||||
|
|
||||||
// All the unflushed entries beyond this amount will get discarded, with
|
// All the unflushed entries beyond this amount will get discarded, with
|
||||||
// the amount of discarded ones sent back to the observers' callbacks as
|
// the amount of discarded ones sent back to the observers' callbacks as
|
||||||
|
@ -167,14 +167,14 @@ double PerformanceEntryReporter::getMarkTime(
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceEntryReporter::event(
|
void PerformanceEntryReporter::event(
|
||||||
const std::string &name,
|
std::string name,
|
||||||
double startTime,
|
double startTime,
|
||||||
double duration,
|
double duration,
|
||||||
double processingStart,
|
double processingStart,
|
||||||
double processingEnd,
|
double processingEnd,
|
||||||
uint32_t interactionId) {
|
uint32_t interactionId) {
|
||||||
logEntry(
|
logEntry(
|
||||||
{name,
|
{std::move(name),
|
||||||
static_cast<int>(PerformanceEntryType::EVENT),
|
static_cast<int>(PerformanceEntryType::EVENT),
|
||||||
startTime,
|
startTime,
|
||||||
duration,
|
duration,
|
||||||
|
@ -203,31 +203,89 @@ void PerformanceEntryReporter::scheduleFlushBuffer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isDiscreteEvent(const char *name) {
|
struct StrKey {
|
||||||
return !std::strstr(name, "Move") && !std::strstr(name, "Layout");
|
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<size_t>(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<StrKey, const char *, StrKeyHash>
|
||||||
|
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) {
|
EventTag PerformanceEntryReporter::onEventStart(const char *name) {
|
||||||
if (!isReportingEvents() || !isDiscreteEvent(name)) {
|
if (!isReportingEvents()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto it = SUPPORTED_EVENTS.find(name);
|
||||||
|
if (it == SUPPORTED_EVENTS.end()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *reportedName = it->second;
|
||||||
|
|
||||||
sCurrentEventTag_++;
|
sCurrentEventTag_++;
|
||||||
if (sCurrentEventTag_ == 0) {
|
if (sCurrentEventTag_ == 0) {
|
||||||
// The tag wrapped around (which is highly unlikely, but still)
|
// The tag wrapped around (which is highly unlikely, but still)
|
||||||
sCurrentEventTag_ = 1;
|
sCurrentEventTag_ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::strstr(name, "top") == name) {
|
|
||||||
// Skip the "top" prefix if present
|
|
||||||
name += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto timeStamp = JSExecutor::performanceNow();
|
auto timeStamp = JSExecutor::performanceNow();
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(eventsInFlightMutex_);
|
std::lock_guard<std::mutex> lock(eventsInFlightMutex_);
|
||||||
eventsInFlight_.emplace(
|
eventsInFlight_.emplace(std::make_pair(
|
||||||
std::make_pair(sCurrentEventTag_, EventEntry{name, timeStamp, 0.0}));
|
sCurrentEventTag_, EventEntry{reportedName, timeStamp, 0.0}));
|
||||||
}
|
}
|
||||||
return sCurrentEventTag_;
|
return sCurrentEventTag_;
|
||||||
}
|
}
|
||||||
|
@ -259,13 +317,12 @@ void PerformanceEntryReporter::onEventEnd(EventTag tag) {
|
||||||
}
|
}
|
||||||
auto &entry = it->second;
|
auto &entry = it->second;
|
||||||
auto &name = entry.name;
|
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
|
// TODO: Define the way to assign interaction IDs to the event chains
|
||||||
// (T141358175)
|
// (T141358175)
|
||||||
const uint32_t interactionId = 0;
|
const uint32_t interactionId = 0;
|
||||||
event(
|
event(
|
||||||
std::move(name),
|
name,
|
||||||
entry.startTime,
|
entry.startTime,
|
||||||
timeStamp - entry.startTime,
|
timeStamp - entry.startTime,
|
||||||
entry.dispatchTime,
|
entry.dispatchTime,
|
||||||
|
|
|
@ -91,7 +91,7 @@ class PerformanceEntryReporter : public EventLogger {
|
||||||
void clearMeasures(const std::optional<std::string> &measureName);
|
void clearMeasures(const std::optional<std::string> &measureName);
|
||||||
|
|
||||||
void event(
|
void event(
|
||||||
const std::string &name,
|
std::string name,
|
||||||
double startTime,
|
double startTime,
|
||||||
double duration,
|
double duration,
|
||||||
double processingStart,
|
double processingStart,
|
||||||
|
@ -125,7 +125,7 @@ class PerformanceEntryReporter : public EventLogger {
|
||||||
uint32_t droppedEntryCount_{0};
|
uint32_t droppedEntryCount_{0};
|
||||||
|
|
||||||
struct EventEntry {
|
struct EventEntry {
|
||||||
std::string name;
|
const char *name;
|
||||||
double startTime{0.0};
|
double startTime{0.0};
|
||||||
double dispatchTime{0.0};
|
double dispatchTime{0.0};
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче