From 2690e7363ce9b1a48eccb49bdae31a1c8ae27b89 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 4 Nov 2019 18:19:05 -0800 Subject: [PATCH] Fabric: Cross-platform implementation of `monotonicTimeInMilliseconds` Summary: Now the function supports iOS. We will use it soon. Changelog: [Internal] Fabric-specific internal change. Reviewed By: mdvacca Differential Revision: D18285828 fbshipit-source-id: b9c16433e9c75ab4c071e4bd55074757372f6c0a --- .../com/facebook/react/fabric/jni/Binding.cpp | 4 +- .../fabric/mounting/MountingTelemetry.cpp | 12 ++--- ReactCommon/utils/TimeUtils.h | 51 ++++++++++++++++--- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp index 5dfcd760eb3..b6638a439a8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp @@ -555,7 +555,7 @@ void Binding::schedulerDidFinishTransaction( std::lock_guard lock(commitMutex_); SystraceSection s("FabricUIManagerBinding::schedulerDidFinishTransaction"); - long finishTransactionStartTime = getTime(); + long finishTransactionStartTime = monotonicTimeInMilliseconds(); jni::global_ref localJavaUIManager = getJavaUIManager(); if (!localJavaUIManager) { @@ -784,7 +784,7 @@ void Binding::schedulerDidFinishTransaction( ->getMethod( "scheduleMountItem"); - long finishTransactionEndTime = getTime(); + long finishTransactionEndTime = monotonicTimeInMilliseconds(); scheduleMountItem( localJavaUIManager, diff --git a/ReactCommon/fabric/mounting/MountingTelemetry.cpp b/ReactCommon/fabric/mounting/MountingTelemetry.cpp index 0910d685e16..f96e4b1d292 100644 --- a/ReactCommon/fabric/mounting/MountingTelemetry.cpp +++ b/ReactCommon/fabric/mounting/MountingTelemetry.cpp @@ -17,38 +17,38 @@ namespace react { void MountingTelemetry::willCommit() { assert(commitStartTime_ == kUndefinedTime); assert(commitEndTime_ == kUndefinedTime); - commitStartTime_ = getTime(); + commitStartTime_ = monotonicTimeInMilliseconds(); commitNumber_++; } void MountingTelemetry::didCommit() { assert(commitStartTime_ != kUndefinedTime); assert(commitEndTime_ == kUndefinedTime); - commitEndTime_ = getTime(); + commitEndTime_ = monotonicTimeInMilliseconds(); } void MountingTelemetry::willDiff() { assert(diffStartTime_ == kUndefinedTime); assert(diffEndTime_ == kUndefinedTime); - diffStartTime_ = getTime(); + diffStartTime_ = monotonicTimeInMilliseconds(); } void MountingTelemetry::didDiff() { assert(diffStartTime_ != kUndefinedTime); assert(diffEndTime_ == kUndefinedTime); - diffEndTime_ = getTime(); + diffEndTime_ = monotonicTimeInMilliseconds(); } void MountingTelemetry::willLayout() { assert(layoutStartTime_ == kUndefinedTime); assert(layoutEndTime_ == kUndefinedTime); - layoutStartTime_ = getTime(); + layoutStartTime_ = monotonicTimeInMilliseconds(); } void MountingTelemetry::didLayout() { assert(layoutStartTime_ != kUndefinedTime); assert(layoutEndTime_ == kUndefinedTime); - layoutEndTime_ = getTime(); + layoutEndTime_ = monotonicTimeInMilliseconds(); } int64_t MountingTelemetry::getDiffStartTime() const { diff --git a/ReactCommon/utils/TimeUtils.h b/ReactCommon/utils/TimeUtils.h index eaf295da95d..91e6e5ae151 100644 --- a/ReactCommon/utils/TimeUtils.h +++ b/ReactCommon/utils/TimeUtils.h @@ -7,15 +7,44 @@ #pragma once +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) + +// It's Unix #include +#include + +#endif + +#if defined(__APPLE__) && defined(__MACH__) + +// It's iOS or macOS or one of derivatives. +#include +#include +#include + +#endif namespace facebook { namespace react { -inline static int64_t getTime() { -#ifdef ANDROID - static const int64_t NANOSECONDS_IN_SECOND = 1000000000LL; - static const int64_t NANOSECONDS_IN_MILLISECOND = 1000000LL; +inline static int64_t monotonicTimeInMilliseconds() { +#if defined(__APPLE__) && defined(__MACH__) + + static struct mach_timebase_info tb_info = {0}; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + __unused int ret = mach_timebase_info(&tb_info); + assert(0 == ret); + }); + + return (mach_absolute_time() * tb_info.numer) / tb_info.denom / 1000000; + +#elif defined(_POSIX_MONOTONIC_CLOCK) + + // It's Unix with MONOTONIC_CLOCK support (e.g. Android) + + constexpr static int64_t NANOSECONDS_IN_SECOND = 1000000000LL; + constexpr static int64_t NANOSECONDS_IN_MILLISECOND = 1000000LL; // Since SystemClock.uptimeMillis() is commonly used for performance // measurement in Java and uptimeMillis() internally uses @@ -25,11 +54,19 @@ inline static int64_t getTime() { // https://android.googlesource.com/platform/frameworks/native/+/jb-mr1-release/libs/utils/SystemClock.cpp // https://android.googlesource.com/platform/system/core/+/master/libutils/Timers.cpp struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); - int64_t nano = now.tv_sec * NANOSECONDS_IN_SECOND + now.tv_nsec; - return nano / NANOSECONDS_IN_MILLISECOND; + + return (now.tv_sec * NANOSECONDS_IN_SECOND + now.tv_nsec) / + NANOSECONDS_IN_MILLISECOND; + #else - return 0l; + + It's Unix *without* MONOTONIC_CLOCK support or Microsoft Windows. + If you run this on Microsoft Windows, could you please implement the + function using some Windows-specific APIs, and submit a PR? + https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows + #endif }