From dc334a2baf465b7fb88ad2935df2749d56370dcb Mon Sep 17 00:00:00 2001 From: Olivier Payen Date: Fri, 10 Jun 2022 12:52:34 -0700 Subject: [PATCH] Use monotonic clock for performance.now() (#33983) Summary: In https://github.com/facebook/react-native/pull/32695, the `Performance.now()` implementation changed to use unix epoch timestamps instead of a monotonic clock. This is problematic, because it means that performance measurements get skewed if the device clock changes between two measurements. With this change, the clock is now monotonic (and the implementation stays consistent between platforms). More details and repro steps can be found in [this issue](https://github.com/facebook/react-native/issues/33977) Closes https://github.com/facebook/react-native/issues/33977 ## Changelog [General] [Fixed] - Use monotonic clock for performance.now() Pull Request resolved: https://github.com/facebook/react-native/pull/33983 Test Plan: Run on iOS and Android: ``` const now = global.performance.now() console.log(`${Platform.OS}: ${now}`) ``` Reviewed By: JoshuaGross, cipolleschi Differential Revision: D37066999 Pulled By: dmitryrykun fbshipit-source-id: 298547bf39faea1b025c17ff2d2e1a03f929865b --- React/CxxBridge/RCTJSIExecutorRuntimeInstaller.mm | 10 ++++++++-- ReactAndroid/src/main/jni/react/jni/NativeTime.cpp | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/React/CxxBridge/RCTJSIExecutorRuntimeInstaller.mm b/React/CxxBridge/RCTJSIExecutorRuntimeInstaller.mm index f5c82368f31920..da0f919a3f86af 100644 --- a/React/CxxBridge/RCTJSIExecutorRuntimeInstaller.mm +++ b/React/CxxBridge/RCTJSIExecutorRuntimeInstaller.mm @@ -22,8 +22,14 @@ bindNativeLogger(runtime, iosLoggingBinder); PerformanceNow iosPerformanceNowBinder = []() { - auto time = std::chrono::system_clock::now().time_since_epoch(); - return std::chrono::duration_cast(time).count(); + auto time = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast( + time.time_since_epoch()) + .count(); + + constexpr double NANOSECONDS_IN_MILLISECOND = 1000000.0; + + return duration / NANOSECONDS_IN_MILLISECOND; }; bindNativePerformanceNow(runtime, iosPerformanceNowBinder); diff --git a/ReactAndroid/src/main/jni/react/jni/NativeTime.cpp b/ReactAndroid/src/main/jni/react/jni/NativeTime.cpp index a338db11ee36a6..042805ff66da38 100644 --- a/ReactAndroid/src/main/jni/react/jni/NativeTime.cpp +++ b/ReactAndroid/src/main/jni/react/jni/NativeTime.cpp @@ -12,8 +12,14 @@ namespace facebook { namespace react { double reactAndroidNativePerformanceNowHook() { - auto time = std::chrono::system_clock::now().time_since_epoch(); - return std::chrono::duration_cast(time).count(); + auto time = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast( + time.time_since_epoch()) + .count(); + + constexpr double NANOSECONDS_IN_MILLISECOND = 1000000.0; + + return duration / NANOSECONDS_IN_MILLISECOND; } } // namespace react