From d2fa1cd9003a852d23c624dfff57b65ca8f3fb2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Mon, 28 Jul 2025 10:02:25 -0700 Subject: [PATCH] Create basic benchmark for Animated (#52874) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52874 Changelog: [internal] This creates a basic benchmark for the Animated API, which shows that **using Animated**, even without setting up animations, **makes rendering 3x slower** (similar when setting up a JS driven animation), but **6x slower when it sets up a native animation.** Baseline: ### Animated (mode 🚀) ### | (index) | Task name | Latency average (ns) | Latency median (ns) | Throughput average (ops/s) | Throughput median (ops/s) | Samples | | ------- | ---------------------------------------------------------------------------- | --------------------- | ----------------------- | -------------------------- | ------------------------- | ------- | | 0 | 'render 1 views' | '85320.76 ± 1.27%' | '82484.00' | '11994 ± 0.09%' | '12124' | 11721 | | 1 | 'render 10 views' | '399462.22 ± 1.03%' | '387702.00' | '2552 ± 0.29%' | '2579' | 2505 | | 2 | 'render 100 views' | '3317795.78 ± 0.90%' | '3232351.00 ± 70.00' | '303 ± 0.74%' | '309' | 302 | | 3 | 'render 1 animated views (without no animations set up)' | '172534.31 ± 0.67%' | '168423.00' | '5874 ± 0.14%' | '5937' | 5796 | | 4 | 'render 10 animated views (without no animations set up)' | '1050582.87 ± 0.63%' | '1031899.00 ± 20.00' | '957 ± 0.37%' | '969' | 952 | | 5 | 'render 100 animated views (without no animations set up)' | '9255133.10 ± 1.06%' | '8990333.00' | '108 ± 0.94%' | '111' | 109 | | 6 | 'render 1 animated views (with a single animation set up - JS driven)' | '203422.03 ± 0.50%' | '198478.00' | '4966 ± 0.17%' | '5038' | 4916 | | 7 | 'render 10 animated views (with a single animation set up - JS driven)' | '1305600.39 ± 0.37%' | '1288088.00 ± 15.00' | '768 ± 0.30%' | '776' | 766 | | 8 | 'render 100 animated views (with a single animation set up - JS driven)' | '12084658.14 ± 1.51%' | '11854181.00 ± 8493.00' | '83 ± 1.27%' | '84' | 84 | | 9 | 'render 1 animated views (with a single animation set up - native driven)' | '313494.69 ± 0.32%' | '308673.00' | '3206 ± 0.19%' | '3240' | 3190 | | 10 | 'render 10 animated views (with a single animation set up - native driven)' | '2223507.22 ± 0.50%' | '2184839.00 ± 70.00' | '451 ± 0.41%' | '458' | 450 | | 11 | 'render 100 animated views (with a single animation set up - native driven)' | '21352575.02 ± 0.71%' | '21239136.00 ± 2824.00' | '47 ± 0.69%' | '47' | 64 | Reviewed By: christophpurrer Differential Revision: D79085920 fbshipit-source-id: 1dc13208da49cc325995f3455eaf86c4eb1e4d47 --- .../__tests__/Animated-benchmark-itest.js | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 packages/react-native/Libraries/Animated/__tests__/Animated-benchmark-itest.js diff --git a/packages/react-native/Libraries/Animated/__tests__/Animated-benchmark-itest.js b/packages/react-native/Libraries/Animated/__tests__/Animated-benchmark-itest.js new file mode 100644 index 00000000000..8e5e2c41633 --- /dev/null +++ b/packages/react-native/Libraries/Animated/__tests__/Animated-benchmark-itest.js @@ -0,0 +1,133 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment'; + +import * as Fantom from '@react-native/fantom'; +import * as React from 'react'; +import {Animated, View, useAnimatedValue} from 'react-native'; + +function MyApp() { + return ( + + ); +} + +function MyAnimatedApp() { + return ( + + ); +} + +function MyAnimatedAppWithAnimation() { + const opacity = useAnimatedValue(1); + + return ( + + ); +} + +function MyAnimatedAppWithNativeAnimation() { + const opacity = useAnimatedValue(1, {useNativeDriver: true}); + + return ( + + ); +} + +const ARGS = [1, 10, 100]; + +let root = Fantom.createRoot(); +let element: React.MixedElement; + +function renderElement() { + Fantom.runTask(() => root.render(element)); +} + +function getOptions( + numberOfComponents: number, + Component: React.ComponentType<{}>, +): Fantom.BenchmarkTestOptions { + return { + beforeAll: () => { + element = ( + <> + {Array.from({length: numberOfComponents}, (_, i) => ( + + ))} + + ); + }, + beforeEach: () => { + Fantom.runTask(() => root.render(<>)); + }, + }; +} + +Fantom.unstable_benchmark + .suite('Animated') + .test.each( + ARGS, + n => `render ${n} views`, + renderElement, + n => getOptions(n, MyApp), + ) + .test.each( + ARGS, + n => `render ${n} animated views (without animations set up)`, + renderElement, + n => getOptions(n, MyAnimatedApp), + ) + .test.each( + ARGS, + n => + `render ${n} animated views (with a single animation set up - JS driven)`, + renderElement, + n => getOptions(n, MyAnimatedAppWithAnimation), + ) + .test.each( + ARGS, + n => + `render ${n} animated views (with a single animation set up - native driven)`, + renderElement, + n => getOptions(n, MyAnimatedAppWithNativeAnimation), + );