Skip to content

Commit f711d17

Browse files
sammy-SCfacebook-github-bot
authored andcommitted
Micro-optimise JavaScript part of Animated (#52906)
Summary: Pull Request resolved: #52906 changelog: [internal] Micro-optimise JavaScript part of Animated by avoiding JS syntax for private variable/method - #foo. Instead, use double underscores. Benchmarks indicate ~10% improvement. # Before ### Animated (mode 🚀) ### | (index) | Task name | Latency average (ns) | Latency median (ns) | Throughput average (ops/s) | Throughput median (ops/s) | Samples | | ------- | ---------------------------------------------------------------------------- | --------------------- | ------------------------ | -------------------------- | ------------------------- | ------- | | 0 | 'render 1 views' | '84990.06 ± 1.49%' | '80691.00' | '12164 ± 0.14%' | '12393' | 11767 | | 1 | 'render 10 views' | '373372.50 ± 1.00%' | '363786.00' | '2727 ± 0.26%' | '2749' | 2679 | | 2 | 'render 100 views' | '3099588.37 ± 0.92%' | '3017559.00' | '324 ± 0.74%' | '331' | 323 | | 3 | 'render 1 animated views (without animations set up)' | '174636.87 ± 0.67%' | '168783.00' | '5808 ± 0.17%' | '5925' | 5727 | | 4 | 'render 10 animated views (without animations set up)' | '1054481.51 ± 0.61%' | '1036686.00' | '953 ± 0.37%' | '965' | 949 | | 5 | 'render 100 animated views (without animations set up)' | '9176283.60 ± 1.12%' | '8932316.00' | '109 ± 0.95%' | '112' | 109 | | 6 | 'render 1 animated views (with a single animation set up - JS driven)' | '204383.77 ± 0.52%' | '199109.00' | '4943 ± 0.17%' | '5022' | 4893 | | 7 | 'render 10 animated views (with a single animation set up - JS driven)' | '1315894.97 ± 0.36%' | '1300562.00 ± 40.00' | '762 ± 0.30%' | '769' | 760 | | 8 | 'render 100 animated views (with a single animation set up - JS driven)' | '11924031.45 ± 1.36%' | '11753334.50 ± 30040.50' | '84 ± 1.18%' | '85' | 84 | | 9 | 'render 1 animated views (with a single animation set up - native driven)' | '318103.70 ± 0.37%' | '311657.50 ± 0.50' | '3162 ± 0.20%' | '3209' | 3144 | | 10 | 'render 10 animated views (with a single animation set up - native driven)' | '2230305.96 ± 0.51%' | '2191890.00' | '449 ± 0.41%' | '456' | 449 | | 11 | 'render 100 animated views (with a single animation set up - native driven)' | '21983695.16 ± 0.75%' | '21945687.00 ± 17186.00' | '46 ± 0.74%' | '46' | 64 | # After ### Animated (mode 🚀) ### | (index) | Task name | Latency average (ns) | Latency median (ns) | Throughput average (ops/s) | Throughput median (ops/s) | Samples | | ------- | ---------------------------------------------------------------------------- | --------------------- | ----------------------- | -------------------------- | ------------------------- | ------- | | 0 | 'render 1 views' | '82684.75 ± 1.11%' | '80231.00' | '12331 ± 0.08%' | '12464' | 12095 | | 1 | 'render 10 views' | '378798.65 ± 1.16%' | '365378.50 ± 9.50' | '2703 ± 0.31%' | '2737' | 2640 | | 2 | 'render 100 views' | '3124253.51 ± 0.95%' | '3039842.00' | '322 ± 0.76%' | '329' | 321 | | 3 | 'render 1 animated views (without animations set up)' | '165580.70 ± 0.73%' | '161562.00' | '6131 ± 0.14%' | '6190' | 6040 | | 4 | 'render 10 animated views (without animations set up)' | '979127.10 ± 0.60%' | '962509.50 ± 5.50' | '1027 ± 0.36%' | '1039' | 1022 | | 5 | 'render 100 animated views (without animations set up)' | '8487740.98 ± 1.32%' | '8235139.50 ± 3244.50' | '118 ± 1.05%' | '121' | 118 | | 6 | 'render 1 animated views (with a single animation set up - JS driven)' | '185333.93 ± 0.52%' | '181582.00' | '5451 ± 0.15%' | '5507' | 5396 | | 7 | 'render 10 animated views (with a single animation set up - JS driven)' | '1145679.81 ± 0.37%' | '1131668.00' | '875 ± 0.29%' | '884' | 873 | | 8 | 'render 100 animated views (with a single animation set up - JS driven)' | '10451056.69 ± 1.60%' | '10064069.50 ± 826.50' | '96 ± 1.39%' | '99' | 96 | | 9 | 'render 1 animated views (with a single animation set up - native driven)' | '292243.89 ± 0.40%' | '286740.00' | '3447 ± 0.21%' | '3487' | 3422 | | 10 | 'render 10 animated views (with a single animation set up - native driven)' | '1993053.78 ± 0.47%' | '1958960.00 ± 20.00' | '503 ± 0.39%' | '510' | 502 | | 11 | 'render 100 animated views (with a single animation set up - native driven)' | '19528221.48 ± 0.95%' | '19383511.00 ± 7431.00' | '51 ± 0.92%' | '52' | 64 | Reviewed By: rubennorte Differential Revision: D79179369 fbshipit-source-id: e641be0e8ec313b58bcae8330f127e707cd4fffc
1 parent 0d3791c commit f711d17

File tree

7 files changed

+97
-97
lines changed

7 files changed

+97
-97
lines changed

packages/react-native/Libraries/Animated/animations/Animation.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ let startNativeAnimationNextId = 1;
4141
// Once an animation has been stopped or finished its course, it will
4242
// not be reused.
4343
export default class Animation {
44-
#nativeID: ?number;
45-
#onEnd: ?EndCallback;
46-
#useNativeDriver: boolean;
44+
_nativeID: ?number;
45+
_onEnd: ?EndCallback;
46+
_useNativeDriver: boolean;
4747

4848
__active: boolean;
4949
__isInteraction: boolean;
@@ -52,10 +52,10 @@ export default class Animation {
5252
__debugID: ?string;
5353

5454
constructor(config: AnimationConfig) {
55-
this.#useNativeDriver = NativeAnimatedHelper.shouldUseNativeDriver(config);
55+
this._useNativeDriver = NativeAnimatedHelper.shouldUseNativeDriver(config);
5656

5757
this.__active = false;
58-
this.__isInteraction = config.isInteraction ?? !this.#useNativeDriver;
58+
this.__isInteraction = config.isInteraction ?? !this._useNativeDriver;
5959
this.__isLooping = config.isLooping;
6060
this.__iterations = config.iterations ?? 1;
6161
if (__DEV__) {
@@ -70,21 +70,21 @@ export default class Animation {
7070
previousAnimation: ?Animation,
7171
animatedValue: AnimatedValue,
7272
): void {
73-
if (!this.#useNativeDriver && animatedValue.__isNative === true) {
73+
if (!this._useNativeDriver && animatedValue.__isNative === true) {
7474
throw new Error(
7575
'Attempting to run JS driven animation on animated node ' +
7676
'that has been moved to "native" earlier by starting an ' +
7777
'animation with `useNativeDriver: true`',
7878
);
7979
}
8080

81-
this.#onEnd = onEnd;
81+
this._onEnd = onEnd;
8282
this.__active = true;
8383
}
8484

8585
stop(): void {
86-
if (this.#nativeID != null) {
87-
const nativeID = this.#nativeID;
86+
if (this._nativeID != null) {
87+
const nativeID = this._nativeID;
8888
const identifier = `${nativeID}:stopAnimation`;
8989
try {
9090
// This is only required when singleOpBatching is used, as otherwise
@@ -123,7 +123,7 @@ export default class Animation {
123123
}
124124

125125
__startAnimationIfNative(animatedValue: AnimatedValue): boolean {
126-
if (!this.#useNativeDriver) {
126+
if (!this._useNativeDriver) {
127127
return false;
128128
}
129129

@@ -135,9 +135,9 @@ export default class Animation {
135135
try {
136136
const config = this.__getNativeAnimationConfig();
137137
animatedValue.__makeNative(config.platformConfig);
138-
this.#nativeID = NativeAnimatedHelper.generateNewAnimationId();
138+
this._nativeID = NativeAnimatedHelper.generateNewAnimationId();
139139
NativeAnimatedHelper.API.startAnimatingNode(
140-
this.#nativeID,
140+
this._nativeID,
141141
animatedValue.__getNativeTag(),
142142
config,
143143
result => {
@@ -185,9 +185,9 @@ export default class Animation {
185185
* callback will never be called more than once.
186186
*/
187187
__notifyAnimationEnd(result: EndResult): void {
188-
const callback = this.#onEnd;
188+
const callback = this._onEnd;
189189
if (callback != null) {
190-
this.#onEnd = null;
190+
this._onEnd = null;
191191
callback(result);
192192
}
193193
}

packages/react-native/Libraries/Animated/nodes/AnimatedNode.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ let _assertNativeAnimatedModule: ?() => void = () => {
2828
};
2929

3030
export default class AnimatedNode {
31-
#listeners: Map<string, ValueListenerCallback>;
31+
_listeners: Map<string, ValueListenerCallback>;
3232

3333
_platformConfig: ?PlatformConfig = undefined;
3434

@@ -38,7 +38,7 @@ export default class AnimatedNode {
3838
...
3939
}>,
4040
) {
41-
this.#listeners = new Map();
41+
this._listeners = new Map();
4242
if (__DEV__) {
4343
this.__debugID = config?.debugID;
4444
}
@@ -85,7 +85,7 @@ export default class AnimatedNode {
8585
*/
8686
addListener(callback: (value: any) => mixed): string {
8787
const id = String(_uniqueId++);
88-
this.#listeners.set(id, callback);
88+
this._listeners.set(id, callback);
8989
return id;
9090
}
9191

@@ -96,7 +96,7 @@ export default class AnimatedNode {
9696
* See https://reactnative.dev/docs/animatedvalue#removelistener
9797
*/
9898
removeListener(id: string): void {
99-
this.#listeners.delete(id);
99+
this._listeners.delete(id);
100100
}
101101

102102
/**
@@ -105,11 +105,11 @@ export default class AnimatedNode {
105105
* See https://reactnative.dev/docs/animatedvalue#removealllisteners
106106
*/
107107
removeAllListeners(): void {
108-
this.#listeners.clear();
108+
this._listeners.clear();
109109
}
110110

111111
hasListeners(): boolean {
112-
return this.#listeners.size > 0;
112+
return this._listeners.size > 0;
113113
}
114114

115115
__onAnimatedValueUpdateReceived(value: number, offset: number): void {
@@ -118,7 +118,7 @@ export default class AnimatedNode {
118118

119119
__callListeners(value: number): void {
120120
const event = {value};
121-
this.#listeners.forEach(listener => {
121+
this._listeners.forEach(listener => {
122122
listener(event);
123123
});
124124
}

packages/react-native/Libraries/Animated/nodes/AnimatedObject.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ function mapAnimatedNodes(value: any, fn: any => any, depth: number = 0): any {
8282
}
8383

8484
export default class AnimatedObject extends AnimatedWithChildren {
85-
#nodes: $ReadOnlyArray<AnimatedNode>;
85+
_nodes: $ReadOnlyArray<AnimatedNode>;
8686
_value: mixed;
8787

8888
/**
@@ -106,7 +106,7 @@ export default class AnimatedObject extends AnimatedWithChildren {
106106
config?: ?AnimatedNodeConfig,
107107
) {
108108
super(config);
109-
this.#nodes = nodes;
109+
this._nodes = nodes;
110110
this._value = value;
111111
}
112112

@@ -117,7 +117,7 @@ export default class AnimatedObject extends AnimatedWithChildren {
117117
}
118118

119119
__getValueWithStaticObject(staticObject: mixed): any {
120-
const nodes = this.#nodes;
120+
const nodes = this._nodes;
121121
let index = 0;
122122
// NOTE: We can depend on `this._value` and `staticObject` sharing a
123123
// structure because of `useAnimatedPropsMemo`.
@@ -131,7 +131,7 @@ export default class AnimatedObject extends AnimatedWithChildren {
131131
}
132132

133133
__attach(): void {
134-
const nodes = this.#nodes;
134+
const nodes = this._nodes;
135135
for (let ii = 0, length = nodes.length; ii < length; ii++) {
136136
const node = nodes[ii];
137137
node.__addChild(this);
@@ -140,7 +140,7 @@ export default class AnimatedObject extends AnimatedWithChildren {
140140
}
141141

142142
__detach(): void {
143-
const nodes = this.#nodes;
143+
const nodes = this._nodes;
144144
for (let ii = 0, length = nodes.length; ii < length; ii++) {
145145
const node = nodes[ii];
146146
node.__removeChild(this);
@@ -149,7 +149,7 @@ export default class AnimatedObject extends AnimatedWithChildren {
149149
}
150150

151151
__makeNative(platformConfig: ?PlatformConfig): void {
152-
const nodes = this.#nodes;
152+
const nodes = this._nodes;
153153
for (let ii = 0, length = nodes.length; ii < length; ii++) {
154154
const node = nodes[ii];
155155
node.__makeNative(platformConfig);

packages/react-native/Libraries/Animated/nodes/AnimatedProps.js

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,11 @@ function createAnimatedProps(
9292
}
9393

9494
export default class AnimatedProps extends AnimatedNode {
95-
#callback: () => void;
96-
#nodeKeys: $ReadOnlyArray<string>;
97-
#nodes: $ReadOnlyArray<AnimatedNode>;
98-
#props: {[string]: mixed};
99-
#target: ?TargetView = null;
95+
_callback: () => void;
96+
_nodeKeys: $ReadOnlyArray<string>;
97+
_nodes: $ReadOnlyArray<AnimatedNode>;
98+
_props: {[string]: mixed};
99+
_target: ?TargetView = null;
100100

101101
constructor(
102102
inputProps: {[string]: mixed},
@@ -106,19 +106,19 @@ export default class AnimatedProps extends AnimatedNode {
106106
) {
107107
super(config);
108108
const [nodeKeys, nodes, props] = createAnimatedProps(inputProps, allowlist);
109-
this.#nodeKeys = nodeKeys;
110-
this.#nodes = nodes;
111-
this.#props = props;
112-
this.#callback = callback;
109+
this._nodeKeys = nodeKeys;
110+
this._nodes = nodes;
111+
this._props = props;
112+
this._callback = callback;
113113
}
114114

115115
__getValue(): Object {
116116
const props: {[string]: mixed} = {};
117117

118-
const keys = Object.keys(this.#props);
118+
const keys = Object.keys(this._props);
119119
for (let ii = 0, length = keys.length; ii < length; ii++) {
120120
const key = keys[ii];
121-
const value = this.#props[key];
121+
const value = this._props[key];
122122

123123
if (value instanceof AnimatedNode) {
124124
props[key] = value.__getValue();
@@ -143,7 +143,7 @@ export default class AnimatedProps extends AnimatedNode {
143143
const keys = Object.keys(staticProps);
144144
for (let ii = 0, length = keys.length; ii < length; ii++) {
145145
const key = keys[ii];
146-
const maybeNode = this.#props[key];
146+
const maybeNode = this._props[key];
147147

148148
if (key === 'style') {
149149
const staticStyle = staticProps.style;
@@ -176,10 +176,10 @@ export default class AnimatedProps extends AnimatedNode {
176176
__getNativeAnimatedEventTuples(): $ReadOnlyArray<[string, AnimatedEvent]> {
177177
const tuples = [];
178178

179-
const keys = Object.keys(this.#props);
179+
const keys = Object.keys(this._props);
180180
for (let ii = 0, length = keys.length; ii < length; ii++) {
181181
const key = keys[ii];
182-
const value = this.#props[key];
182+
const value = this._props[key];
183183

184184
if (value instanceof AnimatedEvent && value.__isNative) {
185185
tuples.push([key, value]);
@@ -192,8 +192,8 @@ export default class AnimatedProps extends AnimatedNode {
192192
__getAnimatedValue(): Object {
193193
const props: {[string]: mixed} = {};
194194

195-
const nodeKeys = this.#nodeKeys;
196-
const nodes = this.#nodes;
195+
const nodeKeys = this._nodeKeys;
196+
const nodes = this._nodes;
197197
for (let ii = 0, length = nodes.length; ii < length; ii++) {
198198
const key = nodeKeys[ii];
199199
const node = nodes[ii];
@@ -204,7 +204,7 @@ export default class AnimatedProps extends AnimatedNode {
204204
}
205205

206206
__attach(): void {
207-
const nodes = this.#nodes;
207+
const nodes = this._nodes;
208208
for (let ii = 0, length = nodes.length; ii < length; ii++) {
209209
const node = nodes[ii];
210210
node.__addChild(this);
@@ -213,12 +213,12 @@ export default class AnimatedProps extends AnimatedNode {
213213
}
214214

215215
__detach(): void {
216-
if (this.__isNative && this.#target != null) {
217-
this.#disconnectAnimatedView(this.#target);
216+
if (this.__isNative && this._target != null) {
217+
this.#disconnectAnimatedView(this._target);
218218
}
219-
this.#target = null;
219+
this._target = null;
220220

221-
const nodes = this.#nodes;
221+
const nodes = this._nodes;
222222
for (let ii = 0, length = nodes.length; ii < length; ii++) {
223223
const node = nodes[ii];
224224
node.__removeChild(this);
@@ -228,11 +228,11 @@ export default class AnimatedProps extends AnimatedNode {
228228
}
229229

230230
update(): void {
231-
this.#callback();
231+
this._callback();
232232
}
233233

234234
__makeNative(platformConfig: ?PlatformConfig): void {
235-
const nodes = this.#nodes;
235+
const nodes = this._nodes;
236236
for (let ii = 0, length = nodes.length; ii < length; ii++) {
237237
const node = nodes[ii];
238238
node.__makeNative(platformConfig);
@@ -246,19 +246,19 @@ export default class AnimatedProps extends AnimatedNode {
246246
// where it will be needed to traverse the graph of attached values.
247247
super.__setPlatformConfig(platformConfig);
248248

249-
if (this.#target != null) {
250-
this.#connectAnimatedView(this.#target);
249+
if (this._target != null) {
250+
this.#connectAnimatedView(this._target);
251251
}
252252
}
253253
}
254254

255255
setNativeView(instance: TargetViewInstance): void {
256-
if (this.#target?.instance === instance) {
256+
if (this._target?.instance === instance) {
257257
return;
258258
}
259-
this.#target = {instance, connectedViewTag: null};
259+
this._target = {instance, connectedViewTag: null};
260260
if (this.__isNative) {
261-
this.#connectAnimatedView(this.#target);
261+
this.#connectAnimatedView(this._target);
262262
}
263263
}
264264

@@ -306,8 +306,8 @@ export default class AnimatedProps extends AnimatedNode {
306306
const platformConfig = this.__getPlatformConfig();
307307
const propsConfig: {[string]: number} = {};
308308

309-
const nodeKeys = this.#nodeKeys;
310-
const nodes = this.#nodes;
309+
const nodeKeys = this._nodeKeys;
310+
const nodes = this._nodes;
311311
for (let ii = 0, length = nodes.length; ii < length; ii++) {
312312
const key = nodeKeys[ii];
313313
const node = nodes[ii];

0 commit comments

Comments
 (0)