diff --git a/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp b/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp index ef6a44c0f12..eeca4b3c929 100644 --- a/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp +++ b/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp @@ -10,8 +10,10 @@ #include "RAMBundleRegistry.h" #include +#include #include +#include namespace facebook::react { @@ -27,8 +29,8 @@ std::string JSExecutor::getSyntheticBundlePath( return buffer.data(); } -HighResTimeStamp JSExecutor::performanceNow() { - return HighResTimeStamp::now(); +double JSExecutor::performanceNow() { + return chronoToDOMHighResTimeStamp(std::chrono::steady_clock::now()); } jsinspector_modern::RuntimeTargetDelegate& diff --git a/packages/react-native/ReactCommon/cxxreact/JSExecutor.h b/packages/react-native/ReactCommon/cxxreact/JSExecutor.h index 775e3971f58..469f4ca6fd7 100644 --- a/packages/react-native/ReactCommon/cxxreact/JSExecutor.h +++ b/packages/react-native/ReactCommon/cxxreact/JSExecutor.h @@ -14,7 +14,6 @@ #include #include #include -#include #ifndef RN_EXPORT #define RN_EXPORT __attribute__((visibility("default"))) @@ -139,7 +138,7 @@ class RN_EXPORT JSExecutor { uint32_t bundleId, const std::string& bundlePath); - static HighResTimeStamp performanceNow(); + static double performanceNow(); /** * Get a reference to the \c RuntimeTargetDelegate owned (or implemented) by diff --git a/packages/react-native/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp b/packages/react-native/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp index 39be0f0f055..6b226006768 100644 --- a/packages/react-native/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp +++ b/packages/react-native/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp @@ -556,9 +556,7 @@ void bindNativePerformanceNow(Runtime& runtime) { [](jsi::Runtime& runtime, const jsi::Value&, const jsi::Value* args, - size_t /*count*/) { - return JSExecutor::performanceNow().toDOMHighResTimeStamp(); - })); + size_t count) { return Value(JSExecutor::performanceNow()); })); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/jsinspector-modern/network/NetworkReporter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/network/NetworkReporter.cpp index 9f207a0a236..1eb6e19f20f 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/network/NetworkReporter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/network/NetworkReporter.cpp @@ -78,7 +78,7 @@ void NetworkReporter::reportRequestStart( int encodedDataLength, const std::optional& redirectResponse) { if (ReactNativeFeatureFlags::enableResourceTimingAPI()) { - auto now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); + double now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); // All builds: Annotate PerformanceResourceTiming metadata { @@ -127,7 +127,7 @@ void NetworkReporter::reportRequestStart( void NetworkReporter::reportConnectionTiming(const std::string& requestId) { if (ReactNativeFeatureFlags::enableResourceTimingAPI()) { - auto now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); + double now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); // All builds: Annotate PerformanceResourceTiming metadata { @@ -168,7 +168,7 @@ void NetworkReporter::reportResponseStart( const ResponseInfo& responseInfo, int encodedDataLength) { if (ReactNativeFeatureFlags::enableResourceTimingAPI()) { - auto now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); + double now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); // All builds: Annotate PerformanceResourceTiming metadata { @@ -205,7 +205,7 @@ void NetworkReporter::reportResponseStart( void NetworkReporter::reportDataReceived(const std::string& requestId) { if (ReactNativeFeatureFlags::enableResourceTimingAPI()) { - auto now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); + double now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); // All builds: Annotate PerformanceResourceTiming metadata { @@ -233,7 +233,7 @@ void NetworkReporter::reportResponseEnd( const std::string& requestId, int encodedDataLength) { if (ReactNativeFeatureFlags::enableResourceTimingAPI()) { - auto now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); + double now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp(); // All builds: Report PerformanceResourceTiming event { diff --git a/packages/react-native/ReactCommon/jsinspector-modern/network/NetworkReporter.h b/packages/react-native/ReactCommon/jsinspector-modern/network/NetworkReporter.h index 90701c412bf..4227deca3df 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/network/NetworkReporter.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/network/NetworkReporter.h @@ -35,11 +35,11 @@ using FrontendChannel = std::function; */ struct ResourceTimingData { std::string url; - HighResTimeStamp fetchStart; - HighResTimeStamp requestStart; - std::optional connectStart; - std::optional connectEnd; - std::optional responseStart; + DOMHighResTimeStamp fetchStart; + DOMHighResTimeStamp requestStart; + std::optional connectStart; + std::optional connectEnd; + std::optional responseStart; std::optional responseStatus; }; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tracing/EventLoopReporter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tracing/EventLoopReporter.cpp index 535fe2af5f1..0c9ccba0208 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tracing/EventLoopReporter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tracing/EventLoopReporter.cpp @@ -8,7 +8,6 @@ #include "EventLoopReporter.h" #if defined(REACT_NATIVE_DEBUGGER_ENABLED) -#include #include "PerformanceTracer.h" #endif diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp index 837e484efb0..0197b82c7f0 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp @@ -9,7 +9,6 @@ #include "Timing.h" #include -#include #include diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h index c01ff8b63f6..9acc978dfc7 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h @@ -13,8 +13,6 @@ #include -#include - #include #include #include diff --git a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp index 804d4a1f3f3..db7287e79d1 100644 --- a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp +++ b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp @@ -784,7 +784,7 @@ TEST_F(BridgingTest, highResTimeStampTest) { bridging::fromJs( rt, bridging::toJs(rt, timestamp), invoker)); - auto duration = HighResDuration::fromNanoseconds(1); + HighResDuration duration = HighResDuration::fromNanoseconds(1); EXPECT_EQ( duration, bridging::fromJs( diff --git a/packages/react-native/ReactCommon/react/nativemodule/intersectionobserver/NativeIntersectionObserver.h b/packages/react-native/ReactCommon/react/nativemodule/intersectionobserver/NativeIntersectionObserver.h index 3872a65217a..0d932e996d5 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/intersectionobserver/NativeIntersectionObserver.h +++ b/packages/react-native/ReactCommon/react/nativemodule/intersectionobserver/NativeIntersectionObserver.h @@ -51,7 +51,7 @@ using NativeIntersectionObserverEntry = // isIntersectingAboveThresholds bool, // time - HighResTimeStamp>; + double>; template <> struct Bridging diff --git a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp index d6ab76d20d8..e8b60299d66 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp @@ -116,31 +116,30 @@ std::shared_ptr tryGetObserver( NativePerformance::NativePerformance(std::shared_ptr jsInvoker) : NativePerformanceCxxSpec(std::move(jsInvoker)) {} -HighResTimeStamp NativePerformance::now(jsi::Runtime& /*rt*/) { +double NativePerformance::now(jsi::Runtime& /*rt*/) { return JSExecutor::performanceNow(); } -HighResTimeStamp NativePerformance::markWithResult( +double NativePerformance::markWithResult( jsi::Runtime& rt, std::string name, - std::optional startTime) { + std::optional startTime) { auto entry = PerformanceEntryReporter::getInstance()->reportMark(name, startTime); return entry.startTime; } -std::tuple -NativePerformance::measureWithResult( +std::tuple NativePerformance::measureWithResult( jsi::Runtime& runtime, std::string name, - HighResTimeStamp startTime, - HighResTimeStamp endTime, - std::optional duration, + double startTime, + double endTime, + std::optional duration, std::optional startMark, std::optional endMark) { auto reporter = PerformanceEntryReporter::getInstance(); - HighResTimeStamp startTimeValue = startTime; + DOMHighResTimeStamp startTimeValue = startTime; // If the start time mark name is specified, it takes precedence over the // startTime parameter, which can be set to 0 by default from JavaScript. if (startMark) { @@ -152,7 +151,7 @@ NativePerformance::measureWithResult( } } - HighResTimeStamp endTimeValue = endTime; + DOMHighResTimeStamp endTimeValue = endTime; // If the end time mark name is specified, it takes precedence over the // startTime parameter, which can be set to 0 by default from JavaScript. if (endMark) { @@ -346,8 +345,7 @@ void NativePerformance::observe( return; } - auto durationThreshold = - options.durationThreshold.value_or(HighResDuration::zero()); + auto durationThreshold = options.durationThreshold.value_or(0.0); // observer of type multiple if (options.entryTypes.has_value()) { diff --git a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.h b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.h index d2602b0b78b..1a23499f988 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.h +++ b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.h @@ -32,7 +32,7 @@ using NativePerformancePerformanceObserverObserveOptions = // buffered std::optional, // durationThreshold - std::optional>; + std::optional>; template <> struct Bridging { @@ -52,21 +52,21 @@ struct Bridging { struct NativePerformanceEntry { std::string name; PerformanceEntryType entryType; - HighResTimeStamp startTime; - HighResDuration duration; + DOMHighResTimeStamp startTime; + DOMHighResTimeStamp duration; // For PerformanceEventTiming only - std::optional processingStart; - std::optional processingEnd; + std::optional processingStart; + std::optional processingEnd; std::optional interactionId; // For PerformanceResourceTiming only - std::optional fetchStart; - std::optional requestStart; - std::optional connectStart; - std::optional connectEnd; - std::optional responseStart; - std::optional responseEnd; + std::optional fetchStart; + std::optional requestStart; + std::optional connectStart; + std::optional connectEnd; + std::optional responseStart; + std::optional responseEnd; std::optional responseStatus; }; @@ -86,23 +86,23 @@ class NativePerformance : public NativePerformanceCxxSpec { #pragma mark - DOM Performance (High Resolution Time) (https://www.w3.org/TR/hr-time-3/#dom-performance) // https://www.w3.org/TR/hr-time-3/#now-method - HighResTimeStamp now(jsi::Runtime& rt); + double now(jsi::Runtime& rt); #pragma mark - User Timing Level 3 functions (https://w3c.github.io/user-timing/) // https://w3c.github.io/user-timing/#mark-method - HighResTimeStamp markWithResult( + double markWithResult( jsi::Runtime& rt, std::string name, - std::optional startTime); + std::optional startTime); // https://w3c.github.io/user-timing/#measure-method - std::tuple measureWithResult( + std::tuple measureWithResult( jsi::Runtime& rt, std::string name, - HighResTimeStamp startTime, - HighResTimeStamp endTime, - std::optional duration, + double startTime, + double endTime, + std::optional duration, std::optional startMark, std::optional endMark); diff --git a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h index 887af0d1a07..e794902f85d 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h +++ b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h @@ -8,7 +8,6 @@ #pragma once #include - #include #include #include @@ -29,8 +28,8 @@ enum class PerformanceEntryType { struct AbstractPerformanceEntry { std::string name; - HighResTimeStamp startTime; - HighResDuration duration = HighResDuration::zero(); + DOMHighResTimeStamp startTime; + DOMHighResTimeStamp duration = 0; }; struct PerformanceMark : AbstractPerformanceEntry { @@ -44,8 +43,8 @@ struct PerformanceMeasure : AbstractPerformanceEntry { struct PerformanceEventTiming : AbstractPerformanceEntry { static constexpr PerformanceEntryType entryType = PerformanceEntryType::EVENT; - HighResTimeStamp processingStart; - HighResTimeStamp processingEnd; + DOMHighResTimeStamp processingStart; + DOMHighResTimeStamp processingEnd; PerformanceEntryInteractionId interactionId; }; @@ -58,13 +57,13 @@ struct PerformanceResourceTiming : AbstractPerformanceEntry { static constexpr PerformanceEntryType entryType = PerformanceEntryType::RESOURCE; /** Aligns with `startTime`. */ - HighResTimeStamp fetchStart; - HighResTimeStamp requestStart; - std::optional connectStart; - std::optional connectEnd; - std::optional responseStart; + DOMHighResTimeStamp fetchStart; + DOMHighResTimeStamp requestStart; + std::optional connectStart; + std::optional connectEnd; + std::optional responseStart; /** Aligns with `duration`. */ - std::optional responseEnd; + std::optional responseEnd; std::optional responseStatus; }; diff --git a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryBuffer.h b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryBuffer.h index c3ce79d3412..96a137ace14 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryBuffer.h +++ b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryBuffer.h @@ -14,7 +14,7 @@ namespace facebook::react { // Default duration threshold for reporting performance entries (0 means "report // all") -constexpr HighResDuration DEFAULT_DURATION_THRESHOLD = HighResDuration::zero(); +constexpr double DEFAULT_DURATION_THRESHOLD = 0.0; /** * Abstract performance entry buffer with reporting flags. @@ -22,7 +22,7 @@ constexpr HighResDuration DEFAULT_DURATION_THRESHOLD = HighResDuration::zero(); */ class PerformanceEntryBuffer { public: - HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; + double durationThreshold{DEFAULT_DURATION_THRESHOLD}; size_t droppedEntriesCount{0}; explicit PerformanceEntryBuffer() = default; diff --git a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.cpp b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.cpp index 01a7591ccef..441409b8571 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.cpp +++ b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.cpp @@ -37,6 +37,10 @@ std::vector getSupportedEntryTypesInternal() { return supportedEntryTypes; } +double performanceNow() { + return chronoToDOMHighResTimeStamp(std::chrono::steady_clock::now()); +} + #if defined(__clang__) #define NO_DESTROY [[clang::no_destroy]] #else @@ -79,9 +83,9 @@ PerformanceEntryReporter::PerformanceEntryReporter() #endif } -HighResTimeStamp PerformanceEntryReporter::getCurrentTimeStamp() const { +DOMHighResTimeStamp PerformanceEntryReporter::getCurrentTimeStamp() const { return timeStampProvider_ != nullptr ? timeStampProvider_() - : HighResTimeStamp::now(); + : performanceNow(); } std::vector @@ -169,7 +173,7 @@ void PerformanceEntryReporter::clearEntries( PerformanceMark PerformanceEntryReporter::reportMark( const std::string& name, - const std::optional& startTime) { + const std::optional& startTime) { // Resolve timings auto startTimeVal = startTime ? *startTime : getCurrentTimeStamp(); const auto entry = PerformanceMark{{.name = name, .startTime = startTimeVal}}; @@ -189,11 +193,11 @@ PerformanceMark PerformanceEntryReporter::reportMark( PerformanceMeasure PerformanceEntryReporter::reportMeasure( const std::string& name, - HighResTimeStamp startTime, - HighResTimeStamp endTime, + DOMHighResTimeStamp startTime, + DOMHighResTimeStamp endTime, const std::optional& trackMetadata) { - HighResDuration duration = endTime - startTime; + DOMHighResTimeStamp duration = endTime - startTime; const auto entry = PerformanceMeasure{ {.name = std::string(name), @@ -213,7 +217,7 @@ PerformanceMeasure PerformanceEntryReporter::reportMeasure( return entry; } -std::optional PerformanceEntryReporter::getMarkTime( +std::optional PerformanceEntryReporter::getMarkTime( const std::string& markName) const { std::shared_lock lock(buffersMutex_); @@ -227,10 +231,10 @@ std::optional PerformanceEntryReporter::getMarkTime( void PerformanceEntryReporter::reportEvent( std::string name, - HighResTimeStamp startTime, - HighResDuration duration, - HighResTimeStamp processingStart, - HighResTimeStamp processingEnd, + DOMHighResTimeStamp startTime, + DOMHighResTimeStamp duration, + DOMHighResTimeStamp processingStart, + DOMHighResTimeStamp processingEnd, uint32_t interactionId) { eventCounts_[name]++; @@ -256,8 +260,8 @@ void PerformanceEntryReporter::reportEvent( } void PerformanceEntryReporter::reportLongTask( - HighResTimeStamp startTime, - HighResDuration duration) { + DOMHighResTimeStamp startTime, + DOMHighResTimeStamp duration) { const auto entry = PerformanceLongTaskTiming{ {.name = std::string{"self"}, .startTime = startTime, @@ -273,12 +277,12 @@ void PerformanceEntryReporter::reportLongTask( PerformanceResourceTiming PerformanceEntryReporter::reportResourceTiming( const std::string& url, - HighResTimeStamp fetchStart, - HighResTimeStamp requestStart, - std::optional connectStart, - std::optional connectEnd, - HighResTimeStamp responseStart, - HighResTimeStamp responseEnd, + DOMHighResTimeStamp fetchStart, + DOMHighResTimeStamp requestStart, + std::optional connectStart, + std::optional connectEnd, + DOMHighResTimeStamp responseStart, + DOMHighResTimeStamp responseEnd, const std::optional& responseStatus) { const auto entry = PerformanceResourceTiming{ {.name = url, .startTime = fetchStart}, @@ -309,7 +313,9 @@ void PerformanceEntryReporter::traceMark(const PerformanceMark& entry) const { auto [trackName, eventName] = parseTrackName(entry.name); if (performanceTracer.isTracing()) { - performanceTracer.reportMark(entry.name, entry.startTime); + performanceTracer.reportMark( + entry.name, + HighResTimeStamp::fromDOMHighResTimeStamp(entry.startTime)); } if (ReactPerfettoLogger::isTracing()) { @@ -333,7 +339,10 @@ void PerformanceEntryReporter::traceMeasure( trackMetadata = {.track = trackName.value()}; } performanceTracer.reportMeasure( - eventName, entry.startTime, entry.duration, trackMetadata); + eventName, + HighResTimeStamp::fromDOMHighResTimeStamp(entry.startTime), + HighResDuration::fromDOMHighResTimeStamp(entry.duration), + trackMetadata); } if (ReactPerfettoLogger::isTracing()) { diff --git a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.h b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.h index 2eb67ceca03..549fe6f591a 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.h +++ b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.h @@ -27,8 +27,7 @@ constexpr size_t EVENT_BUFFER_SIZE = 150; constexpr size_t LONG_TASK_BUFFER_SIZE = 200; constexpr size_t RESOURCE_TIMING_BUFFER_SIZE = 250; -constexpr HighResDuration LONG_TASK_DURATION_THRESHOLD = - HighResDuration::fromMilliseconds(50); +constexpr DOMHighResTimeStamp LONG_TASK_DURATION_THRESHOLD_MS = 50.0; class PerformanceEntryReporter { public: @@ -67,9 +66,9 @@ class PerformanceEntryReporter { PerformanceEntryType entryType, const std::string& entryName); - HighResTimeStamp getCurrentTimeStamp() const; + DOMHighResTimeStamp getCurrentTimeStamp() const; - void setTimeStampProvider(std::function provider) { + void setTimeStampProvider(std::function provider) { timeStampProvider_ = std::move(provider); } @@ -81,38 +80,37 @@ class PerformanceEntryReporter { return eventCounts_; } - std::optional getMarkTime( - const std::string& markName) const; + std::optional getMarkTime(const std::string& markName) const; PerformanceMark reportMark( const std::string& name, - const std::optional& startTime = std::nullopt); + const std::optional& startTime = std::nullopt); PerformanceMeasure reportMeasure( const std::string& name, - HighResTimeStamp startTime, - HighResTimeStamp endTime, + double startTime, + double endTime, const std::optional& trackMetadata = std::nullopt); void reportEvent( std::string name, - HighResTimeStamp startTime, - HighResDuration duration, - HighResTimeStamp processingStart, - HighResTimeStamp processingEnd, + double startTime, + double duration, + double processingStart, + double processingEnd, uint32_t interactionId); - void reportLongTask(HighResTimeStamp startTime, HighResDuration duration); + void reportLongTask(double startTime, double duration); PerformanceResourceTiming reportResourceTiming( const std::string& url, - HighResTimeStamp fetchStart, - HighResTimeStamp requestStart, - std::optional connectStart, - std::optional connectEnd, - HighResTimeStamp responseStart, - HighResTimeStamp responseEnd, + DOMHighResTimeStamp fetchStart, + DOMHighResTimeStamp requestStart, + std::optional connectStart, + std::optional connectEnd, + DOMHighResTimeStamp responseStart, + DOMHighResTimeStamp responseEnd, const std::optional& responseStatus); private: @@ -128,7 +126,7 @@ class PerformanceEntryReporter { std::unordered_map eventCounts_; - std::function timeStampProvider_ = nullptr; + std::function timeStampProvider_ = nullptr; const inline PerformanceEntryBuffer& getBuffer( PerformanceEntryType entryType) const { diff --git a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceObserver.h b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceObserver.h index 8b387ec753c..a79d8d0a99f 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceObserver.h +++ b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceObserver.h @@ -7,15 +7,12 @@ #pragma once -#include "PerformanceEntryBuffer.h" -#include "PerformanceObserverRegistry.h" - -#include - #include #include #include #include +#include "PerformanceEntryBuffer.h" +#include "PerformanceObserverRegistry.h" namespace facebook::react { @@ -30,7 +27,7 @@ using PerformanceObserverCallback = std::function; * https://w3c.github.io/performance-timeline/#performanceobserverinit-dictionary */ struct PerformanceObserverObserveMultipleOptions { - HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; + double durationThreshold = 0.0; }; /** @@ -41,7 +38,7 @@ struct PerformanceObserverObserveMultipleOptions { */ struct PerformanceObserverObserveSingleOptions { bool buffered = false; - HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; + double durationThreshold = 0.0; }; /** @@ -127,7 +124,7 @@ class PerformanceObserver PerformanceObserverEntryTypeFilter observedTypes_; /// https://www.w3.org/TR/event-timing/#sec-modifications-perf-timeline - HighResDuration durationThreshold_ = DEFAULT_DURATION_THRESHOLD; + double durationThreshold_{DEFAULT_DURATION_THRESHOLD}; std::vector buffer_; bool didScheduleFlushBuffer_ = false; bool requiresDroppedEntries_ = false; diff --git a/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceEntryReporterTest.cpp b/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceEntryReporterTest.cpp index 330eb185f44..5217debd97d 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceEntryReporterTest.cpp +++ b/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceEntryReporterTest.cpp @@ -58,10 +58,8 @@ namespace facebook::react { [&](const auto& entryDetails) -> std::ostream& { os << "{ .name = \"" << entryDetails.name << "\"" << ", .entryType = " << entryTypeNames[static_cast(entryDetails.entryType) - 1] - << ", .startTime = " - << entryDetails.startTime.toDOMHighResTimeStamp() - << ", .duration = " << entryDetails.duration.toDOMHighResTimeStamp() - << " }"; + << ", .startTime = " << entryDetails.startTime + << ", .duration = " << entryDetails.duration << " }"; return os; }, entry); @@ -79,116 +77,60 @@ std::vector toSorted( TEST(PerformanceEntryReporter, PerformanceEntryReporterTestReportMarks) { auto reporter = PerformanceEntryReporter::getInstance(); - auto timeOrigin = HighResTimeStamp::now(); reporter->clearEntries(); - reporter->reportMark("mark0", timeOrigin); - reporter->reportMark( - "mark1", timeOrigin + HighResDuration::fromMilliseconds(1)); - reporter->reportMark( - "mark2", timeOrigin + HighResDuration::fromMilliseconds(2)); + reporter->reportMark("mark0", 0); + reporter->reportMark("mark1", 1); + reporter->reportMark("mark2", 2); // Report mark0 again - reporter->reportMark( - "mark0", timeOrigin + HighResDuration::fromMilliseconds(3)); + reporter->reportMark("mark0", 3); const auto entries = toSorted(reporter->getEntries()); ASSERT_EQ(4, entries.size()); const std::vector expected = { - PerformanceMark{ - {.name = "mark0", - .startTime = timeOrigin, - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark1", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(1), - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark2", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(2), - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark0", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(3), - .duration = HighResDuration::zero()}}}; + PerformanceMark{{.name = "mark0", .startTime = 0, .duration = 0}}, + PerformanceMark{{.name = "mark1", .startTime = 1, .duration = 0}}, + PerformanceMark{{.name = "mark2", .startTime = 2, .duration = 0}}, + PerformanceMark{{.name = "mark0", .startTime = 3, .duration = 0}}}; ASSERT_EQ(expected, entries); } TEST(PerformanceEntryReporter, PerformanceEntryReporterTestReportMeasures) { auto reporter = PerformanceEntryReporter::getInstance(); - auto timeOrigin = HighResTimeStamp::now(); reporter->clearEntries(); - reporter->reportMark("mark0", timeOrigin); - reporter->reportMark( - "mark1", timeOrigin + HighResDuration::fromMilliseconds(1)); - reporter->reportMark( - "mark2", timeOrigin + HighResDuration::fromMilliseconds(2)); + reporter->reportMark("mark0", 0); + reporter->reportMark("mark1", 1); + reporter->reportMark("mark2", 2); - reporter->reportMeasure( - "measure0", - timeOrigin, - timeOrigin + HighResDuration::fromMilliseconds(2)); - reporter->reportMeasure( - "measure1", - timeOrigin, - timeOrigin + HighResDuration::fromMilliseconds(3)); + reporter->reportMeasure("measure0", 0, 2); + reporter->reportMeasure("measure1", 0, 3); - reporter->reportMark( - "mark3", timeOrigin + HighResDuration::fromNanoseconds(2.5 * 1e6)); - reporter->reportMeasure( - "measure2", - timeOrigin + HighResDuration::fromMilliseconds(2), - timeOrigin + HighResDuration::fromMilliseconds(2)); - reporter->reportMark( - "mark4", timeOrigin + HighResDuration::fromMilliseconds(3)); + reporter->reportMark("mark3", 2.5); + reporter->reportMeasure("measure2", 2.0, 2.0); + reporter->reportMark("mark4", 3.0); const auto entries = toSorted(reporter->getEntries()); const std::vector expected = { - PerformanceMark{ - {.name = "mark0", - .startTime = timeOrigin, - .duration = HighResDuration::zero()}}, - PerformanceMeasure{ - {.name = "measure0", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(2)}}, - PerformanceMeasure{ - {.name = "measure1", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(3)}}, - PerformanceMark{ - {.name = "mark1", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(1), - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark2", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(2), - .duration = HighResDuration::zero()}}, - PerformanceMeasure{ - {.name = "measure2", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(2), - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark3", - .startTime = - timeOrigin + HighResDuration::fromNanoseconds(2.5 * 1e6), - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark4", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(3), - .duration = HighResDuration::zero()}}}; + PerformanceMark{{.name = "mark0", .startTime = 0, .duration = 0}}, + PerformanceMeasure{{.name = "measure0", .startTime = 0, .duration = 2}}, + PerformanceMeasure{{.name = "measure1", .startTime = 0, .duration = 3}}, + PerformanceMark{{.name = "mark1", .startTime = 1, .duration = 0}}, + PerformanceMark{{.name = "mark2", .startTime = 2, .duration = 0}}, + PerformanceMeasure{{.name = "measure2", .startTime = 2, .duration = 0}}, + PerformanceMark{{.name = "mark3", .startTime = 2.5, .duration = 0}}, + PerformanceMark{{.name = "mark4", .startTime = 3, .duration = 0}}}; ASSERT_EQ(expected, entries); } TEST(PerformanceEntryReporter, PerformanceEntryReporterTestGetEntries) { auto reporter = PerformanceEntryReporter::getInstance(); - auto timeOrigin = HighResTimeStamp::now(); reporter->clearEntries(); { @@ -196,61 +138,27 @@ TEST(PerformanceEntryReporter, PerformanceEntryReporterTestGetEntries) { ASSERT_EQ(0, entries.size()); } - reporter->reportMark("common_name", timeOrigin); - reporter->reportMark( - "mark1", timeOrigin + HighResDuration::fromMilliseconds(1)); - reporter->reportMark( - "mark2", timeOrigin + HighResDuration::fromMilliseconds(2)); + reporter->reportMark("common_name", 0); + reporter->reportMark("mark1", 1); + reporter->reportMark("mark2", 2); - reporter->reportMeasure( - "common_name", - timeOrigin, - timeOrigin + HighResDuration::fromMilliseconds(2)); - reporter->reportMeasure( - "measure1", - timeOrigin, - timeOrigin + HighResDuration::fromMilliseconds(3)); - reporter->reportMeasure( - "measure2", - timeOrigin + HighResDuration::fromMilliseconds(1), - timeOrigin + HighResDuration::fromMilliseconds(6)); - reporter->reportMeasure( - "measure3", - timeOrigin + HighResDuration::fromNanoseconds(1.5 * 1e6), - timeOrigin + HighResDuration::fromMilliseconds(2)); + reporter->reportMeasure("common_name", 0, 2); + reporter->reportMeasure("measure1", 0, 3); + reporter->reportMeasure("measure2", 1, 6); + reporter->reportMeasure("measure3", 1.5, 2); { const auto allEntries = toSorted(reporter->getEntries()); const std::vector expected = { - PerformanceMark{ - {.name = "common_name", - .startTime = timeOrigin, - .duration = HighResDuration::zero()}}, + PerformanceMark{{.name = "common_name", .startTime = 0, .duration = 0}}, PerformanceMeasure{ - {.name = "common_name", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(2)}}, + {.name = "common_name", .startTime = 0, .duration = 2}}, + PerformanceMeasure{{.name = "measure1", .startTime = 0, .duration = 3}}, + PerformanceMark{{.name = "mark1", .startTime = 1, .duration = 0}}, + PerformanceMeasure{{.name = "measure2", .startTime = 1, .duration = 5}}, PerformanceMeasure{ - {.name = "measure1", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(3)}}, - PerformanceMark{ - {.name = "mark1", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(1), - .duration = HighResDuration::zero()}}, - PerformanceMeasure{ - {.name = "measure2", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(1), - .duration = HighResDuration::fromMilliseconds(5)}}, - PerformanceMeasure{ - {.name = "measure3", - .startTime = - timeOrigin + HighResDuration::fromNanoseconds(1.5 * 1e6), - .duration = HighResDuration::fromNanoseconds(0.5 * 1e6)}}, - PerformanceMark{ - {.name = "mark2", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(2), - .duration = HighResDuration::zero()}}}; + {.name = "measure3", .startTime = 1.5, .duration = 0.5}}, + PerformanceMark{{.name = "mark2", .startTime = 2, .duration = 0}}}; ASSERT_EQ(expected, allEntries); } @@ -258,18 +166,9 @@ TEST(PerformanceEntryReporter, PerformanceEntryReporterTestGetEntries) { const auto marks = toSorted(reporter->getEntries(PerformanceEntryType::MARK)); const std::vector expected = { - PerformanceMark{ - {.name = "common_name", - .startTime = timeOrigin, - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark1", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(1), - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark2", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(2), - .duration = HighResDuration::zero()}}}; + PerformanceMark{{.name = "common_name", .startTime = 0, .duration = 0}}, + PerformanceMark{{.name = "mark1", .startTime = 1, .duration = 0}}, + PerformanceMark{{.name = "mark2", .startTime = 2, .duration = 0}}}; ASSERT_EQ(expected, marks); } @@ -278,28 +177,17 @@ TEST(PerformanceEntryReporter, PerformanceEntryReporterTestGetEntries) { toSorted(reporter->getEntries(PerformanceEntryType::MEASURE)); const std::vector expected = { PerformanceMeasure{ - {.name = "common_name", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(2)}}, + {.name = "common_name", .startTime = 0, .duration = 2}}, + PerformanceMeasure{{.name = "measure1", .startTime = 0, .duration = 3}}, + PerformanceMeasure{{.name = "measure2", .startTime = 1, .duration = 5}}, PerformanceMeasure{ - {.name = "measure1", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(3)}}, - PerformanceMeasure{ - {.name = "measure2", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(1), - .duration = HighResDuration::fromMilliseconds(5)}}, - PerformanceMeasure{ - {.name = "measure3", - .startTime = - timeOrigin + HighResDuration::fromNanoseconds(1.5 * 1e6), - .duration = HighResDuration::fromNanoseconds(0.5 * 1e6)}}}; + {.name = "measure3", .startTime = 1.5, .duration = 0.5}}}; ASSERT_EQ(expected, measures); } { const std::vector expected = { - PerformanceMark{{.name = "common_name", .startTime = timeOrigin}}}; + PerformanceMark{{.name = "common_name", .startTime = 0}}}; const auto commonName = reporter->getEntries(PerformanceEntryType::MARK, "common_name"); ASSERT_EQ(expected, commonName); @@ -307,9 +195,7 @@ TEST(PerformanceEntryReporter, PerformanceEntryReporterTestGetEntries) { { const std::vector expected = {PerformanceMeasure{ - {.name = "common_name", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(2)}}}; + {.name = "common_name", .startTime = 0, .duration = 2}}}; const auto commonName = reporter->getEntries(PerformanceEntryType::MEASURE, "common_name"); ASSERT_EQ(expected, commonName); @@ -318,52 +204,26 @@ TEST(PerformanceEntryReporter, PerformanceEntryReporterTestGetEntries) { TEST(PerformanceEntryReporter, PerformanceEntryReporterTestClearMarks) { auto reporter = PerformanceEntryReporter::getInstance(); - auto timeOrigin = HighResTimeStamp::now(); reporter->clearEntries(); - reporter->reportMark("common_name", timeOrigin); - reporter->reportMark( - "mark1", timeOrigin + HighResDuration::fromMilliseconds(1)); - reporter->reportMark( - "mark1", timeOrigin + HighResDuration::fromNanoseconds(2.1 * 1e6)); - reporter->reportMark( - "mark2", timeOrigin + HighResDuration::fromMilliseconds(2)); + reporter->reportMark("common_name", 0); + reporter->reportMark("mark1", 1); + reporter->reportMark("mark1", 2.1); + reporter->reportMark("mark2", 2); - reporter->reportMeasure( - "common_name", - timeOrigin, - timeOrigin + HighResDuration::fromMilliseconds(2)); - reporter->reportMeasure( - "measure1", - timeOrigin, - timeOrigin + HighResDuration::fromMilliseconds(3)); - reporter->reportMeasure( - "measure2", - timeOrigin + HighResDuration::fromMilliseconds(1), - timeOrigin + HighResDuration::fromMilliseconds(6)); - reporter->reportMeasure( - "measure3", - timeOrigin + HighResDuration::fromNanoseconds(1.5 * 1e6), - timeOrigin + HighResDuration::fromMilliseconds(2)); + reporter->reportMeasure("common_name", 0, 2); + reporter->reportMeasure("measure1", 0, 3); + reporter->reportMeasure("measure2", 1, 6); + reporter->reportMeasure("measure3", 1.5, 2); reporter->clearEntries(PerformanceEntryType::MARK, "common_name"); { auto entries = toSorted(reporter->getEntries(PerformanceEntryType::MARK)); std::vector expected = { - PerformanceMark{ - {.name = "mark1", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(1), - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark2", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(2), - .duration = HighResDuration::zero()}}, - PerformanceMark{ - {.name = "mark1", - .startTime = - timeOrigin + HighResDuration::fromNanoseconds(2.1 * 1e6), - .duration = HighResDuration::zero()}}, + PerformanceMark{{.name = "mark1", .startTime = 1, .duration = 0}}, + PerformanceMark{{.name = "mark2", .startTime = 2, .duration = 0}}, + PerformanceMark{{.name = "mark1", .startTime = 2.1, .duration = 0}}, }; ASSERT_EQ(expected, entries); } diff --git a/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceObserverTest.cpp b/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceObserverTest.cpp index 0a954958288..06cf2c3e09b 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceObserverTest.cpp +++ b/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceObserverTest.cpp @@ -49,14 +49,12 @@ TEST(PerformanceObserver, PerformanceObserverTestObserveFlushes) { bool callbackCalled = false; auto observer = PerformanceObserver::create( reporter->getObserverRegistry(), [&]() { callbackCalled = true; }); - auto timeOrigin = HighResTimeStamp::now(); observer->observe(PerformanceEntryType::MARK); // buffer is empty ASSERT_FALSE(callbackCalled); - reporter->reportMark( - "test", timeOrigin + HighResDuration::fromMilliseconds(10)); + reporter->reportMark("test", 10); ASSERT_TRUE(callbackCalled); observer->disconnect(); @@ -66,12 +64,10 @@ TEST(PerformanceObserver, PerformanceObserverTestFilteredSingle) { auto reporter = PerformanceEntryReporter::getInstance(); reporter->clearEntries(); - auto timeOrigin = HighResTimeStamp::now(); auto observer = PerformanceObserver::create(reporter->getObserverRegistry(), [&]() {}); observer->observe(PerformanceEntryType::MEASURE); - reporter->reportMark( - "test", timeOrigin + HighResDuration::fromMilliseconds(10)); + reporter->reportMark("test", 10); // wrong type ASSERT_EQ(observer->takeRecords().size(), 0); @@ -83,34 +79,15 @@ TEST(PerformanceObserver, PerformanceObserverTestFilterMulti) { auto reporter = PerformanceEntryReporter::getInstance(); reporter->clearEntries(); - auto timeOrigin = HighResTimeStamp::now(); auto callbackCalled = false; auto observer = PerformanceObserver::create( reporter->getObserverRegistry(), [&]() { callbackCalled = true; }); observer->observe( {PerformanceEntryType::MEASURE, PerformanceEntryType::MARK}); - reporter->reportEvent( - "test1", - timeOrigin + HighResDuration::fromMilliseconds(10), - HighResDuration::fromMilliseconds(10), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "test2", - timeOrigin + HighResDuration::fromMilliseconds(10), - HighResDuration::fromMilliseconds(10), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "test3", - timeOrigin + HighResDuration::fromMilliseconds(10), - HighResDuration::fromMilliseconds(10), - timeOrigin, - timeOrigin, - 0); + reporter->reportEvent("test1", 10, 10, 0, 0, 0); + reporter->reportEvent("test2", 10, 10, 0, 0, 0); + reporter->reportEvent("test3", 10, 10, 0, 0, 0); ASSERT_EQ(observer->takeRecords().size(), 0); ASSERT_FALSE(callbackCalled); @@ -124,14 +101,11 @@ TEST( auto reporter = PerformanceEntryReporter::getInstance(); reporter->clearEntries(); - auto timeOrigin = HighResTimeStamp::now(); auto callbackCalled = false; auto observer = PerformanceObserver::create( reporter->getObserverRegistry(), [&]() { callbackCalled = true; }); observer->observe(PerformanceEntryType::MEASURE); - - reporter->reportMark( - "test", timeOrigin + HighResDuration::fromMilliseconds(10)); + reporter->reportMark("test", 10); ASSERT_FALSE(callbackCalled); @@ -142,34 +116,14 @@ TEST(PerformanceObserver, PerformanceObserverTestFilterMultiCallbackNotCalled) { auto reporter = PerformanceEntryReporter::getInstance(); reporter->clearEntries(); - auto timeOrigin = HighResTimeStamp::now(); auto callbackCalled = false; auto observer = PerformanceObserver::create( reporter->getObserverRegistry(), [&]() { callbackCalled = true; }); observer->observe( {PerformanceEntryType::MEASURE, PerformanceEntryType::MARK}); - - reporter->reportEvent( - "test1", - timeOrigin + HighResDuration::fromMilliseconds(10), - HighResDuration::fromMilliseconds(10), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "test2", - timeOrigin + HighResDuration::fromMilliseconds(10), - HighResDuration::fromMilliseconds(10), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "off3", - timeOrigin + HighResDuration::fromMilliseconds(10), - HighResDuration::fromMilliseconds(10), - timeOrigin, - timeOrigin, - 0); + reporter->reportEvent("test1", 10, 10, 0, 0, 0); + reporter->reportEvent("test2", 10, 10, 0, 0, 0); + reporter->reportEvent("off3", 10, 10, 0, 0, 0); ASSERT_FALSE(callbackCalled); @@ -180,32 +134,18 @@ TEST(PerformanceObserver, PerformanceObserverTestObserveTakeRecords) { auto reporter = PerformanceEntryReporter::getInstance(); reporter->clearEntries(); - auto timeOrigin = HighResTimeStamp::now(); auto observer = PerformanceObserver::create(reporter->getObserverRegistry(), [&]() {}); observer->observe(PerformanceEntryType::MARK); - - reporter->reportMark( - "test1", timeOrigin + HighResDuration::fromMilliseconds(10)); - reporter->reportMeasure( - "off", - timeOrigin + HighResDuration::fromMilliseconds(10), - timeOrigin + HighResDuration::fromMilliseconds(20)); - reporter->reportMark( - "test2", timeOrigin + HighResDuration::fromMilliseconds(20)); - reporter->reportMark( - "test3", timeOrigin + HighResDuration::fromMilliseconds(30)); + reporter->reportMark("test1", 10); + reporter->reportMeasure("off", 10, 20); + reporter->reportMark("test2", 20); + reporter->reportMark("test3", 30); const std::vector expected = { - PerformanceMark{ - {.name = "test1", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(10)}}, - PerformanceMark{ - {.name = "test2", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(20)}}, - PerformanceMark{ - {.name = "test3", - .startTime = timeOrigin + HighResDuration::fromMilliseconds(30)}}, + PerformanceMark{{.name = "test1", .startTime = 10}}, + PerformanceMark{{.name = "test2", .startTime = 20}}, + PerformanceMark{{.name = "test3", .startTime = 30}}, }; ASSERT_EQ(expected, observer->takeRecords()); @@ -217,66 +157,19 @@ TEST(PerformanceObserver, PerformanceObserverTestObserveDurationThreshold) { auto reporter = PerformanceEntryReporter::getInstance(); reporter->clearEntries(); - auto timeOrigin = HighResTimeStamp::now(); auto observer = PerformanceObserver::create(reporter->getObserverRegistry(), [&]() {}); - observer->observe( - PerformanceEntryType::EVENT, - {.durationThreshold = HighResDuration::fromMilliseconds(50)}); - - reporter->reportEvent( - "test1", - timeOrigin, - HighResDuration::fromMilliseconds(50), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "test2", - timeOrigin, - HighResDuration::fromMilliseconds(100), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "off1", - timeOrigin, - HighResDuration::fromMilliseconds(40), - timeOrigin, - timeOrigin, - 0); - reporter->reportMark( - "off2", timeOrigin + HighResDuration::fromMilliseconds(100)); - reporter->reportEvent( - "test3", - timeOrigin, - HighResDuration::fromMilliseconds(60), - timeOrigin, - timeOrigin, - 0); + observer->observe(PerformanceEntryType::EVENT, {.durationThreshold = 50}); + reporter->reportEvent("test1", 0, 50, 0, 0, 0); + reporter->reportEvent("test2", 0, 100, 0, 0, 0); + reporter->reportEvent("off1", 0, 40, 0, 0, 0); + reporter->reportMark("off2", 100); + reporter->reportEvent("test3", 0, 60, 0, 0, 0); const std::vector expected = { - PerformanceEventTiming{ - {.name = "test1", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(50)}, - timeOrigin, - timeOrigin, - 0}, - PerformanceEventTiming{ - {.name = "test2", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(100)}, - timeOrigin, - timeOrigin, - 0}, - PerformanceEventTiming{ - {.name = "test3", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(60)}, - timeOrigin, - timeOrigin, - 0}, + PerformanceEventTiming{{.name = "test1", .duration = 50}, 0, 0, 0}, + PerformanceEventTiming{{.name = "test2", .duration = 100}, 0, 0, 0}, + PerformanceEventTiming{{.name = "test3", .duration = 60}, 0, 0, 0}, }; ASSERT_EQ(expected, observer->takeRecords()); @@ -288,65 +181,23 @@ TEST(PerformanceObserver, PerformanceObserverTestObserveBuffered) { auto reporter = PerformanceEntryReporter::getInstance(); reporter->clearEntries(); - auto timeOrigin = HighResTimeStamp::now(); - reporter->reportEvent( - "test1", - timeOrigin, - HighResDuration::fromMilliseconds(50), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "test2", - timeOrigin, - HighResDuration::fromMilliseconds(100), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "test3", - timeOrigin, - HighResDuration::fromMilliseconds(40), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "test4", - timeOrigin, - HighResDuration::fromMilliseconds(100), - timeOrigin, - timeOrigin, - 0); + reporter->reportEvent("test1", 0, 50, 0, 0, 0); + reporter->reportEvent("test2", 0, 100, 0, 0, 0); + reporter->reportEvent("test3", 0, 40, 0, 0, 0); + reporter->reportEvent("test4", 0, 100, 0, 0, 0); auto observer = PerformanceObserver::create(reporter->getObserverRegistry(), [&]() {}); observer->observe( - PerformanceEntryType::EVENT, - {.buffered = true, - .durationThreshold = HighResDuration::fromMilliseconds(50)}); + PerformanceEntryType::EVENT, {.buffered = true, .durationThreshold = 50}); const std::vector expected = { PerformanceEventTiming{ - {.name = "test1", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(50)}, - timeOrigin, - timeOrigin, - 0}, + {.name = "test1", .startTime = 0, .duration = 50}, 0, 0, 0}, PerformanceEventTiming{ - {.name = "test2", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(100)}, - timeOrigin, - timeOrigin, - 0}, + {.name = "test2", .startTime = 0, .duration = 100}, 0, 0, 0}, PerformanceEventTiming{ - {.name = "test4", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(100)}, - timeOrigin, - timeOrigin, - 0}, + {.name = "test4", .startTime = 0, .duration = 100}, 0, 0, 0}, }; ASSERT_EQ(expected, observer->takeRecords()); @@ -358,71 +209,26 @@ TEST(PerformanceObserver, PerformanceObserverTestMultiple) { auto reporter = PerformanceEntryReporter::getInstance(); reporter->clearEntries(); - auto timeOrigin = HighResTimeStamp::now(); auto observer1 = PerformanceObserver::create(reporter->getObserverRegistry(), [&]() {}); auto observer2 = PerformanceObserver::create(reporter->getObserverRegistry(), [&]() {}); - observer1->observe( - PerformanceEntryType::EVENT, - {.durationThreshold = HighResDuration::fromMilliseconds(50)}); - observer2->observe( - PerformanceEntryType::EVENT, - {.durationThreshold = HighResDuration::fromMilliseconds(80)}); + observer1->observe(PerformanceEntryType::EVENT, {.durationThreshold = 50}); + observer2->observe(PerformanceEntryType::EVENT, {.durationThreshold = 80}); - reporter->reportMeasure( - "measure", - timeOrigin, - timeOrigin + HighResDuration::fromMilliseconds(50)); - reporter->reportEvent( - "event1", - timeOrigin, - HighResDuration::fromMilliseconds(100), - timeOrigin, - timeOrigin, - 0); - reporter->reportEvent( - "event2", - timeOrigin, - HighResDuration::fromMilliseconds(40), - timeOrigin, - timeOrigin, - 0); - reporter->reportMark( - "mark1", timeOrigin + HighResDuration::fromMilliseconds(100)); - reporter->reportEvent( - "event3", - timeOrigin, - HighResDuration::fromMilliseconds(60), - timeOrigin, - timeOrigin, - 0); + reporter->reportMeasure("measure", 0, 50); + reporter->reportEvent("event1", 0, 100, 0, 0, 0); + reporter->reportEvent("event2", 0, 40, 0, 0, 0); + reporter->reportMark("mark1", 100); + reporter->reportEvent("event3", 0, 60, 0, 0, 0); const std::vector expected1 = { - PerformanceEventTiming{ - {.name = "event1", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(100)}, - timeOrigin, - timeOrigin, - 0}, - PerformanceEventTiming{ - {.name = "event3", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(60)}, - timeOrigin, - timeOrigin, - 0}, + PerformanceEventTiming{{.name = "event1", .duration = 100}, 0, 0, 0}, + PerformanceEventTiming{{.name = "event3", .duration = 60}, 0, 0, 0}, }; const std::vector expected2 = { - PerformanceEventTiming{ - {.name = "event1", - .startTime = timeOrigin, - .duration = HighResDuration::fromMilliseconds(100)}, - timeOrigin, - timeOrigin, - 0}, + PerformanceEventTiming{{.name = "event1", .duration = 100}, 0, 0, 0}, }; ASSERT_EQ(expected1, observer1->takeRecords()); diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventLogger.h b/packages/react-native/ReactCommon/react/renderer/core/EventLogger.h index 1d7526ec471..4e5d211e463 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventLogger.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventLogger.h @@ -34,7 +34,8 @@ class EventLogger { virtual EventTag onEventStart( std::string_view name, SharedEventTarget target, - std::optional eventStartTimeStamp = std::nullopt) = 0; + std::optional eventStartTimeStamp = + std::nullopt) = 0; /* * Called when event starts getting dispatched (processed by the handlers, if diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawEvent.h b/packages/react-native/ReactCommon/react/renderer/core/RawEvent.h index d78cbd11860..817512e5c75 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawEvent.h +++ b/packages/react-native/ReactCommon/react/renderer/core/RawEvent.h @@ -87,7 +87,7 @@ struct RawEvent { // The client may specify a platform-specific timestamp for the event start // time, for example when MotionEvent was triggered on the Android native // side. - std::optional eventStartTimeStamp = std::nullopt; + std::optional eventStartTimeStamp = std::nullopt; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/EventQueueProcessorTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/EventQueueProcessorTest.cpp index b6ebd6f4905..467689efddb 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/EventQueueProcessorTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/EventQueueProcessorTest.cpp @@ -25,7 +25,7 @@ class MockEventLogger : public EventLogger { EventTag onEventStart( std::string_view /*name*/, SharedEventTarget /*target*/, - std::optional /*eventStartTimeStamp*/) override { + std::optional /*eventStartTimeStamp*/) override { return EMPTY_EVENT_TAG; } void onEventProcessingStart(EventTag /*tag*/) override {} diff --git a/packages/react-native/ReactCommon/react/renderer/observers/events/EventPerformanceLogger.cpp b/packages/react-native/ReactCommon/react/renderer/observers/events/EventPerformanceLogger.cpp index f3665ddddaf..6dc9680b232 100644 --- a/packages/react-native/ReactCommon/react/renderer/observers/events/EventPerformanceLogger.cpp +++ b/packages/react-native/ReactCommon/react/renderer/observers/events/EventPerformanceLogger.cpp @@ -105,7 +105,7 @@ EventPerformanceLogger::EventPerformanceLogger( EventTag EventPerformanceLogger::onEventStart( std::string_view name, SharedEventTarget target, - std::optional eventStartTimeStamp) { + std::optional eventStartTimeStamp) { auto performanceEntryReporter = performanceEntryReporter_.lock(); if (performanceEntryReporter == nullptr) { return EMPTY_EVENT_TAG; @@ -123,7 +123,7 @@ EventTag EventPerformanceLogger::onEventStart( // The event start timestamp may be provided by the caller in order to // specify the platform specific event start time. - HighResTimeStamp timeStamp = eventStartTimeStamp + DOMHighResTimeStamp timeStamp = eventStartTimeStamp ? *eventStartTimeStamp : performanceEntryReporter->getCurrentTimeStamp(); { @@ -213,7 +213,7 @@ void EventPerformanceLogger::dispatchPendingEventTimingEntries( void EventPerformanceLogger::shadowTreeDidMount( const RootShadowNode::Shared& rootShadowNode, - HighResTimeStamp mountTime) noexcept { + double mountTime) noexcept { auto performanceEntryReporter = performanceEntryReporter_.lock(); if (performanceEntryReporter == nullptr) { return; diff --git a/packages/react-native/ReactCommon/react/renderer/observers/events/EventPerformanceLogger.h b/packages/react-native/ReactCommon/react/renderer/observers/events/EventPerformanceLogger.h index 2addb87f1d6..ffa1d01fb79 100644 --- a/packages/react-native/ReactCommon/react/renderer/observers/events/EventPerformanceLogger.h +++ b/packages/react-native/ReactCommon/react/renderer/observers/events/EventPerformanceLogger.h @@ -32,7 +32,7 @@ class EventPerformanceLogger : public EventLogger, EventTag onEventStart( std::string_view name, SharedEventTarget target, - std::optional eventStartTimeStamp = + std::optional eventStartTimeStamp = std::nullopt) override; void onEventProcessingStart(EventTag tag) override; void onEventProcessingEnd(EventTag tag) override; @@ -47,15 +47,15 @@ class EventPerformanceLogger : public EventLogger, void shadowTreeDidMount( const RootShadowNode::Shared& rootShadowNode, - HighResTimeStamp mountTime) noexcept override; + double mountTime) noexcept override; private: struct EventEntry { std::string_view name; SharedEventTarget target{nullptr}; - HighResTimeStamp startTime; - std::optional processingStartTime; - std::optional processingEndTime; + DOMHighResTimeStamp startTime; + std::optional processingStartTime; + std::optional processingEndTime; bool isWaitingForMount{false}; diff --git a/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.cpp b/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.cpp index 3346eb836a8..d2e70b1d061 100644 --- a/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.cpp +++ b/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.cpp @@ -132,7 +132,7 @@ static Float getHighestThresholdCrossed( std::optional IntersectionObserver::updateIntersectionObservation( const RootShadowNode& rootShadowNode, - HighResTimeStamp time) { + double time) { bool hasCustomRoot = observationRootShadowNodeFamily_.has_value(); auto rootAncestors = hasCustomRoot @@ -208,7 +208,7 @@ IntersectionObserver::updateIntersectionObservation( std::optional IntersectionObserver::updateIntersectionObservationForSurfaceUnmount( - HighResTimeStamp time) { + double time) { return setNotIntersectingState(Rect{}, Rect{}, Rect{}, time); } @@ -219,7 +219,7 @@ IntersectionObserver::setIntersectingState( const Rect& intersectionRect, Float threshold, Float rootThreshold, - HighResTimeStamp time) { + double time) { auto newState = IntersectionObserverState::Intersecting(threshold, rootThreshold); @@ -245,7 +245,7 @@ IntersectionObserver::setNotIntersectingState( const Rect& rootBoundingRect, const Rect& targetBoundingRect, const Rect& intersectionRect, - HighResTimeStamp time) { + double time) { if (state_ != IntersectionObserverState::NotIntersecting()) { state_ = IntersectionObserverState::NotIntersecting(); IntersectionObserverEntry entry{ diff --git a/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.h b/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.h index 20815c738c1..89483ec3b53 100644 --- a/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.h +++ b/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.h @@ -25,7 +25,9 @@ struct IntersectionObserverEntry { Rect rootRect; Rect intersectionRect; bool isIntersectingAboveThresholds; - HighResTimeStamp time; + // TODO(T156529385) Define `DOMHighResTimeStamp` as an alias for `double` and + // use it here. + double time; bool sameShadowNodeFamily( const ShadowNodeFamily& otherShadowNodeFamily) const { @@ -47,10 +49,10 @@ class IntersectionObserver { // https://w3c.github.io/IntersectionObserver/#update-intersection-observations-algo std::optional updateIntersectionObservation( const RootShadowNode& rootShadowNode, - HighResTimeStamp time); + double time); std::optional - updateIntersectionObservationForSurfaceUnmount(HighResTimeStamp time); + updateIntersectionObservationForSurfaceUnmount(double time); IntersectionObserverObserverId getIntersectionObserverId() const { return intersectionObserverId_; @@ -71,13 +73,13 @@ class IntersectionObserver { const Rect& intersectionRect, Float threshold, Float rootThreshold, - HighResTimeStamp time); + double time); std::optional setNotIntersectingState( const Rect& rootBoundingRect, const Rect& targetBoundingRect, const Rect& intersectionRect, - HighResTimeStamp time); + double time); IntersectionObserverObserverId intersectionObserverId_; std::optional observationRootShadowNodeFamily_; diff --git a/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.cpp b/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.cpp index 17e9667fdc4..a8eb27afeaf 100644 --- a/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.cpp @@ -283,14 +283,14 @@ void IntersectionObserverManager::updateIntersectionObservations( void IntersectionObserverManager::shadowTreeDidMount( const RootShadowNode::Shared& rootShadowNode, - HighResTimeStamp time) noexcept { + double time) noexcept { updateIntersectionObservations( rootShadowNode->getSurfaceId(), rootShadowNode.get(), time); } void IntersectionObserverManager::shadowTreeDidUnmount( SurfaceId surfaceId, - HighResTimeStamp time) noexcept { + double time) noexcept { updateIntersectionObservations(surfaceId, nullptr, time); } @@ -299,7 +299,7 @@ void IntersectionObserverManager::shadowTreeDidUnmount( void IntersectionObserverManager::updateIntersectionObservations( SurfaceId surfaceId, const RootShadowNode* rootShadowNode, - HighResTimeStamp time) { + double time) { TraceSection s("IntersectionObserverManager::updateIntersectionObservations"); std::vector entries; diff --git a/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.h b/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.h index 27af06df363..8faa627b40a 100644 --- a/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.h +++ b/packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.h @@ -56,10 +56,9 @@ class IntersectionObserverManager final void shadowTreeDidMount( const RootShadowNode::Shared& rootShadowNode, - HighResTimeStamp time) noexcept override; + double time) noexcept override; - void shadowTreeDidUnmount(SurfaceId surfaceId, HighResTimeStamp time) noexcept - override; + void shadowTreeDidUnmount(SurfaceId surfaceId, double time) noexcept override; private: mutable std::unordered_map< @@ -94,7 +93,7 @@ class IntersectionObserverManager final void updateIntersectionObservations( SurfaceId surfaceId, const RootShadowNode* rootShadowNode, - HighResTimeStamp time); + double time); const IntersectionObserver& getRegisteredIntersectionObserver( SurfaceId surfaceId, diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp index fcdb9565edb..10fef3e9831 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp @@ -460,10 +460,12 @@ void RuntimeScheduler_Modern::reportLongTasks( return; } - if (longestPeriodWithoutYieldingOpportunity_ >= - LONG_TASK_DURATION_THRESHOLD) { - auto duration = endTime - startTime; - reporter->reportLongTask(startTime, duration); + auto checkedDurationMs = + longestPeriodWithoutYieldingOpportunity_.toDOMHighResTimeStamp(); + if (checkedDurationMs >= LONG_TASK_DURATION_THRESHOLD_MS) { + auto durationMs = (endTime - startTime).toDOMHighResTimeStamp(); + auto startTimeMs = startTime.toDOMHighResTimeStamp(); + reporter->reportLongTask(startTimeMs, durationMs); } } diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp index 6251b5a552b..0fdff1b072f 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -1258,9 +1257,8 @@ TEST_P(RuntimeSchedulerTest, reportsLongTasks) { [startTime](const auto& entryDetails) { EXPECT_EQ(entryDetails.entryType, PerformanceEntryType::LONGTASK); EXPECT_EQ( - entryDetails.startTime.toDOMHighResTimeStamp(), - startTime.toDOMHighResTimeStamp() + 100); - EXPECT_EQ(entryDetails.duration, HighResDuration::fromMilliseconds(50)); + entryDetails.startTime, startTime.toDOMHighResTimeStamp() + 100); + EXPECT_EQ(entryDetails.duration, 50); }, entry); } @@ -1346,10 +1344,8 @@ TEST_P(RuntimeSchedulerTest, reportsLongTasksWithYielding) { [startTime](const auto& entryDetails) { EXPECT_EQ(entryDetails.entryType, PerformanceEntryType::LONGTASK); EXPECT_EQ( - entryDetails.startTime.toDOMHighResTimeStamp(), - startTime.toDOMHighResTimeStamp() + 100); - EXPECT_EQ( - entryDetails.duration, HighResDuration::fromMilliseconds(120)); + entryDetails.startTime, startTime.toDOMHighResTimeStamp() + 100); + EXPECT_EQ(entryDetails.duration, 120); }, entry); } diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerMountHook.h b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerMountHook.h index 1a014411d85..3e5627b53eb 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerMountHook.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerMountHook.h @@ -26,11 +26,11 @@ class UIManagerMountHook { */ virtual void shadowTreeDidMount( const RootShadowNode::Shared& rootShadowNode, - HighResTimeStamp mountTime) noexcept = 0; + double mountTime) noexcept = 0; virtual void shadowTreeDidUnmount( SurfaceId /*surfaceId*/, - HighResTimeStamp /*unmountTime*/) noexcept { + double /*unmountTime*/) noexcept { // Default no-op implementation for backwards compatibility. } diff --git a/packages/react-native/ReactCommon/react/timing/primitives.h b/packages/react-native/ReactCommon/react/timing/primitives.h index 9c3be8990b8..91e5c33ed57 100644 --- a/packages/react-native/ReactCommon/react/timing/primitives.h +++ b/packages/react-native/ReactCommon/react/timing/primitives.h @@ -11,6 +11,23 @@ namespace facebook::react { +// `DOMHighResTimeStamp` represents a time value in milliseconds (time point or +// duration), with sub-millisecond precision. +// On the Web, the precision can be reduced for security purposes, but that is +// not necessary in React Native. +using DOMHighResTimeStamp = double; + +inline DOMHighResTimeStamp chronoToDOMHighResTimeStamp( + std::chrono::steady_clock::duration duration) { + return static_cast>(duration) + .count(); +} + +inline DOMHighResTimeStamp chronoToDOMHighResTimeStamp( + std::chrono::steady_clock::time_point timePoint) { + return chronoToDOMHighResTimeStamp(timePoint.time_since_epoch()); +} + class HighResDuration; class HighResTimeStamp; diff --git a/packages/react-native/ReactCommon/react/timing/tests/PrimitivesTest.cpp b/packages/react-native/ReactCommon/react/timing/tests/PrimitivesTest.cpp index f94a379c036..be1751c2bff 100644 --- a/packages/react-native/ReactCommon/react/timing/tests/PrimitivesTest.cpp +++ b/packages/react-native/ReactCommon/react/timing/tests/PrimitivesTest.cpp @@ -11,6 +11,39 @@ namespace facebook::react { +using Clock = std::chrono::steady_clock; +using TimePoint = std::chrono::time_point; + +TEST(chronoToDOMHighResTimeStamp, withDurations) { + EXPECT_EQ(chronoToDOMHighResTimeStamp(std::chrono::nanoseconds(10)), 0.00001); + EXPECT_EQ(chronoToDOMHighResTimeStamp(std::chrono::microseconds(10)), 0.01); + EXPECT_EQ(chronoToDOMHighResTimeStamp(std::chrono::milliseconds(10)), 10.0); + EXPECT_EQ(chronoToDOMHighResTimeStamp(std::chrono::seconds(10)), 10000.0); + EXPECT_EQ( + chronoToDOMHighResTimeStamp( + std::chrono::seconds(1) + std::chrono::nanoseconds(20)), + 1000.000020); +} + +TEST(chronoToDOMHighResTimeStamp, withTimePoints) { + EXPECT_EQ( + chronoToDOMHighResTimeStamp(TimePoint(std::chrono::nanoseconds(10))), + 0.00001); + EXPECT_EQ( + chronoToDOMHighResTimeStamp(TimePoint(std::chrono::microseconds(10))), + 0.01); + EXPECT_EQ( + chronoToDOMHighResTimeStamp(TimePoint(std::chrono::milliseconds(10))), + 10.0); + EXPECT_EQ( + chronoToDOMHighResTimeStamp(TimePoint(std::chrono::seconds(10))), + 10000.0); + EXPECT_EQ( + chronoToDOMHighResTimeStamp( + TimePoint(std::chrono::seconds(1) + std::chrono::nanoseconds(20))), + 1000.000020); +} + TEST(HighResDuration, CorrectlyConvertsToDOMHighResTimeStamp) { EXPECT_EQ( HighResDuration::fromNanoseconds(10).toDOMHighResTimeStamp(), 0.00001); diff --git a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/HermesPerfettoDataSource.cpp b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/HermesPerfettoDataSource.cpp index 1ae283d7f50..c51d6a7a778 100644 --- a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/HermesPerfettoDataSource.cpp +++ b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/HermesPerfettoDataSource.cpp @@ -113,7 +113,7 @@ void HermesPerfettoDataSource::OnStart(const StartArgs&) { "react-native", perfetto::DynamicString{"Profiling Started"}, getPerfettoWebPerfTrackSync("JS Sampling"), - perfetto::TrackEvent::GetTraceTimeNs()); + performanceNowToPerfettoTraceTime(0)); } void HermesPerfettoDataSource::OnFlush(const FlushArgs&) { diff --git a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.cpp b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.cpp index c280ad4ca08..a0786d4c649 100644 --- a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.cpp +++ b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.cpp @@ -80,17 +80,13 @@ perfetto::Track getPerfettoWebPerfTrackAsync(const std::string& trackName) { } // Perfetto's monotonic clock seems to match the std::chrono::steady_clock we -// use in HighResTimeStamp on Android platforms, but if that +// use in JSExecutor::performanceNow on Android platforms, but if that // assumption is incorrect we may need to manually offset perfetto timestamps. -uint64_t highResTimeStampToPerfettoTraceTime(HighResTimeStamp timestamp) { - auto chronoDurationSinceSteadyClockEpoch = - timestamp.toChronoSteadyClockTimePoint().time_since_epoch(); - auto nanoseconds = std::chrono::duration_cast( - chronoDurationSinceSteadyClockEpoch); - - return std::chrono::duration_cast>( - nanoseconds) - .count(); +uint64_t performanceNowToPerfettoTraceTime(double perfNowTime) { + if (perfNowTime == 0) { + return perfetto::TrackEvent::GetTraceTimeNs(); + } + return static_cast(perfNowTime * 1.e6); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.h b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.h index c46ff051c53..c01ac604c89 100644 --- a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.h +++ b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.h @@ -10,7 +10,6 @@ #ifdef WITH_PERFETTO #include -#include #include #include @@ -21,7 +20,7 @@ void initializePerfetto(); perfetto::Track getPerfettoWebPerfTrackSync(const std::string& trackName); perfetto::Track getPerfettoWebPerfTrackAsync(const std::string& trackName); -uint64_t highResTimeStampToPerfettoTraceTime(HighResTimeStamp timestamp); +uint64_t performanceNowToPerfettoTraceTime(double perfNowTime); } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfettoLogger.cpp b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfettoLogger.cpp index d021a912d49..c895334b7c5 100644 --- a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfettoLogger.cpp +++ b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfettoLogger.cpp @@ -13,6 +13,8 @@ #include #endif +#include + namespace facebook::react { namespace { @@ -28,9 +30,10 @@ std::string toPerfettoTrackName( : PERFETTO_DEFAULT_TRACK_NAME; } #elif defined(WITH_FBSYSTRACE) -int64_t getDeltaNanos(HighResTimeStamp jsTime) { - auto now = HighResTimeStamp::now(); - return (jsTime - now).toNanoseconds(); +int64_t getDeltaNanos(double jsTime) { + auto now = std::chrono::steady_clock::now().time_since_epoch(); + return static_cast(jsTime * 1.e6) - + std::chrono::duration_cast(now).count(); } #endif @@ -48,8 +51,8 @@ int64_t getDeltaNanos(HighResTimeStamp jsTime) { /* static */ void ReactPerfettoLogger::measure( const std::string_view& eventName, - HighResTimeStamp startTime, - HighResTimeStamp endTime, + double startTime, + double endTime, const std::optional& trackName) { #if defined(WITH_PERFETTO) if (TRACE_EVENT_CATEGORY_ENABLED("react-native")) { @@ -58,9 +61,9 @@ int64_t getDeltaNanos(HighResTimeStamp jsTime) { "react-native", perfetto::DynamicString(eventName.data(), eventName.size()), track, - highResTimeStampToPerfettoTraceTime(startTime)); + performanceNowToPerfettoTraceTime(startTime)); TRACE_EVENT_END( - "react-native", track, highResTimeStampToPerfettoTraceTime(endTime)); + "react-native", track, performanceNowToPerfettoTraceTime(endTime)); } #elif defined(WITH_FBSYSTRACE) static int cookie = 0; @@ -74,7 +77,7 @@ int64_t getDeltaNanos(HighResTimeStamp jsTime) { /* static */ void ReactPerfettoLogger::mark( const std::string_view& eventName, - HighResTimeStamp startTime, + double startTime, const std::optional& trackName) { #if defined(WITH_PERFETTO) if (TRACE_EVENT_CATEGORY_ENABLED("react-native")) { @@ -82,7 +85,7 @@ int64_t getDeltaNanos(HighResTimeStamp jsTime) { "react-native", perfetto::DynamicString(eventName.data(), eventName.size()), getPerfettoWebPerfTrackSync(toPerfettoTrackName(trackName)), - highResTimeStampToPerfettoTraceTime(startTime)); + performanceNowToPerfettoTraceTime(startTime)); } #elif defined(WITH_FBSYSTRACE) static const char* kTrackName = "# Web Performance: Markers"; diff --git a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfettoLogger.h b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfettoLogger.h index 7206d679fab..a85d06a5b39 100644 --- a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfettoLogger.h +++ b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfettoLogger.h @@ -7,7 +7,6 @@ #pragma once -#include #include #include @@ -25,13 +24,13 @@ class ReactPerfettoLogger { static void mark( const std::string_view& eventName, - HighResTimeStamp startTime, + double startTime, const std::optional& trackName); static void measure( const std::string_view& eventName, - HighResTimeStamp startTime, - HighResTimeStamp endTime, + double startTime, + double endTime, const std::optional& trackName); };