From 8082ad6be423b0867a81aab4612afb95dc935553 Mon Sep 17 00:00:00 2001 From: Ldoppea Date: Wed, 20 Nov 2024 16:38:48 +0100 Subject: [PATCH 01/11] feat: Add react-native-performance module ReactNative only support a subset of the web's Performance API In order to measure our code performance, we want to use `performance.mark()` and `performance.measure()` methods that are not natively supported by ReactNative `react-native-performance` plugin provide those methods and also allow to se results in realtime thanks to `react-native-performance-flipper-reporter` plugin --- ios/Podfile.lock | 6 ++++++ package.json | 2 ++ yarn.lock | 10 ++++++++++ 3 files changed, 18 insertions(+) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 98844af1a..04ff4eb3d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1093,6 +1093,8 @@ PODS: - React - react-native-netinfo (9.5.0): - React-Core + - react-native-performance (5.1.2): + - React-Core - react-native-print (0.11.0): - React-Core - react-native-quick-base64 (2.1.2): @@ -1425,6 +1427,7 @@ DEPENDENCIES: - react-native-mail (from `../node_modules/react-native-mail`) - react-native-mlkit-ocr (from `../node_modules/react-native-mlkit-ocr`) - "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)" + - react-native-performance (from `../node_modules/react-native-performance`) - react-native-print (from `../node_modules/react-native-print`) - react-native-quick-base64 (from `../node_modules/react-native-quick-base64`) - react-native-quick-sqlite (from `../node_modules/react-native-quick-sqlite`) @@ -1604,6 +1607,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-mlkit-ocr" react-native-netinfo: :path: "../node_modules/@react-native-community/netinfo" + react-native-performance: + :path: "../node_modules/react-native-performance" react-native-print: :path: "../node_modules/react-native-print" react-native-quick-base64: @@ -1788,6 +1793,7 @@ SPEC CHECKSUMS: react-native-mail: 8fdcd3aef007c33a6877a18eb4cf7447a1d4ce4a react-native-mlkit-ocr: 72cdbde86f8d29cba26cf9fa0a1865fe45c8f8d6 react-native-netinfo: 48c5f79a84fbc3ba1d28a8b0d04adeda72885fa8 + react-native-performance: ff93f8af3b2ee9519fd7879896aa9b8b8272691d react-native-print: f704aef52d931bfce6d1d84351dbb5232d7ecb89 react-native-quick-base64: e1ea036b3dec44c6da2439bd62881a09de614b23 react-native-quick-sqlite: e0e23b749382a85e4b57146f753de737a6c3a9e1 diff --git a/package.json b/package.json index 316d315ed..7944f4fa9 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,8 @@ "react-native-mail": "^6.1.1", "react-native-mask-input": "1.2.1", "react-native-mlkit-ocr": "^0.3.0", + "react-native-performance": "^5.1.2", + "react-native-performance-flipper-reporter": "^5.0.0", "react-native-permissions": "^3.9.3", "react-native-play-install-referrer": "^1.1.8", "react-native-print": "0.11.0", diff --git a/yarn.lock b/yarn.lock index 0efb681f0..07fe127c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17712,6 +17712,16 @@ react-native-modal-selector@^2.1.1: dependencies: prop-types "^15.5.10" +react-native-performance-flipper-reporter@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/react-native-performance-flipper-reporter/-/react-native-performance-flipper-reporter-5.0.0.tgz#a0f33863e9ce99a848ca5033cb5cf53f0d9e0048" + integrity sha512-nlr1tI3C3kBpraCUw5TLdf++Brdf/eahg5be/70kAS3p10/A6zIiGf/4qDhrsWZyZh2YKzAiCfa8XsJeprP3QA== + +react-native-performance@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/react-native-performance/-/react-native-performance-5.1.2.tgz#5d9e3720e1db26a2c0d2982e5746483c1f9d36db" + integrity sha512-l5JOJphNzox9a9icL3T6O/gEqZuqWqcbejW04WPa10m0UanBdIYrNkPFl48B3ivWw3MabpjB6GiDYv7old9/fw== + react-native-permissions@^3.9.3: version "3.9.3" resolved "https://registry.yarnpkg.com/react-native-permissions/-/react-native-permissions-3.9.3.tgz#b12b118634437784205b5fd56c2a7edd69707314" From 7b0f40c159a38c652fe02fc3d32072e10d303ae3 Mon Sep 17 00:00:00 2001 From: Ldoppea Date: Thu, 26 Sep 2024 09:17:42 +0200 Subject: [PATCH 02/11] feat: Add performance measurements As we encounter some performances issues in the app startup, we want to add some metrics to understand where time is consumed All measurement are made through the `measure.ts` helper that wraps the `react-native-performance` library and fit the incoming CozyClient performance API Related PR: cozy/cozy-client#1574 --- __mocks__/react-native-performance-mock.ts | 10 ++ __tests__/jestSetupFile.js | 2 + src/App.js | 92 +++++++++++++++---- src/app/domain/performances/measure.ts | 39 ++++++++ src/app/theme/SplashScreenService.ts | 3 + .../webviews/CozyProxyWebView.functions.js | 18 ++++ .../webviews/CryptoWebView/CryptoWebView.js | 7 ++ src/hooks/useAppBootstrap.js | 26 ++++++ src/libs/client.js | 3 + src/libs/functions/session.ts | 10 ++ src/libs/httpserver/httpServerProvider.tsx | 23 +++++ src/libs/httpserver/indexGenerator.ts | 3 + src/libs/intents/flagshipLink.ts | 22 +++++ src/libs/localStore/storage.ts | 12 +++ src/screens/home/components/HomeView.js | 31 +++++++ 15 files changed, 285 insertions(+), 16 deletions(-) create mode 100644 __mocks__/react-native-performance-mock.ts create mode 100644 src/app/domain/performances/measure.ts diff --git a/__mocks__/react-native-performance-mock.ts b/__mocks__/react-native-performance-mock.ts new file mode 100644 index 000000000..9e8a15798 --- /dev/null +++ b/__mocks__/react-native-performance-mock.ts @@ -0,0 +1,10 @@ +import RNPerformance from 'react-native-performance' + +export const mockRNPerformance: jest.Mocked = { + mark: jest.fn(), + measure: jest.fn(), + default: { + mark: jest.fn(), + measure: jest.fn(), + } +} as unknown as jest.Mocked diff --git a/__tests__/jestSetupFile.js b/__tests__/jestSetupFile.js index e4c199a33..56cbf5c54 100644 --- a/__tests__/jestSetupFile.js +++ b/__tests__/jestSetupFile.js @@ -13,6 +13,7 @@ import { mockRNBackgroundGeolocation } from '../__mocks__/react-native-backgroun import { mockRNFS } from '../__mocks__/react-native-fs-mock' import { mockRNIAP } from '../__mocks__/react-native-iap-mock' import { mockRNInAppBrowser } from '../__mocks__/react-native-inappbrowser-reborn-mock' +import { mockRNPerformance } from '../__mocks__/react-native-performance-mock' jest.mock('react-native-device-info', () => mockRNDeviceInfo) @@ -29,6 +30,7 @@ jest.mock('@sentry/react-native', () => ({ jest.mock('react-native-fs', () => mockRNFS) jest.mock('react-native-iap', () => mockRNIAP) jest.mock('react-native-inappbrowser-reborn', () => mockRNInAppBrowser) +jest.mock('react-native-performance', () => mockRNPerformance) jest.mock('react-native-ios11-devicecheck', () => ({ getToken: jest.fn() })) diff --git a/src/App.js b/src/App.js index c9abf579b..549de2f2c 100644 --- a/src/App.js +++ b/src/App.js @@ -2,6 +2,7 @@ import { NavigationContainer } from '@react-navigation/native' import { decode, encode } from 'base-64' import React, { useEffect, useState } from 'react' import { StatusBar, StyleSheet, View } from 'react-native' + import { SafeAreaProvider } from 'react-native-safe-area-context' import { Provider } from 'react-redux' import { PersistGate } from 'redux-persist/integration/react' @@ -10,6 +11,9 @@ import FlipperAsyncStorage from 'rn-flipper-async-storage-advanced' import { CozyProvider, useClient } from 'cozy-client' import { NativeIntentProvider } from 'cozy-intent' +import rnperformance, { + configurePerformances +} from '/app/domain/performances/measure' import { RootNavigator } from '/AppRouter' import * as RootNavigation from '/libs/RootNavigation' import NetStatusBoundary from '/libs/services/NetStatusBoundary' @@ -67,8 +71,16 @@ import { useDimensions } from '/libs/dimensions' import { configureFileLogger } from '/app/domain/logger/fileLogger' import { useColorScheme } from '/app/theme/colorScheme' +if (__DEV__) { + require('react-native-performance-flipper-reporter').setupDefaultFlipperReporter() +} + +configurePerformances() configureFileLogger() +const markStartName = rnperformance.mark('AppStart') +rnperformance.measure({ markName: markStartName }) + // Polyfill needed for cozy-client connection if (!global.btoa) { global.btoa = encode @@ -86,6 +98,7 @@ const LoggedInWrapper = ({ children }) => { // eslint-disable-next-line react/display-name const App = ({ setClient }) => { + const [markNameApp] = useState(() => rnperformance.mark('App')) const client = useClient() useSynchronizeOnInit() @@ -122,6 +135,22 @@ const App = ({ setClient }) => { makeImportantFilesAvailableOfflineInBackground(client) }, [client]) + useEffect(() => { + if (!isLoading) { + rnperformance.measure({ + markName: markNameApp, + measureName: 'useAppBootstrap' + }) + } + }, [isLoading, markNameApp]) + + useEffect(() => { + rnperformance.measure({ + markName: markNameApp, + measureName: 'Mount ' + }) + }, [markNameApp]) + if (isLoading) { return null } @@ -145,12 +174,20 @@ const App = ({ setClient }) => { } const InnerNav = ({ client, setClient }) => { + const [markNameInnerNav] = useState(() => rnperformance.mark('InnerNav')) useDimensions() const colors = getColors() const osReceiveState = useOsReceiveState() const osReceiveDispatch = useOsReceiveDispatch() const { shareFiles } = useShareFiles() + useEffect(() => { + rnperformance.measure({ + markName: markNameInnerNav, + measureName: 'Mount ' + }) + }, [markNameInnerNav]) + return ( { ) } -const Nav = ({ client, setClient }) => ( - - - - - - - - - - {client && } - - - -) +const Nav = ({ client, setClient }) => { + const [markNameNav] = useState(() => rnperformance.mark('Nav')) + useEffect(() => { + rnperformance.measure({ + markName: markNameNav, + measureName: 'Mount