From a9b6a97bb4ddecb7d8ba4fc8262f08b78f15fed0 Mon Sep 17 00:00:00 2001 From: Elvira Burchik Date: Tue, 14 Jun 2022 09:34:43 +0200 Subject: [PATCH] feat: allow using multiple performance profilers (#76) * feat: use instance level onRenderComplete callbacks instead of one global listener * update Android native to send instance-events instead of global * update onRenderComplete callback's usage * clean up * add an example with nested Profiler to fixture app * update after PR comments: - set LogLevel Debug for a global profiler - add a note about not using NestedContextScreen as an example --- fixture/build.gradle | 3 +- fixture/src/App.tsx | 17 +++ fixture/src/constants.ts | 3 + fixture/src/examples/ExamplesScreen.tsx | 26 ++-- fixture/src/examples/NestedContextScreen.tsx | 54 ++++++++ .../PerformanceMarker.kt | 35 ++++-- .../RenderCompletionEventEmitter.kt | 27 ---- .../PerformanceMarker.swift | 28 +++-- .../PerformanceMarkerManager.m | 1 + .../RenderCompletionEventEmitter.m | 5 - .../RenderCompletionEventEmitter.swift | 49 -------- .../src/PerformanceMarker.tsx | 13 ++ .../src/PerformanceMeasureView.tsx | 20 ++- .../__tests__/PerformanceMeasureView.test.tsx | 35 ++++++ .../context/PerformanceProfiler.test.tsx | 18 --- .../useNativeRenderCompletionEvents.test.tsx | 117 ------------------ .../src/context/PerformanceProfiler.tsx | 3 - .../useNativeRenderCompletionEvents.ts | 42 ------- 18 files changed, 207 insertions(+), 289 deletions(-) create mode 100644 fixture/src/examples/NestedContextScreen.tsx delete mode 100644 packages/react-native-performance/android/src/main/kotlin/com/shopify/reactnativeperformance/RenderCompletionEventEmitter.kt delete mode 100644 packages/react-native-performance/ios/ReactNativePerformance/RenderCompletionEventEmitter.m delete mode 100644 packages/react-native-performance/ios/ReactNativePerformance/RenderCompletionEventEmitter.swift delete mode 100644 packages/react-native-performance/src/__tests__/context/useNativeRenderCompletionEvents.test.tsx delete mode 100644 packages/react-native-performance/src/context/useNativeRenderCompletionEvents.ts diff --git a/fixture/build.gradle b/fixture/build.gradle index c5672b5..f554338 100644 --- a/fixture/build.gradle +++ b/fixture/build.gradle @@ -13,7 +13,7 @@ buildscript { } repositories { google() - jcenter() + mavenCentral() maven { url "https://plugins.gradle.org/m2/" } @@ -45,6 +45,7 @@ allprojects { } } google() + mavenCentral() maven { url 'https://www.jitpack.io' } } diff --git a/fixture/src/App.tsx b/fixture/src/App.tsx index 987f269..7325019 100644 --- a/fixture/src/App.tsx +++ b/fixture/src/App.tsx @@ -14,6 +14,7 @@ import FastRenderPassesScreen from './examples/FastRenderPassesScreen'; import ConditionalRenderingScreen from './examples/ConditionalRenderingScreen'; import DrawerNavigator from './examples/DrawerNavigator'; import NestedNavigationScreen from './examples/NestedNavigationScreen'; +import NestedContextScreen, {InnerNestedContextScreen} from './examples/NestedContextScreen'; const Stack = createStackNavigator(); @@ -29,11 +30,27 @@ const NavigationTree = () => { + ); }; +function NestedProfilerNavigationTree() { + return ( + + + + + + + ); +} + const App = () => { const apolloClient = useMemo(() => { return new ApolloClient({ diff --git a/fixture/src/constants.ts b/fixture/src/constants.ts index 17becb0..79fdb02 100644 --- a/fixture/src/constants.ts +++ b/fixture/src/constants.ts @@ -11,6 +11,9 @@ export const NavigationKeys = { DRAWER_NAVIGATOR_SCREEN_2: 'DrawerNavigatorScreen2' as const, FLAT_LIST_SCREEN: 'FlatListScreen' as const, NESTED_NAVIGATION_SCREEN: 'NestedNavigationScreen' as const, + NESTED_PROFILER_CONTEXT: 'NestedProfilerContext' as const, + NESTED_CONTEXT_SCREEN: 'NestedContextScreen' as const, + INNER_NESTED_CONTEXT_SCREEN: 'InnerNestedContextScreen' as const, }; type ValueOf = T[keyof T]; diff --git a/fixture/src/examples/ExamplesScreen.tsx b/fixture/src/examples/ExamplesScreen.tsx index 0898883..b06448f 100644 --- a/fixture/src/examples/ExamplesScreen.tsx +++ b/fixture/src/examples/ExamplesScreen.tsx @@ -2,11 +2,13 @@ import React from 'react'; import {StatusBar, StyleSheet, FlatList, Text, TouchableOpacity, Image} from 'react-native'; import {ReactNavigationPerformanceView, useProfiledNavigation} from '@shopify/react-native-performance-navigation'; import {StackNavigationProp} from '@react-navigation/stack'; +import {useNavigation} from '@react-navigation/native'; import {NavigationKeys, RootStackParamList} from '../constants'; export const ExamplesScreen = () => { const {navigate} = useProfiledNavigation>(); + const navigation = useNavigation>(); const renderTimeoutMillisOverride = (screenName: string) => { return screenName === NavigationKeys.PERFORMANCE ? 6 * 1000 : undefined; @@ -40,19 +42,27 @@ export const ExamplesScreen = () => { title: 'FlatList Screen', destination: NavigationKeys.FLAT_LIST_SCREEN, }, + { + title: 'Nested Context Screen', + destination: NavigationKeys.NESTED_PROFILER_CONTEXT, + }, ]} renderItem={({item}) => ( { - navigate( - { - source: NavigationKeys.EXAMPLES, - uiEvent, - renderTimeoutMillisOverride: renderTimeoutMillisOverride(item.destination), - }, - item.destination, - ); + if (item.destination === NavigationKeys.NESTED_PROFILER_CONTEXT) { + navigation.navigate(item.destination); + } else { + navigate( + { + source: NavigationKeys.EXAMPLES, + uiEvent, + renderTimeoutMillisOverride: renderTimeoutMillisOverride(item.destination), + }, + item.destination, + ); + } }} > {item.title} diff --git a/fixture/src/examples/NestedContextScreen.tsx b/fixture/src/examples/NestedContextScreen.tsx new file mode 100644 index 0000000..9d7bd4e --- /dev/null +++ b/fixture/src/examples/NestedContextScreen.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import {ReactNavigationPerformanceView, useProfiledNavigation} from '@shopify/react-native-performance-navigation'; +import {Button, Text, View, StyleSheet} from 'react-native'; +import {StackNavigationProp} from '@react-navigation/stack'; +import {PerformanceProfiler, LogLevel} from '@shopify/react-native-performance'; + +import {NavigationKeys, RootStackParamList} from '../constants'; + +/** + * NOTE: This screen shouldn't be used as an example since we don't generally recommend mixing multiple profilers. + * Nested profilers only make sense when transitioning between JS and native layers in a hybrid use case. + * For example, in brown-field apps, gradually adopting React Native. + * Please stick with only profiler per App if there is no serious matter to do otherwise. + */ + +const NestedContextScreen = () => { + const {navigate} = useProfiledNavigation>(); + + return ( + + +