use string_view instead of const char* in PerformanceObserver APIs (#39513)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39513

changelog: [internal]

Using std::hash with const char * is dangerous, as it will not hash the contents but only the pointer itself. We want to adopt std::hash in favour of folly to reduce our dependency on folly. One way to fix the issue with const char * is to use std::string_view.

Reviewed By: rshest, cipolleschi

Differential Revision: D49355536

fbshipit-source-id: fd2a7b4558461e913cdf0ec0e8fe878cae2f6015
This commit is contained in:
Samuel Susla
2023-09-22 05:53:13 -07:00
committed by Facebook GitHub Bot
parent 4221cba12d
commit aa03cc0b75
4 changed files with 60 additions and 56 deletions
@@ -155,7 +155,7 @@ void PerformanceEntryReporter::mark(
void PerformanceEntryReporter::clearEntries(
PerformanceEntryType entryType,
const char* entryName) {
std::string_view entryName) {
if (entryType == PerformanceEntryType::UNDEFINED) {
// Clear all entry types
for (int i = 1; i < NUM_PERFORMANCE_ENTRY_TYPES; i++) {
@@ -163,11 +163,11 @@ void PerformanceEntryReporter::clearEntries(
}
} else {
auto& buffer = getBuffer(entryType);
if (entryName != nullptr) {
if (!entryName.empty()) {
if (buffer.hasNameLookup) {
std::scoped_lock lock2(nameLookupMutex_);
RawPerformanceEntry entry{
entryName,
std::string(entryName),
static_cast<int>(entryType),
0.0,
0.0,
@@ -179,7 +179,7 @@ void PerformanceEntryReporter::clearEntries(
std::scoped_lock lock(entriesMutex_);
buffer.entries.clear([entryName](const RawPerformanceEntry& entry) {
return std::strcmp(entry.name.c_str(), entryName) == 0;
return entry.name == entryName;
});
} else {
{
@@ -196,7 +196,7 @@ void PerformanceEntryReporter::clearEntries(
void PerformanceEntryReporter::getEntries(
PerformanceEntryType entryType,
const char* entryName,
std::string_view entryName,
std::vector<RawPerformanceEntry>& res) const {
if (entryType == PerformanceEntryType::UNDEFINED) {
// Collect all entry types
@@ -206,11 +206,11 @@ void PerformanceEntryReporter::getEntries(
} else {
std::scoped_lock lock(entriesMutex_);
const auto& entries = getBuffer(entryType).entries;
if (entryName == nullptr) {
if (entryName.empty()) {
entries.getEntries(res);
} else {
entries.getEntries(res, [entryName](const RawPerformanceEntry& entry) {
return std::strcmp(entry.name.c_str(), entryName) == 0;
return entry.name == entryName;
});
}
}
@@ -218,7 +218,7 @@ void PerformanceEntryReporter::getEntries(
std::vector<RawPerformanceEntry> PerformanceEntryReporter::getEntries(
PerformanceEntryType entryType,
const char* entryName) const {
std::string_view entryName) const {
std::vector<RawPerformanceEntry> res;
getEntries(entryType, entryName, res);
return res;
@@ -298,7 +298,8 @@ void PerformanceEntryReporter::scheduleFlushBuffer() {
struct StrKey {
uint32_t key;
StrKey(const char* s) : key(folly::hash::fnv32_buf(s, std::strlen(s))) {}
StrKey(std::string_view s)
: key(folly::hash::fnv32_buf(s.data(), s.length())) {}
bool operator==(const StrKey& rhs) const {
return key == rhs.key;
@@ -316,51 +317,51 @@ struct StrKeyHash {
// Not all of these are currently supported by RN, but we map them anyway for
// future-proofing.
using SupportedEventTypeRegistry =
std::unordered_map<StrKey, const char*, StrKeyHash>;
std::unordered_map<StrKey, std::string_view, StrKeyHash>;
static const SupportedEventTypeRegistry& getSupportedEvents() {
static SupportedEventTypeRegistry 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"},
{StrKey("topAuxClick"), "auxclick"},
{StrKey("topClick"), "click"},
{StrKey("topContextMenu"), "contextmenu"},
{StrKey("topDblClick"), "dblclick"},
{StrKey("topMouseDown"), "mousedown"},
{StrKey("topMouseEnter"), "mouseenter"},
{StrKey("topMouseLeave"), "mouseleave"},
{StrKey("topMouseOut"), "mouseout"},
{StrKey("topMouseOver"), "mouseover"},
{StrKey("topMouseUp"), "mouseup"},
{StrKey("topPointerOver"), "pointerover"},
{StrKey("topPointerEnter"), "pointerenter"},
{StrKey("topPointerDown"), "pointerdown"},
{StrKey("topPointerUp"), "pointerup"},
{StrKey("topPointerCancel"), "pointercancel"},
{StrKey("topPointerOut"), "pointerout"},
{StrKey("topPointerLeave"), "pointerleave"},
{StrKey("topGotPointerCapture"), "gotpointercapture"},
{StrKey("topLostPointerCapture"), "lostpointercapture"},
{StrKey("topTouchStart"), "touchstart"},
{StrKey("topTouchEnd"), "touchend"},
{StrKey("topTouchCancel"), "touchcancel"},
{StrKey("topKeyDown"), "keydown"},
{StrKey("topKeyPress"), "keypress"},
{StrKey("topKeyUp"), "keyup"},
{StrKey("topBeforeInput"), "beforeinput"},
{StrKey("topInput"), "input"},
{StrKey("topCompositionStart"), "compositionstart"},
{StrKey("topCompositionUpdate"), "compositionupdate"},
{StrKey("topCompositionEnd"), "compositionend"},
{StrKey("topDragStart"), "dragstart"},
{StrKey("topDragEnd"), "dragend"},
{StrKey("topDragEnter"), "dragenter"},
{StrKey("topDragLeave"), "dragleave"},
{StrKey("topDragOver"), "dragover"},
{StrKey("topDrop"), "drop"},
};
return SUPPORTED_EVENTS;
}
EventTag PerformanceEntryReporter::onEventStart(const char* name) {
EventTag PerformanceEntryReporter::onEventStart(std::string_view name) {
if (!isReporting(PerformanceEntryType::EVENT)) {
return 0;
}
@@ -370,7 +371,7 @@ EventTag PerformanceEntryReporter::onEventStart(const char* name) {
return 0;
}
const char* reportedName = it->second;
auto reportedName = it->second;
sCurrentEventTag_++;
if (sCurrentEventTag_ == 0) {
@@ -419,7 +420,7 @@ void PerformanceEntryReporter::onEventEnd(EventTag tag) {
// (T141358175)
const uint32_t interactionId = 0;
event(
name,
std::string(name),
entry.startTime,
timeStamp - entry.startTime,
entry.dispatchTime,
@@ -13,6 +13,7 @@
#include <functional>
#include <mutex>
#include <optional>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include "BoundedConsumableBuffer.h"
@@ -125,11 +126,11 @@ class PerformanceEntryReporter : public EventLogger {
void clearEntries(
PerformanceEntryType entryType = PerformanceEntryType::UNDEFINED,
const char* entryName = nullptr);
std::string_view entryName = {});
std::vector<RawPerformanceEntry> getEntries(
PerformanceEntryType entryType = PerformanceEntryType::UNDEFINED,
const char* entryName = nullptr) const;
std::string_view entryName = {}) const;
void event(
std::string name,
@@ -139,7 +140,7 @@ class PerformanceEntryReporter : public EventLogger {
double processingEnd,
uint32_t interactionId);
EventTag onEventStart(const char* name) override;
EventTag onEventStart(std::string_view name) override;
void onEventDispatch(EventTag tag) override;
void onEventEnd(EventTag tag) override;
@@ -161,7 +162,7 @@ class PerformanceEntryReporter : public EventLogger {
uint32_t droppedEntryCount_{0};
struct EventEntry {
const char* name;
std::string_view name;
double startTime{0.0};
double dispatchTime{0.0};
};
@@ -186,7 +187,7 @@ class PerformanceEntryReporter : public EventLogger {
void getEntries(
PerformanceEntryType entryType,
const char* entryName,
std::string_view entryName,
std::vector<RawPerformanceEntry>& res) const;
double getCurrentTimeStamp() const;
@@ -43,7 +43,7 @@ void EventDispatcher::dispatchEvent(RawEvent&& rawEvent, EventPriority priority)
auto eventLogger = getEventLogger();
if (eventLogger != nullptr) {
rawEvent.loggingTag = eventLogger->onEventStart(rawEvent.type.c_str());
rawEvent.loggingTag = eventLogger->onEventStart(rawEvent.type);
}
getEventQueue(priority).enqueueEvent(std::move(rawEvent));
}
@@ -7,6 +7,8 @@
#pragma once
#include <string_view>
namespace facebook::react {
using EventTag = unsigned int;
@@ -24,7 +26,7 @@ class EventLogger {
* Called when an event is first created, returns and unique tag for this
* event, which can be used to log further event processing stages.
*/
virtual EventTag onEventStart(const char* name) = 0;
virtual EventTag onEventStart(std::string_view name) = 0;
/*
* Called when event starts getting dispatched (processed by the handlers, if