From 90212e8b3b40d3fad4f8888b4b11b1770f34aca3 Mon Sep 17 00:00:00 2001 From: rory Date: Fri, 20 Feb 2026 15:00:33 -0800 Subject: [PATCH 1/5] Remove Performance.tsx module (replaced by Sentry) The custom Performance module built on react-native-performance has been fully replaced by Sentry spans for telemetry. This removes the module and all its consumers: - Delete src/libs/Performance.tsx, src/libs/Metrics/, and the react-native-performance type declarations - Remove all Performance.markStart/markEnd/withRenderTrace/measureTTI calls from ~20 consumer files - Uninstall the react-native-performance npm package - Remove all dead CONST.TIMING string constants that were only used as performance mark identifiers (keep numeric debounce/delay values) Co-authored-by: Cursor --- package-lock.json | 3 +- package.json | 1 - src/CONST/index.ts | 27 -- .../LHNOptionsList/OptionRowLHN.tsx | 2 - .../MoneyRequestReportPreviewContent.tsx | 2 - .../MoneyRequestReportPreview/index.tsx | 2 - .../Search/SearchAutocompleteList.tsx | 9 - .../Search/SearchRouter/SearchButton.tsx | 2 - src/components/Search/index.tsx | 2 - src/libs/IOUUtils.ts | 2 - src/libs/Metrics/index.native.ts | 9 - src/libs/Metrics/index.ts | 6 - src/libs/Metrics/types.ts | 3 - src/libs/OptionsListUtils/index.ts | 5 - src/libs/Performance.tsx | 267 ------------------ src/libs/SidebarUtils.ts | 4 - src/libs/actions/App.ts | 2 - src/libs/actions/IOU/index.ts | 3 - src/libs/actions/OnyxUpdates.ts | 7 - .../markNavigateAfterExpenseCreateEnd.ts | 2 - src/libs/telemetry/markOpenReportEnd.ts | 11 +- src/libs/telemetry/markSubmitExpenseEnd.ts | 2 - .../ReportActionCompose.tsx | 2 - .../inbox/report/ReportActionItemThread.tsx | 2 - src/pages/inbox/report/ReportActionsView.tsx | 3 +- .../report/comment/TextCommentFragment.tsx | 4 - src/pages/inbox/sidebar/BaseSidebarScreen.tsx | 8 +- .../iou/request/DistanceRequestStartPage.tsx | 2 - src/pages/iou/request/IOURequestStartPage.tsx | 2 - .../step/IOURequestStepConfirmation.tsx | 3 - .../step/IOURequestStepParticipants.tsx | 3 - src/pages/signin/SignInPage.tsx | 5 - src/setup/platformSetup/index.native.ts | 11 +- .../modules/react-native-performance.d.ts | 12 - 34 files changed, 6 insertions(+), 424 deletions(-) delete mode 100644 src/libs/Metrics/index.native.ts delete mode 100644 src/libs/Metrics/index.ts delete mode 100644 src/libs/Metrics/types.ts delete mode 100644 src/libs/Performance.tsx delete mode 100644 src/types/modules/react-native-performance.d.ts diff --git a/package-lock.json b/package-lock.json index bd1d3e9eccb5c..5418df8e83d61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -120,7 +120,6 @@ "react-native-onyx": "3.0.35", "react-native-pager-view": "8.0.0", "react-native-pdf": "7.0.2", - "react-native-performance": "^6.0.0", "react-native-permissions": "^5.4.0", "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#07d60d78d4772d47afd7a744940fc6b6d1881806", "react-native-plaid-link-sdk": "12.5.3", @@ -34256,6 +34255,8 @@ "resolved": "https://registry.npmjs.org/react-native-performance/-/react-native-performance-6.0.0.tgz", "integrity": "sha512-Sca75O8jhqXAnNbqvINnrw248Kv9cIwoGxToD8u2uX+BrkAxxXS+YhClEV5L3JdiOpdNCO1MJ5R9bgs2VkNpFg==", "license": "MIT", + "optional": true, + "peer": true, "peerDependencies": { "react-native": "*" } diff --git a/package.json b/package.json index 58cc0ab954867..54479b3c3c953 100644 --- a/package.json +++ b/package.json @@ -183,7 +183,6 @@ "react-native-onyx": "3.0.35", "react-native-pager-view": "8.0.0", "react-native-pdf": "7.0.2", - "react-native-performance": "^6.0.0", "react-native-permissions": "^5.4.0", "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#07d60d78d4772d47afd7a744940fc6b6d1881806", "react-native-plaid-link-sdk": "12.5.3", diff --git a/src/CONST/index.ts b/src/CONST/index.ts index e8d303b1b8e18..fb3c46b2e8532 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -1717,48 +1717,21 @@ const CONST = { }, }, TIMING: { - GET_ORDERED_REPORT_IDS: 'get_ordered_report_ids', - CALCULATE_MOST_RECENT_LAST_MODIFIED_ACTION: 'calc_most_recent_last_modified_action', - SPLASH_SCREEN: 'splash_screen', - OPEN_SEARCH: 'open_search', - OPEN_REPORT: 'open_report', - OPEN_REPORT_FROM_PREVIEW: 'open_report_from_preview', - OPEN_REPORT_THREAD: 'open_report_thread', - OPEN_REPORT_SEARCH: 'open_report_search', - SIDEBAR_LOADED: 'sidebar_loaded', - LOAD_SEARCH_OPTIONS: 'load_search_options', - SEND_MESSAGE: 'send_message', - SUBMIT_EXPENSE: 'submit_expense', - NAVIGATE_AFTER_EXPENSE_CREATE: 'navigate_after_expense_create', - OPEN_CREATE_EXPENSE: 'open_create_expense', - OPEN_CREATE_EXPENSE_CONTACT: 'open_create_expense_contact', - OPEN_CREATE_EXPENSE_APPROVE: 'open_create_expense_approve', - APPLY_AIRSHIP_UPDATES: 'apply_airship_updates', - APPLY_PUSHER_UPDATES: 'apply_pusher_updates', - APPLY_HTTPS_UPDATES: 'apply_https_updates', - COLD: 'cold', - WARM: 'warm', REPORT_ACTION_ITEM_LAYOUT_DEBOUNCE_TIME: 1500, SHOW_LOADING_SPINNER_DEBOUNCE_TIME: 250, TEST_TOOLS_MODAL_THROTTLE_TIME: 800, TOOLTIP_SENSE: 1000, - TRIE_INITIALIZATION: 'trie_initialization', COMMENT_LENGTH_DEBOUNCE_TIME: 1500, SEARCH_OPTION_LIST_DEBOUNCE_TIME: 300, SUGGESTION_DEBOUNCE_TIME: 100, RESIZE_DEBOUNCE_TIME: 100, UNREAD_UPDATE_DEBOUNCE_TIME: 300, - SEARCH_FILTER_OPTIONS: 'search_filter_options', USE_DEBOUNCED_STATE_DELAY: 300, LIST_SCROLLING_DEBOUNCE_TIME: 200, - PUSHER_PING_PONG: 'pusher_ping_pong', LOCATION_UPDATE_INTERVAL: 5000, PLAY_SOUND_MESSAGE_DEBOUNCE_TIME: 500, NOTIFY_NEW_ACTION_DELAY: 700, SKELETON_ANIMATION_SPEED: 3, - SEARCH_MOST_RECENT_OPTIONS: 'search_most_recent_options', - DEBOUNCE_HANDLE_SEARCH: 'debounce_handle_search', - FAST_SEARCH_TREE_CREATION: 'fast_search_tree_creation', SHOW_HOVER_PREVIEW_DELAY: 270, SHOW_HOVER_PREVIEW_ANIMATION_DURATION: 250, ACTIVITY_INDICATOR_TIMEOUT: 10000, diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index 412f8fdbd6009..2ba32e7f1679b 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -25,7 +25,6 @@ import DomUtils from '@libs/DomUtils'; import {containsCustomEmoji as containsCustomEmojiUtils, containsOnlyCustomEmoji} from '@libs/EmojiUtils'; import FS from '@libs/Fullstory'; import {shouldOptionShowTooltip, shouldUseBoldText} from '@libs/OptionsListUtils'; -import Performance from '@libs/Performance'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import {isAdminRoom, isChatUsedForOnboarding as isChatUsedForOnboardingReportUtils, isConciergeChatReport, isGroupChat, isOneOnOneChat, isSystemChat} from '@libs/ReportUtils'; import {startSpan} from '@libs/telemetry/activeSpans'; @@ -177,7 +176,6 @@ function OptionRowLHN({ const alternateTextFSClass = FS.getChatFSClass(report); const onOptionPress = (event: GestureResponderEvent | KeyboardEvent | undefined) => { - Performance.markStart(CONST.TIMING.OPEN_REPORT); startSpan(`${CONST.TELEMETRY.SPAN_OPEN_REPORT}_${reportID}`, { name: 'OptionRowLHN', op: CONST.TELEMETRY.SPAN_OPEN_REPORT, diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx index 19ae329f23823..b5526d85dcd02 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx @@ -44,7 +44,6 @@ import {convertToDisplayString} from '@libs/CurrencyUtils'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; import {getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportUtils'; import Navigation from '@libs/Navigation/Navigation'; -import Performance from '@libs/Performance'; import {getConnectedIntegration, hasDynamicExternalWorkflow} from '@libs/PolicyUtils'; import {hasPendingDEWSubmit} from '@libs/ReportActionsUtils'; import {getInvoicePayerName} from '@libs/ReportNameUtils'; @@ -553,7 +552,6 @@ function MoneyRequestReportPreviewContent({ if (!iouReportID) { return; } - Performance.markStart(CONST.TIMING.OPEN_REPORT_FROM_PREVIEW); startSpan(`${CONST.TELEMETRY.SPAN_OPEN_REPORT}_${iouReportID}`, { name: 'MoneyRequestReportPreviewContent', op: CONST.TELEMETRY.SPAN_OPEN_REPORT, diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/index.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/index.tsx index 606d702304988..02c8bf2d2c79f 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/index.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/index.tsx @@ -9,7 +9,6 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import useTransactionViolations from '@hooks/useTransactionViolations'; -import Performance from '@libs/Performance'; import {getIOUActionForReportID, isSplitBillAction as isSplitBillActionReportActionsUtils, isTrackExpenseAction as isTrackExpenseActionReportActionsUtils} from '@libs/ReportActionsUtils'; import {isIOUReport} from '@libs/ReportUtils'; import {startSpan} from '@libs/telemetry/activeSpans'; @@ -104,7 +103,6 @@ function MoneyRequestReportPreview({ return; } - Performance.markStart(CONST.TIMING.OPEN_REPORT_FROM_PREVIEW); startSpan(`${CONST.TELEMETRY.SPAN_OPEN_REPORT}_${iouReportID}`, { name: 'MoneyRequestReportPreview', op: CONST.TELEMETRY.SPAN_OPEN_REPORT, diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index 9777e67ee7780..c09dd4c403254 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -29,7 +29,6 @@ import Log from '@libs/Log'; import type {Options, SearchOption} from '@libs/OptionsListUtils'; import {combineOrderingOfReportsAndPersonalDetails, getSearchOptions} from '@libs/OptionsListUtils'; import Parser from '@libs/Parser'; -import Performance from '@libs/Performance'; import {getAllTaxRates, getCleanedTagName, shouldShowPolicy} from '@libs/PolicyUtils'; import {getReportAction} from '@libs/ReportActionsUtils'; import type {OptionData} from '@libs/ReportUtils'; @@ -115,7 +114,6 @@ const defaultListOptions = { }; const setPerformanceTimersEnd = () => { - Performance.markEnd(CONST.TIMING.OPEN_SEARCH); endSpan(CONST.TELEMETRY.SPAN_OPEN_SEARCH_ROUTER); }; @@ -693,7 +691,6 @@ function SearchAutocompleteList({ const actionId = `filter_options_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`; const startTime = Date.now(); - Performance.markStart(CONST.TIMING.SEARCH_FILTER_OPTIONS); Log.info('[CMD_K_DEBUG] Filter options started', false, { actionId, queryLength: autocompleteQueryValue.length, @@ -705,7 +702,6 @@ function SearchAutocompleteList({ try { if (autocompleteQueryValue.trim() === '') { const endTime = Date.now(); - Performance.markEnd(CONST.TIMING.SEARCH_FILTER_OPTIONS); Log.info('[CMD_K_DEBUG] Filter options completed (empty query path)', false, { actionId, duration: endTime - startTime, @@ -727,7 +723,6 @@ function SearchAutocompleteList({ const finalOptions = reportOptions.slice(0, 20); const endTime = Date.now(); - Performance.markEnd(CONST.TIMING.SEARCH_FILTER_OPTIONS); Log.info('[CMD_K_DEBUG] Filter options completed (search path)', false, { actionId, duration: endTime - startTime, @@ -741,7 +736,6 @@ function SearchAutocompleteList({ return finalOptions; } catch (error) { const endTime = Date.now(); - Performance.markEnd(CONST.TIMING.SEARCH_FILTER_OPTIONS); Log.alert('[CMD_K_FREEZE] Filter options failed', { actionId, error: String(error), @@ -767,7 +761,6 @@ function SearchAutocompleteList({ handleSearch(autocompleteQueryWithoutFilters); const endTime = Date.now(); - Performance.markEnd(CONST.TIMING.DEBOUNCE_HANDLE_SEARCH); Log.info('[CMD_K_DEBUG] Debounced search completed', false, { actionId, duration: endTime - startTime, @@ -780,7 +773,6 @@ function SearchAutocompleteList({ const actionId = `debounce_search_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`; const startTime = Date.now(); - Performance.markStart(CONST.TIMING.DEBOUNCE_HANDLE_SEARCH); Log.info('[CMD_K_DEBUG] Debounced search started', false, { actionId, queryLength: autocompleteQueryWithoutFilters?.length ?? 0, @@ -792,7 +784,6 @@ function SearchAutocompleteList({ handleDebouncedSearch(actionId, startTime); } catch (error) { const endTime = Date.now(); - Performance.markEnd(CONST.TIMING.DEBOUNCE_HANDLE_SEARCH); Log.alert('[CMD_K_FREEZE] Debounced search failed', { actionId, error: String(error), diff --git a/src/components/Search/SearchRouter/SearchButton.tsx b/src/components/Search/SearchRouter/SearchButton.tsx index 15c6e70eb862c..033daa0be0b3d 100644 --- a/src/components/Search/SearchRouter/SearchButton.tsx +++ b/src/components/Search/SearchRouter/SearchButton.tsx @@ -7,7 +7,6 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import Performance from '@libs/Performance'; import {startSpan} from '@libs/telemetry/activeSpans'; import {callFunctionIfActionIsAllowed} from '@userActions/Session'; import CONST from '@src/CONST'; @@ -30,7 +29,6 @@ function SearchButton({style, shouldUseAutoHitSlop = false}: SearchButtonProps) callFunctionIfActionIsAllowed(() => { pressableRef.current?.blur(); - Performance.markStart(CONST.TIMING.OPEN_SEARCH); startSpan(CONST.TELEMETRY.SPAN_OPEN_SEARCH_ROUTER, { name: CONST.TELEMETRY.SPAN_OPEN_SEARCH_ROUTER, op: CONST.TELEMETRY.SPAN_OPEN_SEARCH_ROUTER, diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 876c8b137cc6a..d7ae47603ed29 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -42,7 +42,6 @@ import {canUseTouchScreen} from '@libs/DeviceCapabilities'; import Log from '@libs/Log'; import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute'; import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types'; -import Performance from '@libs/Performance'; import {isSplitAction} from '@libs/ReportSecondaryActionUtils'; import {canEditFieldOfMoneyRequest, canHoldUnholdReportAction, canRejectReportAction, isOneTransactionReport, selectFilteredReportActions} from '@libs/ReportUtils'; import {buildCannedSearchQuery, buildSearchQueryString} from '@libs/SearchQueryUtils'; @@ -951,7 +950,6 @@ function Search({ return; } - Performance.markStart(CONST.TIMING.OPEN_REPORT_SEARCH); startSpan(`${CONST.TELEMETRY.SPAN_OPEN_REPORT}_${reportID}`, { name: 'Search', op: CONST.TELEMETRY.SPAN_OPEN_REPORT, diff --git a/src/libs/IOUUtils.ts b/src/libs/IOUUtils.ts index d50b15e56eb91..b889a27dff20e 100644 --- a/src/libs/IOUUtils.ts +++ b/src/libs/IOUUtils.ts @@ -9,7 +9,6 @@ import SafeString from '@src/utils/SafeString'; import type {IOURequestType} from './actions/IOU'; import {getCurrencyUnit} from './CurrencyUtils'; import Navigation from './Navigation/Navigation'; -import Performance from './Performance'; import {isPaidGroupPolicy} from './PolicyUtils'; import {getReportTransactions} from './ReportUtils'; import {getCurrency, getTagArrayFromName} from './TransactionUtils'; @@ -49,7 +48,6 @@ function navigateToStartMoneyRequestStep(requestType: IOURequestType, iouType: I } function navigateToParticipantPage(iouType: ValueOf, transactionID: string, reportID: string) { - Performance.markStart(CONST.TIMING.OPEN_CREATE_EXPENSE_CONTACT); switch (iouType) { case CONST.IOU.TYPE.REQUEST: Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); diff --git a/src/libs/Metrics/index.native.ts b/src/libs/Metrics/index.native.ts deleted file mode 100644 index 1749761de8363..0000000000000 --- a/src/libs/Metrics/index.native.ts +++ /dev/null @@ -1,9 +0,0 @@ -import CONFIG from '@src/CONFIG'; -import type CanCapturePerformanceMetrics from './types'; - -/** - * Is capturing performance stats enabled. - */ -const canCapturePerformanceMetrics: CanCapturePerformanceMetrics = () => CONFIG.CAPTURE_METRICS; - -export default canCapturePerformanceMetrics; diff --git a/src/libs/Metrics/index.ts b/src/libs/Metrics/index.ts deleted file mode 100644 index 658888b740f86..0000000000000 --- a/src/libs/Metrics/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type CanCapturePerformanceMetrics from './types'; - -// We don't capture performance metrics on web as there are enough tools available -const canCapturePerformanceMetrics: CanCapturePerformanceMetrics = () => false; - -export default canCapturePerformanceMetrics; diff --git a/src/libs/Metrics/types.ts b/src/libs/Metrics/types.ts deleted file mode 100644 index 15e6c43575ce9..0000000000000 --- a/src/libs/Metrics/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -type CanCapturePerformanceMetrics = () => boolean; - -export default CanCapturePerformanceMetrics; diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index e876f77d4292f..79bf1a2c4e231 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -20,7 +20,6 @@ import {MinHeap} from '@libs/MinHeap'; import {getForReportAction, getForReportActionTemp} from '@libs/ModifiedExpenseMessage'; import Navigation from '@libs/Navigation/Navigation'; import Parser from '@libs/Parser'; -import Performance from '@libs/Performance'; import Permissions from '@libs/Permissions'; import {getDisplayNameOrDefault, getPersonalDetailByEmail, getPersonalDetailsByIDs} from '@libs/PersonalDetailsUtils'; import {addSMSDomainIfPhoneNumber, parsePhoneNumber} from '@libs/PhoneNumber'; @@ -2543,8 +2542,6 @@ function getSearchOptions({ reportAttributesDerived, personalDetails, }: SearchOptionsConfig): Options { - Performance.markStart(CONST.TIMING.LOAD_SEARCH_OPTIONS); - const optionList = getValidOptions( options, policyCollection, @@ -2580,8 +2577,6 @@ function getSearchOptions({ reportAttributesDerived, ); - Performance.markEnd(CONST.TIMING.LOAD_SEARCH_OPTIONS); - return optionList; } diff --git a/src/libs/Performance.tsx b/src/libs/Performance.tsx deleted file mode 100644 index b867ce540e833..0000000000000 --- a/src/libs/Performance.tsx +++ /dev/null @@ -1,267 +0,0 @@ -import {deepEqual} from 'fast-equals'; -import isObject from 'lodash/isObject'; -import lodashTransform from 'lodash/transform'; -import React, {Profiler} from 'react'; -import {Alert, InteractionManager} from 'react-native'; -import performance, {PerformanceObserver, setResourceLoggingEnabled} from 'react-native-performance'; -import type {PerformanceEntry, PerformanceMark, PerformanceMeasure} from 'react-native-performance'; -import CONST from '@src/CONST'; -import getComponentDisplayName from './getComponentDisplayName'; -import canCapturePerformanceMetrics from './Metrics'; - -/** - * Deep diff between two objects. Useful for figuring out what changed about an object from one render to the next so - * that state and props updates can be optimized. - */ -function diffObject(object: Record, base: Record): Record { - function changes(obj: Record, comparisonObject: Record): Record { - return lodashTransform(obj, (result, value, key) => { - if (deepEqual(value, comparisonObject[key])) { - return; - } - - // eslint-disable-next-line no-param-reassign - result[key] = isObject(value) && isObject(comparisonObject[key]) ? changes(value as Record, comparisonObject[key] as Record) : value; - }); - } - return changes(object, base); -} - -function measureFailSafe(measureName: string, startOrMeasureOptions: string, endMark?: string): void { - try { - performance.measure(measureName, startOrMeasureOptions, endMark); - } catch (error) { - // Sometimes there might be no start mark recorded and the measure will fail with an error - if (error instanceof Error) { - console.debug(error.message); - } - } -} - -/** - * Measures the TTI (time to interactive) time starting from the `nativeLaunchStart` event. - * To be called when the app is considered to be interactive. - */ -function measureTTI(endMark?: string): void { - // Make sure TTI is captured when the app is really usable - // eslint-disable-next-line @typescript-eslint/no-deprecated - InteractionManager.runAfterInteractions(() => { - requestAnimationFrame(() => { - measureFailSafe('TTI', 'nativeLaunchStart', endMark); - - if (!canCapturePerformanceMetrics()) { - return; - } - - printPerformanceMetrics(); - }); - }); -} - -/* - * Monitor native marks that we want to put on the timeline - */ -const nativeMarksObserver = new PerformanceObserver((list, _observer) => { - for (const entry of list.getEntries()) { - if (entry.name === 'nativeLaunchEnd') { - measureFailSafe('nativeLaunch', 'nativeLaunchStart', 'nativeLaunchEnd'); - } - if (entry.name === 'downloadEnd') { - measureFailSafe('jsBundleDownload', 'downloadStart', 'downloadEnd'); - } - if (entry.name === 'runJsBundleEnd') { - measureFailSafe('runJsBundle', 'runJsBundleStart', 'runJsBundleEnd'); - } - if (entry.name === 'appCreationEnd') { - measureFailSafe('appCreation', 'appCreationStart', 'appCreationEnd'); - measureFailSafe('nativeLaunchEnd_To_appCreationStart', 'nativeLaunchEnd', 'appCreationStart'); - } - if (entry.name === 'contentAppeared') { - measureFailSafe('appCreationEnd_To_contentAppeared', 'appCreationEnd', 'contentAppeared'); - } - - // At this point we've captured and processed all the native marks we're interested in - // and are not expecting to have more thus we can safely disconnect the observer - if (entry.name === 'runJsBundleEnd' || entry.name === 'downloadEnd') { - _observer.disconnect(); - } - } -}); - -function setNativeMarksObserverEnabled(enabled = false): void { - if (!enabled) { - nativeMarksObserver.disconnect(); - return; - } - - nativeMarksObserver.disconnect(); - nativeMarksObserver.observe({type: 'react-native-mark', buffered: true}); -} - -/** - * Monitor for "_end" marks and capture "_start" to "_end" measures, including events recorded in the native layer before the app fully initializes. - */ -const customMarksObserver = new PerformanceObserver((list) => { - for (const mark of list.getEntriesByType('mark')) { - if (mark.name.endsWith('_end')) { - const end = mark.name; - const name = end.replaceAll(/_end$/g, ''); - const start = `${name}_start`; - measureFailSafe(name, start, end); - } - - // Capture any custom measures or metrics below - if (mark.name === `${CONST.TIMING.SIDEBAR_LOADED}_end`) { - measureFailSafe('contentAppeared_To_screenTTI', 'contentAppeared', mark.name); - measureTTI(mark.name); - } - } -}); - -function setCustomMarksObserverEnabled(enabled = false): void { - if (!enabled) { - customMarksObserver.disconnect(); - return; - } - - customMarksObserver.disconnect(); - customMarksObserver.observe({type: 'mark', buffered: true}); -} - -function getPerformanceMetrics(): PerformanceEntry[] { - return [ - ...performance.getEntriesByName('nativeLaunch'), - ...performance.getEntriesByName('nativeLaunchEnd_To_appCreationStart'), - ...performance.getEntriesByName('appCreation'), - ...performance.getEntriesByName('appCreationEnd_To_contentAppeared'), - ...performance.getEntriesByName('contentAppeared_To_screenTTI'), - ...performance.getEntriesByName('runJsBundle'), - ...performance.getEntriesByName('jsBundleDownload'), - ...performance.getEntriesByName('TTI'), - ...performance.getEntriesByName('regularAppStart'), - ...performance.getEntriesByName('appStartedToReady'), - ].filter((entry) => entry.duration > 0); -} - -function getPerformanceMeasures(): PerformanceEntry[] { - return performance.getEntriesByType('measure'); -} - -/** - * Outputs performance stats. We alert these so that they are easy to access in release builds. - */ -function printPerformanceMetrics(): void { - const stats = getPerformanceMetrics(); - const statsAsText = stats.map((entry) => `\u2022 ${entry.name}: ${entry.duration.toFixed(1)}ms`).join('\n'); - - if (stats.length > 0) { - Alert.alert('Performance', statsAsText); - } -} - -function subscribeToMeasurements(callback: (entry: PerformanceEntry) => void): () => void { - const observer = new PerformanceObserver((list) => { - for (const entry of list.getEntriesByType('measure')) { - callback(entry); - } - }); - - observer.observe({type: 'measure', buffered: true}); - - return () => observer.disconnect(); -} - -/** - * Add a start mark to the performance entries - */ -function markStart(name: string, detail?: Record): PerformanceMark { - return performance.mark(`${name}_start`, {detail}); -} - -/** - * Add an end mark to the performance entries - * A measure between start and end is captured automatically - */ -function markEnd(name: string, detail?: Record): PerformanceMark { - return performance.mark(`${name}_end`, {detail}); -} - -type Phase = 'mount' | 'update' | 'nested-update'; - -/** - * Put data emitted by Profiler components on the timeline - * @param id the "id" prop of the Profiler tree that has just committed - * @param phase either "mount" (if the tree just mounted) or "update" (if it re-rendered) - * @param actualDuration time spent rendering the committed update - * @param baseDuration estimated time to render the entire subtree without memoization - * @param startTime when React began rendering this update - * @param commitTime when React committed this update - */ -function traceRender(id: string, phase: Phase, actualDuration: number, baseDuration: number, startTime: number, commitTime: number): PerformanceMeasure { - return performance.measure(id, { - start: startTime, - duration: actualDuration, - detail: { - phase, - baseDuration, - commitTime, - }, - }); -} - -type WrappedComponentConfig = {id: string}; - -/** - * A HOC that captures render timings of the Wrapped component - */ -function withRenderTrace({id}: WrappedComponentConfig) { - if (!canCapturePerformanceMetrics()) { - return

>(WrappedComponent: React.ComponentType

): React.ComponentType

=> WrappedComponent; - } - - return

>(WrappedComponent: React.ComponentType

): React.ComponentType

=> { - function WithRenderTrace(props: P) { - return ( - - - - ); - } - - WithRenderTrace.displayName = `withRenderTrace(${getComponentDisplayName(WrappedComponent as React.ComponentType)})`; - return WithRenderTrace; - }; -} - -function enableMonitoring() { - setResourceLoggingEnabled(true); - setNativeMarksObserverEnabled(true); - setCustomMarksObserverEnabled(true); -} - -function disableMonitoring() { - setResourceLoggingEnabled(false); - setNativeMarksObserverEnabled(false); - setCustomMarksObserverEnabled(false); -} - -export default { - diffObject, - measureFailSafe, - measureTTI, - enableMonitoring, - disableMonitoring, - getPerformanceMetrics, - getPerformanceMeasures, - printPerformanceMetrics, - subscribeToMeasurements, - markStart, - markEnd, - withRenderTrace, -}; diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index 4a75fbc26f665..4bbf225a4530c 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -23,7 +23,6 @@ import { shouldShowLastActorDisplayName, } from './OptionsListUtils'; import Parser from './Parser'; -import Performance from './Performance'; import {getCleanedTagName} from './PolicyUtils'; import { getActionableCardFraudAlertResolutionMessage, @@ -544,8 +543,6 @@ function sortReportsToDisplayInLHN( reportNameValuePairs: OnyxCollection | undefined, conciergeReportID: string | undefined, ): string[] { - Performance.markStart(CONST.TIMING.GET_ORDERED_REPORT_IDS); - const isInFocusMode = priorityMode === CONST.PRIORITY_MODE.GSD; const isInDefaultMode = !isInFocusMode; // The LHN is split into five distinct groups, and each group is sorted a little differently. The groups will ALWAYS be in this order: @@ -574,7 +571,6 @@ function sortReportsToDisplayInLHN( sortedCategories.archivedReports, ); - Performance.markEnd(CONST.TIMING.GET_ORDERED_REPORT_IDS); return result; } diff --git a/src/libs/actions/App.ts b/src/libs/actions/App.ts index b7167043cb422..422393542dec3 100644 --- a/src/libs/actions/App.ts +++ b/src/libs/actions/App.ts @@ -13,7 +13,6 @@ import Log from '@libs/Log'; import getCurrentUrl from '@libs/Navigation/currentUrl'; import {linkingConfig} from '@libs/Navigation/linkingConfig'; import Navigation, {navigationRef} from '@libs/Navigation/Navigation'; -import Performance from '@libs/Performance'; import {isPublicRoom, isValidReport} from '@libs/ReportUtils'; import {isLoggingInAsNewUser as isLoggingInAsNewUserSessionUtils} from '@libs/SessionUtils'; import {clearSoundAssetsCache} from '@libs/Sound'; @@ -222,7 +221,6 @@ function setSidebarLoaded() { } Onyx.set(ONYXKEYS.IS_SIDEBAR_LOADED, true); - Performance.markEnd(CONST.TIMING.SIDEBAR_LOADED); } function setAppLoading(isLoading: boolean) { diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index d37630cc1b57b..c7e33e1e67ff4 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -72,7 +72,6 @@ import * as NumberUtils from '@libs/NumberUtils'; import {getManagerMcTestParticipant, getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils'; import Parser from '@libs/Parser'; import {getCustomUnitID} from '@libs/PerDiemRequestUtils'; -import Performance from '@libs/Performance'; import {getAccountIDsByLogins, getLoginByAccountID} from '@libs/PersonalDetailsUtils'; import {addSMSDomainIfPhoneNumber} from '@libs/PhoneNumber'; import { @@ -1145,7 +1144,6 @@ function handleNavigateAfterExpenseCreate({ return; } - Performance.markStart(CONST.TIMING.NAVIGATE_AFTER_EXPENSE_CREATE); startSpan(CONST.TELEMETRY.SPAN_NAVIGATE_AFTER_EXPENSE_CREATE, { name: 'navigate-after-expense-create', op: CONST.TELEMETRY.SPAN_NAVIGATE_AFTER_EXPENSE_CREATE, @@ -1360,7 +1358,6 @@ function startMoneyRequest( draftTransactions?: OnyxCollection, isFromFloatingActionButton?: boolean, ) { - Performance.markStart(CONST.TIMING.OPEN_CREATE_EXPENSE); const sourceRoute = Navigation.getActiveRoute(); startSpan(CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE, { name: '/money-request-create', diff --git a/src/libs/actions/OnyxUpdates.ts b/src/libs/actions/OnyxUpdates.ts index 707350c05854b..c2d344373caea 100644 --- a/src/libs/actions/OnyxUpdates.ts +++ b/src/libs/actions/OnyxUpdates.ts @@ -4,7 +4,6 @@ import Onyx from 'react-native-onyx'; import type {Merge} from 'type-fest'; import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import Log from '@libs/Log'; -import Performance from '@libs/Performance'; import PusherUtils from '@libs/PusherUtils'; import {trackExpenseApiError} from '@libs/telemetry/trackExpenseCreationError'; import CONST from '@src/CONST'; @@ -31,7 +30,6 @@ let pusherEventsPromise = Promise.resolve(); let airshipEventsPromise = Promise.resolve(); function applyHTTPSOnyxUpdates(request: Request, response: Response, lastUpdateID: number) { - Performance.markStart(CONST.TIMING.APPLY_HTTPS_UPDATES); const span = Sentry.startInactiveSpan({ name: CONST.TELEMETRY.SPAN_APPLY_ONYX_UPDATES, op: `${CONST.TELEMETRY.SPAN_APPLY_ONYX_UPDATES}.https`, @@ -84,7 +82,6 @@ function applyHTTPSOnyxUpdates(request: Request, res return Promise.resolve(); }) .then(() => { - Performance.markEnd(CONST.TIMING.APPLY_HTTPS_UPDATES); span.setStatus({code: 1}); span.end(); Log.info('[OnyxUpdateManager] Done applying HTTPS update', false, {lastUpdateID}); @@ -98,7 +95,6 @@ function applyHTTPSOnyxUpdates(request: Request, res } function applyPusherOnyxUpdates(updates: Array>, lastUpdateID: number) { - Performance.markStart(CONST.TIMING.APPLY_PUSHER_UPDATES); const span = Sentry.startInactiveSpan({ name: CONST.TELEMETRY.SPAN_APPLY_ONYX_UPDATES, op: `${CONST.TELEMETRY.SPAN_APPLY_ONYX_UPDATES}.pusher`, @@ -114,7 +110,6 @@ function applyPusherOnyxUpdates(updates: Array promise.then(() => PusherUtils.triggerMultiEventHandler(update.eventType, update.data)), pusherEventsPromise) .then(() => { - Performance.markEnd(CONST.TIMING.APPLY_PUSHER_UPDATES); span.setStatus({code: 1}); span.end(); Log.info('[OnyxUpdateManager] Done applying Pusher update', false, {lastUpdateID}); @@ -129,7 +124,6 @@ function applyPusherOnyxUpdates(updates: Array(updates: Array>, lastUpdateID: number) { - Performance.markStart(CONST.TIMING.APPLY_AIRSHIP_UPDATES); const span = Sentry.startInactiveSpan({ name: CONST.TELEMETRY.SPAN_APPLY_ONYX_UPDATES, op: `${CONST.TELEMETRY.SPAN_APPLY_ONYX_UPDATES}.airship`, @@ -145,7 +139,6 @@ function applyAirshipOnyxUpdates(updates: Array promise.then(() => Onyx.update(update.data as Array>)), airshipEventsPromise) .then(() => { - Performance.markEnd(CONST.TIMING.APPLY_AIRSHIP_UPDATES); span.setStatus({code: 1}); span.end(); Log.info('[OnyxUpdateManager] Done applying Airship updates', false, {lastUpdateID}); diff --git a/src/libs/telemetry/markNavigateAfterExpenseCreateEnd.ts b/src/libs/telemetry/markNavigateAfterExpenseCreateEnd.ts index 284efe53ceb90..d42184382e0db 100644 --- a/src/libs/telemetry/markNavigateAfterExpenseCreateEnd.ts +++ b/src/libs/telemetry/markNavigateAfterExpenseCreateEnd.ts @@ -1,4 +1,3 @@ -import Performance from '@libs/Performance'; import CONST from '@src/CONST'; import {endSpan, getSpan} from './activeSpans'; @@ -10,7 +9,6 @@ function markNavigateAfterExpenseCreateEnd() { return; } endSpan(CONST.TELEMETRY.SPAN_NAVIGATE_AFTER_EXPENSE_CREATE); - Performance.markEnd(CONST.TIMING.NAVIGATE_AFTER_EXPENSE_CREATE); } export default markNavigateAfterExpenseCreateEnd; diff --git a/src/libs/telemetry/markOpenReportEnd.ts b/src/libs/telemetry/markOpenReportEnd.ts index cc163fd478bae..654b4dab17b49 100644 --- a/src/libs/telemetry/markOpenReportEnd.ts +++ b/src/libs/telemetry/markOpenReportEnd.ts @@ -1,11 +1,10 @@ -import Performance from '@libs/Performance'; import {isOneTransactionReport, isReportTransactionThread} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import type * as OnyxTypes from '@src/types/onyx'; import {endSpan, getSpan} from './activeSpans'; /** - * Mark all 'open_report*' performance events as finished using both Performance (local) and Timing (remote) tracking. + * Mark all 'open_report*' telemetry spans as finished. */ function markOpenReportEnd(report: OnyxTypes.Report) { const {reportID, type, chatType} = report; @@ -23,14 +22,6 @@ function markOpenReportEnd(report: OnyxTypes.Report) { }); endSpan(spanId); - - Performance.markEnd(CONST.TIMING.OPEN_REPORT); - - Performance.markEnd(CONST.TIMING.OPEN_REPORT_THREAD); - - Performance.markEnd(CONST.TIMING.OPEN_REPORT_FROM_PREVIEW); - - Performance.markEnd(CONST.TIMING.OPEN_REPORT_SEARCH); } export default markOpenReportEnd; diff --git a/src/libs/telemetry/markSubmitExpenseEnd.ts b/src/libs/telemetry/markSubmitExpenseEnd.ts index 985c9f3f7da9e..29b13cdffbe23 100644 --- a/src/libs/telemetry/markSubmitExpenseEnd.ts +++ b/src/libs/telemetry/markSubmitExpenseEnd.ts @@ -1,4 +1,3 @@ -import Performance from '@libs/Performance'; import CONST from '@src/CONST'; import {endSpan, getSpan} from './activeSpans'; @@ -11,7 +10,6 @@ function markSubmitExpenseEnd() { return; } endSpan(CONST.TELEMETRY.SPAN_SUBMIT_EXPENSE); - Performance.markEnd(CONST.TIMING.SUBMIT_EXPENSE); } export default markSubmitExpenseEnd; diff --git a/src/pages/inbox/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/inbox/report/ReportActionCompose/ReportActionCompose.tsx index 336512880c385..ebd0b5909c894 100644 --- a/src/pages/inbox/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ReportActionCompose.tsx @@ -39,7 +39,6 @@ import DomUtils from '@libs/DomUtils'; import FS from '@libs/Fullstory'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import {rand64} from '@libs/NumberUtils'; -import Performance from '@libs/Performance'; import {getLinkedTransactionID, getReportAction, isMoneyRequestAction} from '@libs/ReportActionsUtils'; import { canEditFieldOfMoneyRequest, @@ -366,7 +365,6 @@ function ReportActionCompose({ // The list is inverted, so an offset near 0 means the user is at the bottom (newest messages visible). const isScrolledToBottom = scrollOffsetRef.current < CONST.REPORT.ACTIONS.ACTION_VISIBLE_THRESHOLD; if (isScrolledToBottom) { - Performance.markStart(CONST.TIMING.SEND_MESSAGE, {message: newCommentTrimmed}); startSpan(`${CONST.TELEMETRY.SPAN_SEND_MESSAGE}_${optimisticReportActionID}`, { name: 'send-message', op: CONST.TELEMETRY.SPAN_SEND_MESSAGE, diff --git a/src/pages/inbox/report/ReportActionItemThread.tsx b/src/pages/inbox/report/ReportActionItemThread.tsx index a99c04c965bdc..9a278ce4dc362 100644 --- a/src/pages/inbox/report/ReportActionItemThread.tsx +++ b/src/pages/inbox/report/ReportActionItemThread.tsx @@ -9,7 +9,6 @@ import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; import {navigateToAndOpenChildReport} from '@libs/actions/Report'; -import Performance from '@libs/Performance'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Report, ReportAction} from '@src/types/onyx'; @@ -55,7 +54,6 @@ function ReportActionItemThread({numberOfReplies, accountIDs, mostRecentReply, r { - Performance.markStart(CONST.TIMING.OPEN_REPORT_THREAD); navigateToAndOpenChildReport(childReport, reportAction, report); }} role={CONST.ROLE.BUTTON} diff --git a/src/pages/inbox/report/ReportActionsView.tsx b/src/pages/inbox/report/ReportActionsView.tsx index a1e2c00310d79..2120bc7cd9fcf 100755 --- a/src/pages/inbox/report/ReportActionsView.tsx +++ b/src/pages/inbox/report/ReportActionsView.tsx @@ -19,7 +19,6 @@ import {getAllNonDeletedTransactions} from '@libs/MoneyRequestReportUtils'; import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; import type {ReportsSplitNavigatorParamList} from '@libs/Navigation/types'; import {generateNewRandomInt, rand64} from '@libs/NumberUtils'; -import Performance from '@libs/Performance'; import { getCombinedReportActions, getMostRecentIOURequestActionID, @@ -337,4 +336,4 @@ function ReportActionsView({ ); } -export default Performance.withRenderTrace({id: ' rendering'})(ReportActionsView); +export default ReportActionsView; diff --git a/src/pages/inbox/report/comment/TextCommentFragment.tsx b/src/pages/inbox/report/comment/TextCommentFragment.tsx index 1a692b9517473..baaf95b01bc7d 100644 --- a/src/pages/inbox/report/comment/TextCommentFragment.tsx +++ b/src/pages/inbox/report/comment/TextCommentFragment.tsx @@ -13,7 +13,6 @@ import convertToLTR from '@libs/convertToLTR'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; import {containsOnlyCustomEmoji as containsOnlyCustomEmojiUtil, containsOnlyEmojis as containsOnlyEmojisUtil, splitTextWithEmojis} from '@libs/EmojiUtils'; import Parser from '@libs/Parser'; -import Performance from '@libs/Performance'; import {getHtmlWithAttachmentID, getTextFromHtml} from '@libs/ReportActionsUtils'; import {endSpan} from '@libs/telemetry/activeSpans'; import variables from '@styles/variables'; @@ -63,9 +62,6 @@ function TextCommentFragment({fragment, styleAsDeleted, reportActionID, styleAsM const processedTextArray = splitTextWithEmojis(message); - useEffect(() => { - Performance.markEnd(CONST.TIMING.SEND_MESSAGE, {message: text}); - }, [text]); useEffect(() => { if (!reportActionID) { return; diff --git a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx index dd84de362a742..ddb3207cdf2f1 100644 --- a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx +++ b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx @@ -1,4 +1,4 @@ -import React, {useEffect} from 'react'; +import React from 'react'; import {View} from 'react-native'; import NavigationTabBar from '@components/Navigation/NavigationTabBar'; import NAVIGATION_TABS from '@components/Navigation/NavigationTabBar/NAVIGATION_TABS'; @@ -8,8 +8,6 @@ import useLocalize from '@hooks/useLocalize'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import {isMobile} from '@libs/Browser'; -import Performance from '@libs/Performance'; -import CONST from '@src/CONST'; import SidebarLinksData from './SidebarLinksData'; function BaseSidebarScreen() { @@ -18,10 +16,6 @@ function BaseSidebarScreen() { const {shouldUseNarrowLayout} = useResponsiveLayout(); const shouldDisplayLHB = !shouldUseNarrowLayout; - useEffect(() => { - Performance.markStart(CONST.TIMING.SIDEBAR_LOADED); - }, []); - return ( { endSpan(CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE); - Performance.markEnd(CONST.TIMING.OPEN_CREATE_EXPENSE); }, []); const navigateBack = () => { diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 677d618a822de..0b4e991736dc5 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -26,7 +26,6 @@ import type Platform from '@libs/getPlatform/types'; import Navigation from '@libs/Navigation/Navigation'; import OnyxTabNavigator, {TabScreenWithFocusTrapWrapper, TopTab} from '@libs/Navigation/OnyxTabNavigator'; import {getIsUserSubmittedExpenseOrScannedReceipt} from '@libs/OptionsListUtils'; -import Performance from '@libs/Performance'; import { getActivePoliciesWithExpenseChatAndPerDiemEnabledAndHasRates, getActivePoliciesWithExpenseChatAndTimeEnabled, @@ -157,7 +156,6 @@ function IOURequestStartPage({ useEffect(() => { endSpan(CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE); - Performance.markEnd(CONST.TIMING.OPEN_CREATE_EXPENSE); }, []); useEffect(() => { diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 57659881545c4..6378d9e7718d8 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -49,7 +49,6 @@ import navigateAfterInteraction from '@libs/Navigation/navigateAfterInteraction' import Navigation from '@libs/Navigation/Navigation'; import {rand64, roundToTwoDecimalPlaces} from '@libs/NumberUtils'; import {getParticipantsOption, getReportOption} from '@libs/OptionsListUtils'; -import Performance from '@libs/Performance'; import {isPaidGroupPolicy} from '@libs/PolicyUtils'; import { doesReportReceiverMatchParticipant, @@ -324,7 +323,6 @@ function IOURequestStepConfirmation({ useEffect(() => { endSpan(CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE); - Performance.markEnd(CONST.TIMING.OPEN_CREATE_EXPENSE_APPROVE); }, []); useEffect(() => { @@ -995,7 +993,6 @@ function IOURequestStepConfirmation({ hasReceiptFiles, }); - Performance.markStart(CONST.TIMING.SUBMIT_EXPENSE); startSpan(CONST.TELEMETRY.SPAN_SUBMIT_EXPENSE, { name: 'submit-expense', op: CONST.TELEMETRY.SPAN_SUBMIT_EXPENSE, diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index 99da565eebbd5..e382043939fef 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -17,7 +17,6 @@ import getPlatform from '@libs/getPlatform'; import HttpUtils from '@libs/HttpUtils'; import {isMovingTransactionFromTrackExpense as isMovingTransactionFromTrackExpenseIOUUtils, navigateToStartMoneyRequestStep} from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; -import Performance from '@libs/Performance'; import {isPaidGroupPolicy} from '@libs/PolicyUtils'; import {findSelfDMReportID, generateReportID, isInvoiceRoomWithID} from '@libs/ReportUtils'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; @@ -127,7 +126,6 @@ function IOURequestStepParticipants({ useEffect(() => { endSpan(CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE); - Performance.markEnd(CONST.TIMING.OPEN_CREATE_EXPENSE_CONTACT); }, []); // When the component mounts, if there is a receipt, see if the image can be read from the disk. If not, redirect the user to the starting step of the flow. @@ -359,7 +357,6 @@ function IOURequestStepParticipants({ ? ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, initialTransactionID, selectedReportID.current || reportID, iouConfirmationPageRoute) : iouConfirmationPageRoute; - Performance.markStart(CONST.TIMING.OPEN_CREATE_EXPENSE_APPROVE); waitForKeyboardDismiss(() => { // If the backTo parameter is set, we should navigate back to the confirmation screen that is already on the stack. // We wrap navigation in setNavigationActionToMicrotaskQueue so that data loading in Onyx and navigation do not occur simultaneously, which resets the amount to 0. diff --git a/src/pages/signin/SignInPage.tsx b/src/pages/signin/SignInPage.tsx index c9d5f496d9e0b..267a9089de9ca 100644 --- a/src/pages/signin/SignInPage.tsx +++ b/src/pages/signin/SignInPage.tsx @@ -18,7 +18,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {isClientTheLeader as isClientTheLeaderActiveClientManager} from '@libs/ActiveClientManager'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; -import Performance from '@libs/Performance'; import Visibility from '@libs/Visibility'; import {clearSignInData} from '@userActions/Session'; import CONST from '@src/CONST'; @@ -180,10 +179,6 @@ function SignInPage({ref}: SignInPageProps) { // eslint-disable-next-line rulesdir/no-negated-variables const shouldShowAnotherLoginPageOpenedMessage = Visibility.isVisible() && !isClientTheLeader; - useEffect(() => { - Performance.measureTTI(); - }, []); - useEffect(() => { if (credentials?.login) { return; diff --git a/src/setup/platformSetup/index.native.ts b/src/setup/platformSetup/index.native.ts index a071672e8bab3..ea9b101e1c225 100644 --- a/src/setup/platformSetup/index.native.ts +++ b/src/setup/platformSetup/index.native.ts @@ -1,10 +1 @@ -import canCapturePerformanceMetrics from '@libs/Metrics'; -import Performance from '@libs/Performance'; - -export default function () { - if (!canCapturePerformanceMetrics()) { - return; - } - - Performance.enableMonitoring(); -} +export default function () {} diff --git a/src/types/modules/react-native-performance.d.ts b/src/types/modules/react-native-performance.d.ts deleted file mode 100644 index e42e7593b027b..0000000000000 --- a/src/types/modules/react-native-performance.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type {Performance, PerformanceEntry, PerformanceMark, PerformanceMeasure, PerformanceObserver} from 'react-native-performance'; - -declare module 'react-native-performance' { - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions - interface ReactNativePerformance { - default: Performance; - setResourceLoggingEnabled: (enabled?: boolean) => void; - PerformanceObserver: typeof PerformanceObserver; - } - - export type {PerformanceEntry, PerformanceMark, PerformanceMeasure, Performance, ReactNativePerformance}; -} From a6aafbb30d7699ddaa482476f7b6c53562b98840 Mon Sep 17 00:00:00 2001 From: rory Date: Fri, 20 Feb 2026 15:19:35 -0800 Subject: [PATCH 2/5] Remove dead jest.mock for deleted Performance module The jest.mock('@libs/Performance', ...) in OnyxUpdatesSpanTest.ts references the now-deleted Performance.tsx, causing the test suite to fail with "Cannot find module". Co-authored-by: Cursor --- tests/unit/OnyxUpdatesSpanTest.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/unit/OnyxUpdatesSpanTest.ts b/tests/unit/OnyxUpdatesSpanTest.ts index d29b2fa8dbe25..5c7e7beb12f31 100644 --- a/tests/unit/OnyxUpdatesSpanTest.ts +++ b/tests/unit/OnyxUpdatesSpanTest.ts @@ -54,14 +54,6 @@ jest.mock('@libs/PusherUtils', () => ({ }, })); -jest.mock('@libs/Performance', () => ({ - __esModule: true, - default: { - markStart: jest.fn(), - markEnd: jest.fn(), - }, -})); - jest.mock('@libs/Log', () => ({ __esModule: true, default: { From 035c0304a12b613d8a938bd2afe9df0278a9f62d Mon Sep 17 00:00:00 2001 From: rory Date: Fri, 20 Feb 2026 15:31:29 -0800 Subject: [PATCH 3/5] Remove RNPerformance references from Android native code The react-native-performance package was uninstalled, but MainActivity.kt and MainApplication.kt still imported and used RNPerformance, breaking the Android build. Co-authored-by: Cursor --- android/app/src/main/java/com/expensify/chat/MainActivity.kt | 3 --- .../app/src/main/java/com/expensify/chat/MainApplication.kt | 2 -- 2 files changed, 5 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/MainActivity.kt b/android/app/src/main/java/com/expensify/chat/MainActivity.kt index 669c4c09ea7c9..783ae54c2a059 100644 --- a/android/app/src/main/java/com/expensify/chat/MainActivity.kt +++ b/android/app/src/main/java/com/expensify/chat/MainActivity.kt @@ -16,8 +16,6 @@ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnable import com.facebook.react.defaults.DefaultReactActivityDelegate import expo.modules.ReactActivityDelegateWrapper -import com.oblador.performance.RNPerformance - class MainActivity : ReactActivity() { /** * Returns the name of the main component registered from JavaScript. This is used to schedule @@ -117,6 +115,5 @@ class MainActivity : ReactActivity() { override fun onStart() { super.onStart() - RNPerformance.getInstance().mark("appCreationEnd", false) } } diff --git a/android/app/src/main/java/com/expensify/chat/MainApplication.kt b/android/app/src/main/java/com/expensify/chat/MainApplication.kt index d1ea6e18c82c9..06a0bc5f50b04 100644 --- a/android/app/src/main/java/com/expensify/chat/MainApplication.kt +++ b/android/app/src/main/java/com/expensify/chat/MainApplication.kt @@ -21,7 +21,6 @@ import com.facebook.react.defaults.DefaultReactNativeHost import com.facebook.react.modules.i18nmanager.I18nUtil import com.facebook.react.soloader.OpenSourceMergedSoMapping import com.facebook.soloader.SoLoader -import com.oblador.performance.RNPerformance import expo.modules.ApplicationLifecycleDispatcher import expo.modules.ReactNativeHostWrapper import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative @@ -58,7 +57,6 @@ class MainApplication : MultiDexApplication(), ReactApplication { ReactFontManager.getInstance().addCustomFont(this, "Expensify New Kansas", R.font.expensify_new_kansas) ReactFontManager.getInstance().addCustomFont(this, "Expensify Neue", R.font.expensify_neue) ReactFontManager.getInstance().addCustomFont(this, "Expensify Mono", R.font.expensify_mono) - RNPerformance.getInstance().mark("appCreationStart", false); if (isOnfidoProcess()) { return From 786ad8f8f972fe9845f5f3a053957c1a5dd9cfe9 Mon Sep 17 00:00:00 2001 From: rory Date: Fri, 20 Feb 2026 15:35:34 -0800 Subject: [PATCH 4/5] Update Podfile.lock after removing react-native-performance Co-authored-by: Cursor --- ios/Podfile.lock | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 01a064dbbdddd..dffd37290531c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2564,34 +2564,6 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-performance (6.0.0): - - boost - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - RCT-Folly/Fabric - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsi - - React-NativeModulesApple - - React-RCTFabric - - React-renderercss - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - SocketRocket - - Yoga - react-native-plaid-link-sdk (12.5.3): - boost - DoubleConversion @@ -4122,7 +4094,6 @@ DEPENDENCIES: - "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)" - react-native-pager-view (from `../node_modules/react-native-pager-view`) - react-native-pdf (from `../node_modules/react-native-pdf`) - - react-native-performance (from `../node_modules/react-native-performance`) - react-native-plaid-link-sdk (from `../node_modules/react-native-plaid-link-sdk`) - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - "react-native-skia (from `../node_modules/@shopify/react-native-skia`)" @@ -4391,8 +4362,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-pager-view" react-native-pdf: :path: "../node_modules/react-native-pdf" - react-native-performance: - :path: "../node_modules/react-native-performance" react-native-plaid-link-sdk: :path: "../node_modules/react-native-plaid-link-sdk" react-native-safe-area-context: @@ -4632,7 +4601,6 @@ SPEC CHECKSUMS: react-native-netinfo: f94b3a0fc305e812f3f615989d99299d7110c2ae react-native-pager-view: c62ab82db28e2d11e7809c59085e2984a45979c5 react-native-pdf: 6a09a9be0e7ee954ea671437483316f9a28f8572 - react-native-performance: a7a65d0b0f3055c5db33e1433e4345143ef6a100 react-native-plaid-link-sdk: 425c0a3a923310fcd8489142209ff1508372a7bf react-native-safe-area-context: 0a3b034bb63a5b684dd2f5fffd3c90ef6ed41ee8 react-native-skia: 51f30133876025c83e933f4f7253479e6de5d937 From 2158bbeaafd2be16944e41a41e1e5d21577a2206 Mon Sep 17 00:00:00 2001 From: rory Date: Fri, 20 Feb 2026 15:52:37 -0800 Subject: [PATCH 5/5] Consolidate platformSetup: remove redundant index.website.ts index.native.ts and index.ts were both no-ops after removing Performance. Move the web implementation from index.website.ts into index.ts and delete the .website variant. Co-authored-by: Cursor --- src/setup/platformSetup/index.ts | 66 +++++++++++++++++++++++- src/setup/platformSetup/index.website.ts | 65 ----------------------- 2 files changed, 65 insertions(+), 66 deletions(-) delete mode 100644 src/setup/platformSetup/index.website.ts diff --git a/src/setup/platformSetup/index.ts b/src/setup/platformSetup/index.ts index 2d1ec238274a0..f0038a8f0728e 100644 --- a/src/setup/platformSetup/index.ts +++ b/src/setup/platformSetup/index.ts @@ -1 +1,65 @@ -export default () => {}; +import {AppRegistry} from 'react-native'; +import checkForUpdates from '@libs/checkForUpdates'; +import DateUtils from '@libs/DateUtils'; +import Visibility from '@libs/Visibility'; +import Config from '@src/CONFIG'; +import pkg from '../../../package.json'; +import type PlatformSpecificUpdater from './types'; + +/** + * Download the latest app version from the server, and if it is different than the current one, + * then refresh. If the page is visible, prompt the user to refresh. + */ +function webUpdate() { + fetch('/version.json', {cache: 'no-cache'}) + .then((response) => response.json()) + .then(({version}) => { + if (version === pkg.version) { + return; + } + + if (!Visibility.isVisible()) { + // Page is hidden, refresh immediately + window.location.reload(); + return; + } + + // Prompt user to refresh the page + if (window.confirm('Refresh the page to get the latest updates!')) { + window.location.reload(); + } + }); +} + +/** + * Create an object whose shape reflects the callbacks used in checkForUpdates. + */ +const webUpdater = (): PlatformSpecificUpdater => ({ + init: () => { + // We want to check for updates and refresh the page if necessary when the app is background. + // That way, it will auto-update silently when they minimize the page, + // and we don't bug the user any more than necessary :) + window.addEventListener('visibilitychange', () => { + if (Visibility.isVisible()) { + return; + } + + webUpdate(); + }); + }, + update: () => webUpdate(), +}); + +export default function () { + AppRegistry.runApplication(Config.APP_NAME, { + rootTag: document.getElementById('root'), + }); + + // When app loads, get current version (production only) + if (Config.IS_IN_PRODUCTION) { + checkForUpdates(webUpdater()); + } + + // Start current date updater + DateUtils.startCurrentDateUpdater(); +} diff --git a/src/setup/platformSetup/index.website.ts b/src/setup/platformSetup/index.website.ts deleted file mode 100644 index f0038a8f0728e..0000000000000 --- a/src/setup/platformSetup/index.website.ts +++ /dev/null @@ -1,65 +0,0 @@ -import {AppRegistry} from 'react-native'; -import checkForUpdates from '@libs/checkForUpdates'; -import DateUtils from '@libs/DateUtils'; -import Visibility from '@libs/Visibility'; -import Config from '@src/CONFIG'; -import pkg from '../../../package.json'; -import type PlatformSpecificUpdater from './types'; - -/** - * Download the latest app version from the server, and if it is different than the current one, - * then refresh. If the page is visible, prompt the user to refresh. - */ -function webUpdate() { - fetch('/version.json', {cache: 'no-cache'}) - .then((response) => response.json()) - .then(({version}) => { - if (version === pkg.version) { - return; - } - - if (!Visibility.isVisible()) { - // Page is hidden, refresh immediately - window.location.reload(); - return; - } - - // Prompt user to refresh the page - if (window.confirm('Refresh the page to get the latest updates!')) { - window.location.reload(); - } - }); -} - -/** - * Create an object whose shape reflects the callbacks used in checkForUpdates. - */ -const webUpdater = (): PlatformSpecificUpdater => ({ - init: () => { - // We want to check for updates and refresh the page if necessary when the app is background. - // That way, it will auto-update silently when they minimize the page, - // and we don't bug the user any more than necessary :) - window.addEventListener('visibilitychange', () => { - if (Visibility.isVisible()) { - return; - } - - webUpdate(); - }); - }, - update: () => webUpdate(), -}); - -export default function () { - AppRegistry.runApplication(Config.APP_NAME, { - rootTag: document.getElementById('root'), - }); - - // When app loads, get current version (production only) - if (Config.IS_IN_PRODUCTION) { - checkForUpdates(webUpdater()); - } - - // Start current date updater - DateUtils.startCurrentDateUpdater(); -}