From 0486640571c89a0ce067c0437655a6b375308bcd Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 13 May 2020 20:24:37 -0700 Subject: [PATCH] Introduce NativeModulePerfLogger Summary: ## Description This diff introduces `NativeModulePerfLogger`, its BUCK, Cocoapod, android-ndk targets. This diff also wires up those targets into the React Native bridge and TurboModules targets, so that we get signal on if the code compiles. This diff also introduces `TurboModulePerfLogger`, which is a namespace that holds the `NativeModulePerfLogger` that'll do perf-logging for TurboModules. ## How will perflogging work on iOS? 1. Each application will, during React Native initialization, create a NativeModule perf logger. 2. If TurboModules are enabled, we'll call `TurboModulePerfLogger::setInstance(perfLogger)`. If TurboModules are disabled, we'll call `NativeModulePerfLogger::setInstance(perfLogger)`. 3. TurboModules, when they're created and used, will log events via `TurboModulePerfLogger::getInstance()`. NativeModules (i.e: bridge modules), when they're created and used, will log events via the `NativeModulePerfLogger::getInstance()`. > **Note:** The NativeModule system will log events for non-TurboModules as well. Maybe we should log events for only NativeModules that conform to the `TurboModule` interface, when TurboModules are disabled. This'll ensure a fair comparison between the two systems. ## How will perflogging work on Android? Please see the subsequent diff. allow-large-files Changelog: [Both][Added] - Introduce `NativeModulePerfLogger` Reviewed By: PeteTheHeat Differential Revision: D21318053 fbshipit-source-id: 6ddf5b5a80bdc4076d2dd6588067e2b0ec8c2c6b --- RNTester/Podfile.lock | 27 ++- React-Core.podspec | 1 + .../src/main/jni/react/jni/Android.mk | 1 + ReactCommon/ReactCommon.podspec | 1 + ReactCommon/perflogger/.clang-tidy | 5 + ReactCommon/perflogger/Android.mk | 25 +++ ReactCommon/perflogger/BUCK | 35 ++++ .../perflogger/React-perflogger.podspec | 34 ++++ .../ReactCommon/NativeModulePerfLogger.cpp | 144 +++++++++++++++ .../ReactCommon/NativeModulePerfLogger.h | 165 ++++++++++++++++++ ReactCommon/turbomodule/core/BUCK | 2 + .../core/TurboModulePerfLogger.cpp | 27 +++ .../turbomodule/core/TurboModulePerfLogger.h | 22 +++ scripts/react_native_pods.rb | 1 + 14 files changed, 488 insertions(+), 2 deletions(-) create mode 100644 ReactCommon/perflogger/.clang-tidy create mode 100644 ReactCommon/perflogger/Android.mk create mode 100644 ReactCommon/perflogger/BUCK create mode 100644 ReactCommon/perflogger/React-perflogger.podspec create mode 100644 ReactCommon/perflogger/ReactCommon/NativeModulePerfLogger.cpp create mode 100644 ReactCommon/perflogger/ReactCommon/NativeModulePerfLogger.h create mode 100644 ReactCommon/turbomodule/core/TurboModulePerfLogger.cpp create mode 100644 ReactCommon/turbomodule/core/TurboModulePerfLogger.h diff --git a/RNTester/Podfile.lock b/RNTester/Podfile.lock index f19e86f52a7133..09cde73049f25f 100644 --- a/RNTester/Podfile.lock +++ b/RNTester/Podfile.lock @@ -99,6 +99,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/ARTHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -107,6 +108,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/CoreModulesHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -115,6 +117,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/Default (1000.0.0): - Folly (= 2020.01.13.00) @@ -122,6 +125,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/DevSupport (1000.0.0): - Folly (= 2020.01.13.00) @@ -132,6 +136,7 @@ PODS: - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-jsinspector (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTActionSheetHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -140,6 +145,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTAnimationHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -148,6 +154,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTBlobHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -156,6 +163,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTImageHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -164,6 +172,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTLinkingHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -172,6 +181,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTNetworkHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -180,6 +190,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTPushNotificationHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -188,6 +199,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTSettingsHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -196,6 +208,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTTextHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -204,6 +217,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTVibrationHeaders (1000.0.0): - Folly (= 2020.01.13.00) @@ -212,6 +226,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTWebSocket (1000.0.0): - Folly (= 2020.01.13.00) @@ -220,6 +235,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) + - React-perflogger (= 1000.0.0) - Yoga - React-CoreModules (1000.0.0): - FBReactNativeSpec (= 1000.0.0) @@ -255,6 +271,7 @@ PODS: - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsinspector (1000.0.0) + - React-perflogger (1000.0.0) - React-RCTActionSheet (1000.0.0): - React-Core/RCTActionSheetHeaders (= 1000.0.0) - React-RCTAnimation (1000.0.0): @@ -329,6 +346,7 @@ PODS: - React-Core (= 1000.0.0) - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) + - React-perflogger (= 1000.0.0) - ReactCommon/turbomodule/samples (1000.0.0): - DoubleConversion - Folly (= 2020.01.13.00) @@ -337,6 +355,7 @@ PODS: - React-Core (= 1000.0.0) - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) + - React-perflogger (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) - Yoga (1.14.0) - YogaKit (1.18.1): @@ -380,6 +399,7 @@ DEPENDENCIES: - React-jsi (from `../ReactCommon/jsi`) - React-jsiexecutor (from `../ReactCommon/jsiexecutor`) - React-jsinspector (from `../ReactCommon/jsinspector`) + - React-perflogger (from `../ReactCommon/perflogger`) - React-RCTActionSheet (from `../Libraries/ActionSheetIOS`) - React-RCTAnimation (from `../Libraries/NativeAnimation`) - React-RCTBlob (from `../Libraries/Blob`) @@ -444,6 +464,8 @@ EXTERNAL SOURCES: :path: "../ReactCommon/jsiexecutor" React-jsinspector: :path: "../ReactCommon/jsinspector" + React-perflogger: + :path: "../ReactCommon/perflogger" React-RCTActionSheet: :path: "../Libraries/ActionSheetIOS" React-RCTAnimation: @@ -495,12 +517,13 @@ SPEC CHECKSUMS: React: cafb3c2321f7df55ce90dbf29d513799a79e4418 React-ART: df0460bdff42ef039e28ee3ffd41f50b75644788 React-callinvoker: 0dada022d38b73e6e15b33e2a96476153f79bbf6 - React-Core: 08c69f013e6fd654ea8f9fd84bbd66780a54d886 + React-Core: d85e4563acbfbb6e6be7414a813ad55d05d675df React-CoreModules: d13d148c851af5780f864be74bc2165140923dc7 React-cxxreact: b43a94e679b307660de530a3af872ab4c7d9925d React-jsi: fe94132da767bfc4801968c2a12abae43e9a833e React-jsiexecutor: 55eff40b2e0696e7a979016e321793ec8b28a2ac React-jsinspector: 7fbf9b42b58b02943a0d89b0ba9fff0070f2de98 + React-perflogger: d32d3423e466a825ef2e9934fe9d62b149e5d9f8 React-RCTActionSheet: 51c43beeb74ef41189e87fe9823e53ebf6210359 React-RCTAnimation: 9d09196c641c1ebfef3a4e9ae670bcda5fadb420 React-RCTBlob: 715489626cf44d28ee51e5277a4d559167351696 @@ -513,7 +536,7 @@ SPEC CHECKSUMS: React-RCTText: 6c01963d3e562109f5548262b09b1b2bc260dd60 React-RCTVibration: d42d73dafd9f63cf758656ee743aa80c566798ff React-runtimeexecutor: 60dd6204a13f68a1aa1118870edcc604a791df2b - ReactCommon: 39e00b754f5e1628804fab28f44146d06280f700 + ReactCommon: 511b4a9ea129c129c6dbc982942007d195903a9a Yoga: f7fa200d8c49f97b54c9421079e781fb900b5cae YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/React-Core.podspec b/React-Core.podspec index cf65263fbdd033..35ff5a6ae6f471 100644 --- a/React-Core.podspec +++ b/React-Core.podspec @@ -94,6 +94,7 @@ Pod::Spec.new do |s| s.dependency "Folly", folly_version s.dependency "React-cxxreact", version + s.dependency "React-perflogger", version s.dependency "React-jsi", version s.dependency "React-jsiexecutor", version s.dependency "Yoga" diff --git a/ReactAndroid/src/main/jni/react/jni/Android.mk b/ReactAndroid/src/main/jni/react/jni/Android.mk index dabd4b7c5125c9..8939df56814266 100644 --- a/ReactAndroid/src/main/jni/react/jni/Android.mk +++ b/ReactAndroid/src/main/jni/react/jni/Android.mk @@ -69,6 +69,7 @@ $(call import-module,cxxreact) $(call import-module,jsi) $(call import-module,jsiexecutor) $(call import-module,callinvoker) +$(call import-module,perflogger) $(call import-module,hermes) $(call import-module,runtimeexecutor) diff --git a/ReactCommon/ReactCommon.podspec b/ReactCommon/ReactCommon.podspec index 765ec10e6b887c..b8cd4043acc1f2 100644 --- a/ReactCommon/ReactCommon.podspec +++ b/ReactCommon/ReactCommon.podspec @@ -38,6 +38,7 @@ Pod::Spec.new do |s| s.subspec "turbomodule" do |ss| ss.dependency "React-callinvoker", version + ss.dependency "React-perflogger", version ss.dependency "React-Core", version ss.dependency "React-cxxreact", version ss.dependency "React-jsi", version diff --git a/ReactCommon/perflogger/.clang-tidy b/ReactCommon/perflogger/.clang-tidy new file mode 100644 index 00000000000000..c98fd78ff64baa --- /dev/null +++ b/ReactCommon/perflogger/.clang-tidy @@ -0,0 +1,5 @@ +--- +Checks: '> +clang-diagnostic-*, +' +... diff --git a/ReactCommon/perflogger/Android.mk b/ReactCommon/perflogger/Android.mk new file mode 100644 index 00000000000000..3e33354bf2d696 --- /dev/null +++ b/ReactCommon/perflogger/Android.mk @@ -0,0 +1,25 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +# Header search path for all source files in this module. +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ReactCommon + +# Header search path for modules that depend on this module +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +# Name of this module. +LOCAL_MODULE := perflogger + +# Compile all local c++ files under ./ReactCommon +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/ReactCommon/*.cpp) + +# Build the files in this directory as a shared library +include $(BUILD_STATIC_LIBRARY) diff --git a/ReactCommon/perflogger/BUCK b/ReactCommon/perflogger/BUCK new file mode 100644 index 00000000000000..6618b210ac7373 --- /dev/null +++ b/ReactCommon/perflogger/BUCK @@ -0,0 +1,35 @@ +load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "rn_xplat_cxx_library", "subdir_glob") + +rn_xplat_cxx_library( + name = "perflogger", + srcs = glob(["**/*.cpp"]), + header_namespace = "", + exported_headers = subdir_glob( + [ + ("ReactCommon", "*.h"), + ], + prefix = "ReactCommon", + ), + compiler_flags = [ + "-fexceptions", + "-frtti", + "-std=c++14", + "-Wall", + "-Wno-global-constructors", + ], + fbandroid_labels = [ + "supermodule:android/default/public.react_native.infra", + ], + fbobjc_labels = [ + "supermodule:ios/default/public.react_native.infra", + ], + platforms = (ANDROID, APPLE), + preferred_linkage = "static", + preprocessor_flags = [ + "-DLOG_TAG=\"ReactNative\"", + "-DWITH_FBSYSTRACE=1", + ], + visibility = [ + "PUBLIC", + ], +) diff --git a/ReactCommon/perflogger/React-perflogger.podspec b/ReactCommon/perflogger/React-perflogger.podspec new file mode 100644 index 00000000000000..3f8808229d80ca --- /dev/null +++ b/ReactCommon/perflogger/React-perflogger.podspec @@ -0,0 +1,34 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json"))) +version = package['version'] + +source = { :git => 'https://github.com/facebook/react-native.git' } +if version == '1000.0.0' + # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. + source[:commit] = `git rev-parse HEAD`.strip +else + source[:tag] = "v#{version}" +end + +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' +folly_version = '2020.01.13.00' +boost_compiler_flags = '-Wno-documentation' + +Pod::Spec.new do |s| + s.name = "React-perflogger" + s.version = version + s.summary = "-" # TODO + s.homepage = "https://reactnative.dev/" + s.license = package["license"] + s.author = "Facebook, Inc. and its affiliates" + s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.source = source + s.source_files = "**/*.{cpp,h}" + s.header_dir = "ReactCommon" +end diff --git a/ReactCommon/perflogger/ReactCommon/NativeModulePerfLogger.cpp b/ReactCommon/perflogger/ReactCommon/NativeModulePerfLogger.cpp new file mode 100644 index 00000000000000..ca9e3b1c4c762f --- /dev/null +++ b/ReactCommon/perflogger/ReactCommon/NativeModulePerfLogger.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "NativeModulePerfLogger.h" + +namespace facebook { +namespace react { + +std::shared_ptr NativeModulePerfLogger::s_perfLogger = + nullptr; + +NativeModulePerfLogger &NativeModulePerfLogger::getInstance() { + static std::shared_ptr defaultPerfLogger = + std::make_shared(); + return s_perfLogger ? *s_perfLogger : *defaultPerfLogger; +} +void NativeModulePerfLogger::setInstance( + std::shared_ptr newPerfLogger) { + s_perfLogger = newPerfLogger; +} + +NativeModulePerfLogger::~NativeModulePerfLogger() {} + +void NativeModulePerfLogger::moduleDataCreateStart( + const char *moduleName, + int32_t id) {} +void NativeModulePerfLogger::moduleDataCreateEnd( + const char *moduleName, + int32_t id) {} + +void NativeModulePerfLogger::moduleCreateStart( + const char *moduleName, + int32_t id) {} +void NativeModulePerfLogger::moduleCreateCacheHit( + const char *moduleName, + int32_t id) {} +void NativeModulePerfLogger::moduleCreateConstructStart( + const char *moduleName, + int32_t id) {} +void NativeModulePerfLogger::moduleCreateConstructEnd( + const char *moduleName, + int32_t id) {} +void NativeModulePerfLogger::moduleCreateSetUpStart( + const char *moduleName, + int32_t id) {} +void NativeModulePerfLogger::moduleCreateSetUpEnd( + const char *moduleName, + int32_t id) {} +void NativeModulePerfLogger::moduleCreateEnd( + const char *moduleName, + int32_t id) {} +void NativeModulePerfLogger::moduleCreateFail( + const char *moduleName, + int32_t id) {} + +void NativeModulePerfLogger::moduleJSRequireBeginningStart( + const char *moduleName) {} +void NativeModulePerfLogger::moduleJSRequireBeginningCacheHit( + const char *moduleName) {} +void NativeModulePerfLogger::moduleJSRequireBeginningEnd( + const char *moduleName) {} +void NativeModulePerfLogger::moduleJSRequireBeginningFail( + const char *moduleName) {} + +void NativeModulePerfLogger::moduleJSRequireEndingStart( + const char *moduleName) {} +void NativeModulePerfLogger::moduleJSRequireEndingEnd(const char *moduleName) {} +void NativeModulePerfLogger::moduleJSRequireEndingFail(const char *moduleName) { +} + +void NativeModulePerfLogger::syncMethodCallStart( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::syncMethodCallArgConversionStart( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::syncMethodCallArgConversionEnd( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::syncMethodCallExecutionStart( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::syncMethodCallExecutionEnd( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::syncMethodCallReturnConversionStart( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::syncMethodCallReturnConversionEnd( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::syncMethodCallEnd( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::syncMethodCallFail( + const char *moduleName, + const char *methodName) {} + +void NativeModulePerfLogger::asyncMethodCallStart( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::asyncMethodCallArgConversionStart( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::asyncMethodCallArgConversionEnd( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::asyncMethodCallDispatch( + const char *moduleName, + const char *methodName) {} +void NativeModulePerfLogger::asyncMethodCallEnd( + const char *moduleName, + const char *methodName) {} + +void NativeModulePerfLogger::asyncMethodCallBatchPreprocessStart() {} +void NativeModulePerfLogger::asyncMethodCallBatchPreprocessEnd(int batchSize) {} + +void NativeModulePerfLogger::asyncMethodCallExecutionStart( + const char *moduleName, + const char *methodName, + int32_t id) {} +void NativeModulePerfLogger::asyncMethodCallExecutionArgConversionStart( + const char *moduleName, + const char *methodName, + int32_t id) {} +void NativeModulePerfLogger::asyncMethodCallExecutionArgConversionEnd( + const char *moduleName, + const char *methodName, + int32_t id) {} +void NativeModulePerfLogger::asyncMethodCallExecutionEnd( + const char *moduleName, + const char *methodName, + int32_t id) {} +void NativeModulePerfLogger::asyncMethodCallExecutionFail( + const char *moduleName, + const char *methodName, + int32_t id) {} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/perflogger/ReactCommon/NativeModulePerfLogger.h b/ReactCommon/perflogger/ReactCommon/NativeModulePerfLogger.h new file mode 100644 index 00000000000000..08b04c0165495c --- /dev/null +++ b/ReactCommon/perflogger/ReactCommon/NativeModulePerfLogger.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) Facebook, Inc. and its 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 +#include + +namespace facebook { +namespace react { + +/** + * A platform-agnostic interface to do performance logging on NativeModules and + * TuboModules. + */ +class NativeModulePerfLogger { + private: + static std::shared_ptr s_perfLogger; + + public: + static NativeModulePerfLogger &getInstance(); + static void setInstance(std::shared_ptr perfLogger); + + virtual ~NativeModulePerfLogger(); + + /** + * NativeModule Initialization. + * + * The initialization of two NativeModules can interleave. Therefore, + * performance markers should use the moduleName as a unique key. + */ + + /** + * On iOS: + * - NativeModule initialization is split into two phases, which sometimes + * have a pause in the middle. + * - TurboModule initialization happens all at once. + * + * On Android: + * - NativeModule and TurboModule initialization happens all at once. + * + * These markers are meant for iOS NativeModules: + * - moduleDataCreateStart: very beginning of first phase. + * - moduleDataCreateEnd: after RCTModuleData has been created. + */ + virtual void moduleDataCreateStart(const char *moduleName, int32_t id); + virtual void moduleDataCreateEnd(const char *moduleName, int32_t id); + + /** + * How long does it take to create the platform NativeModule object? + * - moduleCreateStart: start creating platform NativeModule + * - moduleCreateEnd: stop creating platform NativeModule + */ + virtual void moduleCreateStart(const char *moduleName, int32_t id); + virtual void moduleCreateCacheHit(const char *moduleName, int32_t id); + virtual void moduleCreateConstructStart(const char *moduleName, int32_t id); + virtual void moduleCreateConstructEnd(const char *moduleName, int32_t id); + virtual void moduleCreateSetUpStart(const char *moduleName, int32_t id); + virtual void moduleCreateSetUpEnd(const char *moduleName, int32_t id); + virtual void moduleCreateEnd(const char *moduleName, int32_t id); + virtual void moduleCreateFail(const char *moduleName, int32_t id); + + /** + * How long, after starting JS require, does it take to start creating the + * platform NativeModule? + * - moduleJSRequireBeginningStart: start of JS require + * - moduleJSRequireBeginningEnd: start creating platform NativeModule + */ + virtual void moduleJSRequireBeginningStart(const char *moduleName); + virtual void moduleJSRequireBeginningCacheHit(const char *moduleName); + virtual void moduleJSRequireBeginningEnd(const char *moduleName); + virtual void moduleJSRequireBeginningFail(const char *moduleName); + + /** + * How long does it take to return from the JS require after the platform + * NativeModule is created? + * - moduleJSRequireEndingStart: end creating platform NativeModule + * - moduleJSRequireEndingEnd: end of JS require + */ + virtual void moduleJSRequireEndingStart(const char *moduleName); + virtual void moduleJSRequireEndingEnd(const char *moduleName); + virtual void moduleJSRequireEndingFail(const char *moduleName); + + // Sync method calls + virtual void syncMethodCallStart( + const char *moduleName, + const char *methodName); + virtual void syncMethodCallArgConversionStart( + const char *moduleName, + const char *methodName); + virtual void syncMethodCallArgConversionEnd( + const char *moduleName, + const char *methodName); + virtual void syncMethodCallExecutionStart( + const char *moduleName, + const char *methodName); + virtual void syncMethodCallExecutionEnd( + const char *moduleName, + const char *methodName); + virtual void syncMethodCallReturnConversionStart( + const char *moduleName, + const char *methodName); + virtual void syncMethodCallReturnConversionEnd( + const char *moduleName, + const char *methodName); + virtual void syncMethodCallEnd( + const char *moduleName, + const char *methodName); + virtual void syncMethodCallFail( + const char *moduleName, + const char *methodName); + + // Async method calls + virtual void asyncMethodCallStart( + const char *moduleName, + const char *methodName); + virtual void asyncMethodCallArgConversionStart( + const char *moduleName, + const char *methodName); + virtual void asyncMethodCallArgConversionEnd( + const char *moduleName, + const char *methodName); + virtual void asyncMethodCallDispatch( + const char *moduleName, + const char *methodName); + virtual void asyncMethodCallEnd( + const char *moduleName, + const char *methodName); + + /** + * In the NativeModule system, we batch async NativeModule method calls. + * When we execute a batch of NativeModule method calls, we convert the batch + * from a jsi::Value to folly::dynamic to std::vector. This marker + * documents that work. + */ + virtual void asyncMethodCallBatchPreprocessStart(); + virtual void asyncMethodCallBatchPreprocessEnd(int batchSize); + + // Async method call execution + virtual void asyncMethodCallExecutionStart( + const char *moduleName, + const char *methodName, + int32_t id); + virtual void asyncMethodCallExecutionArgConversionStart( + const char *moduleName, + const char *methodName, + int32_t id); + virtual void asyncMethodCallExecutionArgConversionEnd( + const char *moduleName, + const char *methodName, + int32_t id); + virtual void asyncMethodCallExecutionEnd( + const char *moduleName, + const char *methodName, + int32_t id); + virtual void asyncMethodCallExecutionFail( + const char *moduleName, + const char *methodName, + int32_t id); +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/turbomodule/core/BUCK b/ReactCommon/turbomodule/core/BUCK index af7350e7f2ccad..338413ba2a41b5 100644 --- a/ReactCommon/turbomodule/core/BUCK +++ b/ReactCommon/turbomodule/core/BUCK @@ -18,6 +18,7 @@ rn_xplat_cxx_library( "-frtti", "-std=c++14", "-Wall", + "-Wno-global-constructors", ], fbandroid_deps = [ react_native_target("jni/react/jni:jni"), @@ -80,6 +81,7 @@ rn_xplat_cxx_library( react_native_xplat_target("cxxreact:bridge"), react_native_xplat_target("cxxreact:module"), react_native_xplat_target("callinvoker:callinvoker"), + react_native_xplat_target("perflogger:perflogger"), ], exported_deps = [ "//xplat/jsi:jsi", diff --git a/ReactCommon/turbomodule/core/TurboModulePerfLogger.cpp b/ReactCommon/turbomodule/core/TurboModulePerfLogger.cpp new file mode 100644 index 00000000000000..ba9babdb38ca96 --- /dev/null +++ b/ReactCommon/turbomodule/core/TurboModulePerfLogger.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "TurboModulePerfLogger.h" + +namespace facebook { +namespace react { +namespace TurboModulePerfLogger { + +std::shared_ptr g_perfLogger = nullptr; + +NativeModulePerfLogger &getInstance() { + static std::shared_ptr defaultPerfLogger = + std::make_shared(); + return g_perfLogger ? *g_perfLogger : *defaultPerfLogger; +} +void setInstance(std::shared_ptr perfLogger) { + g_perfLogger = perfLogger; +} + +} // namespace TurboModulePerfLogger +} // namespace react +} // namespace facebook diff --git a/ReactCommon/turbomodule/core/TurboModulePerfLogger.h b/ReactCommon/turbomodule/core/TurboModulePerfLogger.h new file mode 100644 index 00000000000000..354734e9447139 --- /dev/null +++ b/ReactCommon/turbomodule/core/TurboModulePerfLogger.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) Facebook, Inc. and its 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 + +#include +#include + +namespace facebook { +namespace react { +namespace TurboModulePerfLogger { + +NativeModulePerfLogger &getInstance(); +void setInstance(std::shared_ptr perfLogger); + +} // namespace TurboModulePerfLogger +} // namespace react +} // namespace facebook diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index d54c09f3406846..6950b6562db432 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -42,6 +42,7 @@ def use_react_native! (options={}) pod 'React-jsinspector', :path => "#{prefix}/ReactCommon/jsinspector" pod 'React-callinvoker', :path => "#{prefix}/ReactCommon/callinvoker" pod 'React-runtimeexecutor', :path => "#{prefix}/ReactCommon/runtimeexecutor" + pod 'React-perflogger', :path => "#{prefix}/ReactCommon/perflogger" pod 'ReactCommon/turbomodule/core', :path => "#{prefix}/ReactCommon" pod 'Yoga', :path => "#{prefix}/ReactCommon/yoga", :modular_headers => true