diff --git a/benchmarks/README.md b/benchmarks/README.md index 81cb8c66d..50434af27 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -71,7 +71,7 @@ Launch a specific test scenario with a particular configuration: - **Method**: `start` - **Parameters**: - **scenario**: name of the test as defined on the `Scenario` enum in `types/testConfig.ts` - - **runType**: `instrumented|baseline|profiling` + - **runType**: one of the values defined on the `RunType` enum in `types/testConfig.ts`: `baseline|instrumented|instrumented_profiling_native` ### iOS @@ -85,6 +85,24 @@ xcrun simctl openurl booted "benchmark://start?scenario=navigation&runType=instr adb shell am start -W -a android.intent.action.VIEW -d 'benchmark://start?scenario=navigation\&runType=instrumented' com.benchmarkrunner ``` +### Example: Profiling scenario + +The profiling scenario enables native profiling when `runType` is `instrumented_profiling_native`. With `instrumented`, it only initializes the SDK. + +iOS: + +``` +xcrun simctl openurl booted "benchmark://start?scenario=profiling&runType=instrumented_profiling_native" +``` + +Android: + +``` +adb shell am start -W -a android.intent.action.VIEW -d 'benchmark://start?scenario=profiling\&runType=instrumented_profiling_native' com.benchmarkrunner +``` + +Note: Native profiling only takes effect on Android 15 (API 35) and above; on lower API levels the native profiling call is a no-op. + ## Stop a test scenario Stops the scenario currently running. diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index cde50e224..0c89c8c4c 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -11,6 +11,8 @@ PODS: - DatadogInternal (3.16.1) - DatadogLogs (3.16.1): - DatadogInternal (= 3.16.1) + - DatadogProfiling (3.16.1): + - DatadogInternal (= 3.16.1) - DatadogRUM (3.16.1): - DatadogInternal (= 3.16.1) - DatadogSDKReactNative (3.11.0): @@ -41,6 +43,29 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - DatadogSDKReactNativeProfiling (3.11.0): + - DatadogProfiling (= 3.16.1) + - DatadogSDKReactNative + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - DatadogSDKReactNativeSessionReplay (3.11.0): - DatadogSDKReactNative - DatadogSessionReplay (= 3.16.1) @@ -1883,6 +1908,7 @@ PODS: DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - "DatadogSDKReactNative (from `../node_modules/@datadog/mobile-react-native`)" + - "DatadogSDKReactNativeProfiling (from `../node_modules/@datadog/mobile-react-native-profiling`)" - "DatadogSDKReactNativeSessionReplay (from `../node_modules/@datadog/mobile-react-native-session-replay`)" - "DatadogSDKReactNativeWebView (from `../node_modules/@datadog/mobile-react-native-webview`)" - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) @@ -1968,6 +1994,7 @@ SPEC REPOS: - DatadogFlags - DatadogInternal - DatadogLogs + - DatadogProfiling - DatadogRUM - DatadogSessionReplay - DatadogTrace @@ -1982,6 +2009,8 @@ EXTERNAL SOURCES: :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" DatadogSDKReactNative: :path: "../node_modules/@datadog/mobile-react-native" + DatadogSDKReactNativeProfiling: + :path: "../node_modules/@datadog/mobile-react-native-profiling" DatadogSDKReactNativeSessionReplay: :path: "../node_modules/@datadog/mobile-react-native-session-replay" DatadogSDKReactNativeWebView: @@ -2139,8 +2168,10 @@ SPEC CHECKSUMS: DatadogFlags: 65cb325168aed2f7beb24ebef716227c6c2a8d1a DatadogInternal: 152be7f0a389684161fa642e55509163c99757d5 DatadogLogs: 0c145bb072308903df8a7edd9c1125f4b479fa5f + DatadogProfiling: 03a1ac3f8fbeee901aceb5f176c2ce1918e6c826 DatadogRUM: dcffd64699184ef38f63d42bd331cc1eba967661 DatadogSDKReactNative: 71c08109f6606110d115a4371b397aefd0602e5e + DatadogSDKReactNativeProfiling: 8cb3c971d9c2e4c18ed3f86b77d20f9683a39bde DatadogSDKReactNativeSessionReplay: dabfdd28924ab6a001e7c8aea61b40b4a483d3aa DatadogSDKReactNativeWebView: 75353385df029f3b4f105f5b1f6cc3b822172147 DatadogSessionReplay: 137621c077cfb039224ecb3955a8d9a015d065a0 diff --git a/benchmarks/package.json b/benchmarks/package.json index d208e29fd..76fd87603 100644 --- a/benchmarks/package.json +++ b/benchmarks/package.json @@ -20,6 +20,7 @@ }, "dependencies": { "@datadog/mobile-react-native": "workspace:packages/core", + "@datadog/mobile-react-native-profiling": "workspace:packages/react-native-profiling", "@datadog/mobile-react-native-session-replay": "workspace:packages/react-native-session-replay", "@datadog/mobile-react-native-webview": "workspace:packages/react-native-webview", "@datadog/mobile-react-navigation": "workspace:packages/react-navigation", diff --git a/benchmarks/src/App.tsx b/benchmarks/src/App.tsx index 4a3bc0255..d1f3d0f2f 100644 --- a/benchmarks/src/App.tsx +++ b/benchmarks/src/App.tsx @@ -21,6 +21,7 @@ import TracesScenario from './scenario/Traces/tracesScenario'; import RUMManualScenario from './scenario/RUM/Manual/rumManualScenario'; import RUMAutoScenario from './scenario/RUM/Auto/rumAutoScenario'; import SessionReplayScenario from './scenario/SessionReplay/sessionReplayScenario'; +import ProfilingScenario from './scenario/Profiling/profilingScenario'; function App(): React.JSX.Element { const [testConfig, setTestConfig] = useState(); @@ -85,6 +86,8 @@ function App(): React.JSX.Element { return ; case Scenario.SessionReplay: return ; + case Scenario.Profiling: + return ; // Add new scenarios here default: return ( diff --git a/benchmarks/src/scenario/Profiling/profilingScenario.tsx b/benchmarks/src/scenario/Profiling/profilingScenario.tsx new file mode 100644 index 000000000..8a839d589 --- /dev/null +++ b/benchmarks/src/scenario/Profiling/profilingScenario.tsx @@ -0,0 +1,116 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import React, { useEffect, useState } from 'react'; +import { + ActivityIndicator, + Button, + Platform, + SafeAreaView, + Text, + View, +} from 'react-native'; +import type { ProfilingScenarioProps } from './types'; +import { DdProfiling } from '@datadog/mobile-react-native-profiling'; +import { RunType } from '../../testSetup/types/testConfig'; +import { instrument } from '../../testSetup/testUtils'; +import { + blockJsThread, + computePrimes, + fibonacci, + sortNumbers, +} from './profilingUtils'; +import { Colors, CommonStyles as styles } from '../../common/styles'; + +const OS = Platform.OS; +const SORT_COUNT = 1_000_000; +const FIBONACCI_N = 35; +const PRIMES_LIMIT = 1_000_000; +const LONG_TASK_DURATION_MS = 500; + +function ProfilingScenario(props: ProfilingScenarioProps): React.JSX.Element { + const [isRunning, setIsRunning] = useState(false); + const [lastResult, setLastResult] = useState(''); + + useEffect(() => { + console.log(props.testConfig); + const runType = props.testConfig?.runType; + if (runType !== RunType.BASELINE) { + instrument().then(async () => { + if (runType === RunType.INSTRUMENTED_PROFILING_NATIVE) { + console.log("Enabling native profiling"); + await DdProfiling.enable({ + applicationLaunchSampleRate: 100, + continuousSampleRate: 100, + }); + } + }); + } + }, []); + + const runWork = (label: string, work: () => void) => { + setIsRunning(true); + setLastResult(''); + + const startTime = performance.now(); + work(); + const durationMs = performance.now() - startTime; + + setLastResult(`${label} took ${durationMs.toFixed(0)}ms`); + setIsRunning(false); + }; + + const onSortNumbers = () => runWork(`Sort ${SORT_COUNT} numbers`, () => sortNumbers(SORT_COUNT)); + const onFibonacci = () => runWork(`Fibonacci(${FIBONACCI_N})`, () => fibonacci(FIBONACCI_N)); + const onComputePrimes = () => runWork(`Primes up to ${PRIMES_LIMIT}`, () => computePrimes(PRIMES_LIMIT)); + const onLongTask = () => runWork('JS long task', () => blockJsThread(LONG_TASK_DURATION_MS)); + + return ( + + + PROFILING SCENARIO + + +