diff --git a/.github/workflows/perf-tests.yml b/.github/workflows/perf-tests.yml
index d29a71a3290..762643cc172 100644
--- a/.github/workflows/perf-tests.yml
+++ b/.github/workflows/perf-tests.yml
@@ -27,7 +27,7 @@ jobs:
perf-tests:
name: Component Performance Tests
runs-on: windows-latest
- timeout-minutes: 30
+ timeout-minutes: 60
permissions:
contents: read
@@ -49,9 +49,31 @@ jobs:
- name: Install dependencies
run: yarn install --frozen-lockfile
+ - name: Install Windows SDK 10.0.22621
+ shell: pwsh
+ run: |
+ $installerUrl = "https://download.microsoft.com/download/3/b/d/3bd97f81-3f5b-4922-b86d-dc5145cd6bfe/windowssdk/winsdksetup.exe"
+ $installerPath = "$env:TEMP\winsdksetup.exe"
+ Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath
+ Start-Process -FilePath $installerPath -ArgumentList '/quiet', '/norestart', '/features', '+' -Wait -NoNewWindow
+ $sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\10\Include\10.0.22621.0"
+ if (!(Test-Path $sdkPath)) {
+ echo "::error::Failed to install Windows SDK 10.0.22621"
+ exit 1
+ }
+
- name: Build perf-testing package
run: yarn workspace @react-native-windows/perf-testing build
+ - name: Enable Developer Mode
+ shell: pwsh
+ run: reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t REG_DWORD /f /v AllowDevelopmentWithoutDevLicense /d 1
+
+ # ── Build & Deploy RNTesterApp-Fabric (for native perf tests) ──
+ - name: Build and deploy RNTesterApp-Fabric
+ working-directory: packages/e2e-test-app-fabric
+ run: yarn windows --release --no-launch --logging
+
# ── Run Tests ──────────────────────────────────────────
- name: Run perf tests
id: perf-run
@@ -61,7 +83,14 @@ jobs:
RN_TARGET_PLATFORM: windows
run: yarn perf:ci
continue-on-error: true # Don't fail here — let comparison decide
-
+ - name: Run native perf tests
+ id: native-perf-run
+ working-directory: packages/e2e-test-app-fabric
+ env:
+ CI: 'true'
+ RN_TARGET_PLATFORM: windows
+ run: yarn perf:native:ci
+ continue-on-error: true
# ── Compare & Report ───────────────────────────────────
- name: Compare against baselines
id: compare
@@ -80,7 +109,9 @@ jobs:
name: perf-results
path: |
packages/e2e-test-app-fabric/.perf-results/
+ packages/e2e-test-app-fabric/.native-perf-results/
packages/e2e-test-app-fabric/test/__perf__/**/__perf_snapshots__/
+ packages/e2e-test-app-fabric/test/__native_perf__/**/__perf_snapshots__/
retention-days: 30
# ── Status Gate ────────────────────────────────────────
diff --git a/change/@react-native-windows-automation-a4bcc22f-ba9f-409b-baeb-eac0e646b9d6.json b/change/@react-native-windows-automation-a4bcc22f-ba9f-409b-baeb-eac0e646b9d6.json
new file mode 100644
index 00000000000..49d47680c40
--- /dev/null
+++ b/change/@react-native-windows-automation-a4bcc22f-ba9f-409b-baeb-eac0e646b9d6.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "add native perf benchmarking infrastructure for Fabric components",
+ "packageName": "@react-native-windows/automation",
+ "email": "74712637+iamAbhi-916@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/@react-native-windows-perf-testing-4734971c-72bb-4389-b990-27e212a15295.json b/change/@react-native-windows-perf-testing-4734971c-72bb-4389-b990-27e212a15295.json
new file mode 100644
index 00000000000..0235cff197b
--- /dev/null
+++ b/change/@react-native-windows-perf-testing-4734971c-72bb-4389-b990-27e212a15295.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "add native perf benchmarking infrastructure for Fabric components",
+ "packageName": "@react-native-windows/perf-testing",
+ "email": "74712637+iamAbhi-916@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/@react-native-windows/automation/src/AutomationEnvironment.ts b/packages/@react-native-windows/automation/src/AutomationEnvironment.ts
index d12b3d4da9d..9088328a9d6 100644
--- a/packages/@react-native-windows/automation/src/AutomationEnvironment.ts
+++ b/packages/@react-native-windows/automation/src/AutomationEnvironment.ts
@@ -209,16 +209,24 @@ export default class AutomationEnvironment extends NodeEnvironment {
// Set up the "Desktop" or Root session
const rootBrowser = await webdriverio.remote(this.rootWebDriverOptions);
- // Get the list of windows
- const allWindows = await rootBrowser.$$('//Window');
-
- // Find our target window
+ // Poll for the app window with timeout (cold starts can be slow)
+ const windowTimeout = 300000; // 5 minutes
+ const pollInterval = 2000;
+ const deadline = Date.now() + windowTimeout;
let appWindow: webdriverio.Element | undefined;
- for (const window of allWindows) {
- if ((await window.getAttribute('Name')) === appName) {
- appWindow = window;
+
+ while (Date.now() < deadline) {
+ const allWindows = await rootBrowser.$$('//Window');
+ for (const window of allWindows) {
+ if ((await window.getAttribute('Name')) === appName) {
+ appWindow = window;
+ break;
+ }
+ }
+ if (appWindow) {
break;
}
+ await new Promise(resolve => setTimeout(resolve, pollInterval));
}
if (!appWindow) {
diff --git a/packages/@react-native-windows/perf-testing/src/config/thresholdPresets.ts b/packages/@react-native-windows/perf-testing/src/config/thresholdPresets.ts
index 3b1b260c488..02d6880c104 100644
--- a/packages/@react-native-windows/perf-testing/src/config/thresholdPresets.ts
+++ b/packages/@react-native-windows/perf-testing/src/config/thresholdPresets.ts
@@ -56,4 +56,14 @@ export const ThresholdPresets: Readonly<
maxCV: 0.6,
mode: 'track',
},
+
+ native: {
+ maxDurationIncrease: 15,
+ maxDuration: Infinity,
+ minAbsoluteDelta: 5,
+ maxRenderCount: 1,
+ minRuns: 10,
+ maxCV: 0.5,
+ mode: 'gate',
+ },
};
diff --git a/packages/@react-native-windows/tester/src/js/examples-win/NativePerfBenchmark/NativePerfBenchmarkExample.js b/packages/@react-native-windows/tester/src/js/examples-win/NativePerfBenchmark/NativePerfBenchmarkExample.js
new file mode 100644
index 00000000000..d0f48ed7cc4
--- /dev/null
+++ b/packages/@react-native-windows/tester/src/js/examples-win/NativePerfBenchmark/NativePerfBenchmarkExample.js
@@ -0,0 +1,265 @@
+/**
+ * Copyright (c) Microsoft Corporation.
+ * Licensed under the MIT License.
+ * @format
+ */
+
+'use strict';
+
+const React = require('react');
+const {
+ View,
+ Text,
+ TextInput,
+ Image,
+ ScrollView,
+ FlatList,
+ SectionList,
+ Switch,
+ ActivityIndicator,
+ Button,
+ Modal,
+ Pressable,
+ TouchableHighlight,
+ TouchableOpacity,
+ StyleSheet,
+} = require('react-native');
+
+const {useState, useRef, useCallback, useEffect} = React;
+
+const PHASE_IDLE = 'idle';
+const PHASE_CLEARING = 'clearing';
+const PHASE_MOUNTING = 'mounting';
+const PHASE_DONE = 'done';
+
+const COMPONENT_REGISTRY = {
+ View: () => ,
+ Text: () => Benchmark Text,
+ TextInput: () => (
+
+ ),
+ Image: () => (
+
+ ),
+ ScrollView: () => (
+
+ {Array.from({length: 20}, (_, i) => (
+
+ ))}
+
+ ),
+ FlatList: () => (
+ ({key: String(i)}))}
+ renderItem={({item}) => {item.key}}
+ />
+ ),
+ SectionList: () => (
+ {item}}
+ renderSectionHeader={({section}) => {section.title}}
+ />
+ ),
+ Switch: () => ,
+ ActivityIndicator: () => ,
+ Button: () =>