Skip to content

Commit 1139b02

Browse files
committed
Add RenderComponentThroughput benchmark
1 parent 2412a7f commit 1139b02

File tree

10 files changed

+275
-79
lines changed

10 files changed

+275
-79
lines changed

App.js

Lines changed: 43 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,61 @@
11
/**
2-
* Sample React Native App
3-
* https://github.com/facebook/react-native
4-
*
52
* @format
63
* @flow
74
*/
85

9-
import React, {Fragment} from 'react';
10-
import {
11-
SafeAreaView,
12-
StyleSheet,
13-
ScrollView,
14-
View,
15-
Text,
16-
StatusBar,
17-
} from 'react-native';
6+
import React, { useEffect, useState } from 'react';
7+
import { View, Text, Linking, StyleSheet } from 'react-native';
8+
import URL from 'url-parse';
189

19-
import {
20-
Header,
21-
LearnMoreLinks,
22-
Colors,
23-
DebugInstructions,
24-
ReloadInstructions,
25-
} from 'react-native/Libraries/NewAppScreen';
10+
const ROUTES = {
11+
'/RenderComponentThroughput': require('./src/ReactRender/RenderComponentThroughput').default,
12+
};
13+
14+
const NotFoundView = () => (
15+
<View style={styles.notFoundView}>
16+
<Text style={styles.notFoundText}>View not found</Text>
17+
</View>
18+
);
2619

2720
const App = () => {
21+
const [route, setRoute] = useState(null);
22+
useEffect(() => {
23+
async function setupInitialRoute() {
24+
const initialUrl = await Linking.getInitialURL();
25+
if (initialUrl && initialUrl.startsWith('rnbench://')) {
26+
const url = new URL(initialUrl, '', true);
27+
setRoute(url);
28+
}
29+
}
30+
31+
setupInitialRoute();
32+
}, []);
33+
2834
return (
29-
<Fragment>
30-
<StatusBar barStyle="dark-content" />
31-
<SafeAreaView>
32-
<ScrollView
33-
contentInsetAdjustmentBehavior="automatic"
34-
style={styles.scrollView}>
35-
<Header />
36-
<View style={styles.body}>
37-
<View style={styles.sectionContainer}>
38-
<Text style={styles.sectionTitle}>Step One</Text>
39-
<Text style={styles.sectionDescription}>
40-
Edit <Text style={styles.highlight}>App.js</Text> to change this
41-
screen and then come back to see your edits.
42-
</Text>
43-
</View>
44-
<View style={styles.sectionContainer}>
45-
<Text style={styles.sectionTitle}>See Your Changes</Text>
46-
<Text style={styles.sectionDescription}>
47-
<ReloadInstructions />
48-
</Text>
49-
</View>
50-
<View style={styles.sectionContainer}>
51-
<Text style={styles.sectionTitle}>Debug</Text>
52-
<Text style={styles.sectionDescription}>
53-
<DebugInstructions />
54-
</Text>
55-
</View>
56-
<View style={styles.sectionContainer}>
57-
<Text style={styles.sectionTitle}>Learn More</Text>
58-
<Text style={styles.sectionDescription}>
59-
Read the docs to discover what to do next:
60-
</Text>
61-
</View>
62-
<LearnMoreLinks />
63-
</View>
64-
</ScrollView>
65-
</SafeAreaView>
66-
</Fragment>
35+
<View style={styles.container}>
36+
{route != null && ROUTES[route.pathname] != null ? (
37+
React.createElement(ROUTES[route.pathname], route.query)
38+
) : (
39+
<NotFoundView />
40+
)}
41+
</View>
6742
);
6843
};
6944

7045
const styles = StyleSheet.create({
71-
scrollView: {
72-
backgroundColor: Colors.lighter,
73-
},
74-
body: {
75-
backgroundColor: Colors.white,
76-
},
77-
sectionContainer: {
78-
marginTop: 32,
79-
paddingHorizontal: 24,
80-
},
81-
sectionTitle: {
82-
fontSize: 24,
83-
fontWeight: '600',
84-
color: Colors.black,
46+
container: {
47+
flex: 1,
8548
},
86-
sectionDescription: {
87-
marginTop: 8,
88-
fontSize: 18,
89-
fontWeight: '400',
90-
color: Colors.dark,
49+
notFoundView: {
50+
flex: 1,
51+
backgroundColor: 'rgb(192, 186, 48)',
52+
flexDirection: 'column',
53+
justifyContent: 'center',
9154
},
92-
highlight: {
93-
fontWeight: '700',
55+
notFoundText: {
56+
color: 'rgb(255, 255, 255)',
57+
fontSize: 32,
58+
textAlign: 'center',
9459
},
9560
});
9661

android/jsc/build.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ repositories {
55
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
66
url("$rootDir/../node_modules/react-native/android")
77
}
8+
9+
if (project.hasProperty("JSC_DIST_REPO")) {
10+
maven {
11+
url(project.findProperty("JSC_DIST_REPO"))
12+
}
13+
}
14+
815
maven {
916
// Android JSC is installed from npm
1017
url("$rootDir/../node_modules/jsc-android/dist")

android/jsc/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
<action android:name="android.intent.action.MAIN" />
2020
<category android:name="android.intent.category.LAUNCHER" />
2121
</intent-filter>
22+
23+
<intent-filter>
24+
<action android:name="android.intent.action.VIEW" />
25+
<category android:name="android.intent.category.DEFAULT" />
26+
<data android:scheme="rnbench" android:host="jsc" />
27+
</intent-filter>
2228
</activity>
2329
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
2430
</application>

android/v8/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
apply plugin: "com.android.application"
22

33
repositories {
4+
if (project.hasProperty("V8_DIST_REPO")) {
5+
maven {
6+
url(project.findProperty("V8_DIST_REPO"))
7+
}
8+
}
9+
410
maven {
511
url("$rootDir/../node_modules/react-native-v8/dist")
612
}

android/v8/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
<action android:name="android.intent.action.MAIN" />
2020
<category android:name="android.intent.category.LAUNCHER" />
2121
</intent-filter>
22+
23+
<intent-filter>
24+
<action android:name="android.intent.action.VIEW" />
25+
<category android:name="android.intent.category.DEFAULT" />
26+
<data android:scheme="rnbench" android:host="v8" />
27+
</intent-filter>
2228
</activity>
2329
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
2430
</application>

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
"lint": "eslint ."
99
},
1010
"dependencies": {
11+
"jsc-android": "^245459.0.0",
1112
"react": "16.8.6",
12-
"react-native": "0.60.0-rc.2"
13+
"react-native": "0.60.0-rc.2",
14+
"react-native-v8": "^0.60.0-rc.2",
15+
"url-parse": "^1.4.7"
1316
},
1417
"devDependencies": {
1518
"@babel/core": "^7.4.5",

prettier.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
'trailingComma': 'es5',
3+
'singleQuote': true,
4+
'printWidth': 100,
5+
'requirePragma': true,
6+
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* @format
3+
* @flow
4+
*/
5+
6+
import React, { useEffect, useLayoutEffect, useState, useRef } from 'react';
7+
import { ScrollView, View, Text, StyleSheet } from 'react-native';
8+
9+
const Child = ({ id, onMount }) => {
10+
useLayoutEffect(() => {
11+
onMount(id);
12+
}, [id, onMount]);
13+
14+
return (
15+
<View style={styles.child}>
16+
<Text style={styles.childText}>{id}</Text>
17+
</View>
18+
);
19+
};
20+
21+
const RenderComponentThroughput = ({ interval }) => {
22+
const [children, setChildren] = useState([0]);
23+
const [shouldContinue, setShouldContinue] = useState(true);
24+
const latestChildren = useRef(children);
25+
26+
function appendChild(id) {
27+
setTimeout(() => setChildren(array => [...array, id]), 0);
28+
}
29+
30+
function handleChildDidMount(id) {
31+
if (shouldContinue && id === children.length - 1) {
32+
appendChild(id + 1);
33+
}
34+
}
35+
36+
useEffect(() => {
37+
latestChildren.current = children;
38+
});
39+
40+
useEffect(() => {
41+
// eslint-disable-next-line no-bitwise
42+
const intervalInt = interval | 0;
43+
setTimeout(() => {
44+
setShouldContinue(false);
45+
console.log(`count=${latestChildren.current.length}`);
46+
}, intervalInt);
47+
}, [interval]);
48+
49+
return (
50+
<ScrollView style={styles.scrollView}>
51+
{children.map(i => (
52+
<Child key={i} id={i} onMount={handleChildDidMount} />
53+
))}
54+
</ScrollView>
55+
);
56+
};
57+
58+
const styles = StyleSheet.create({
59+
scrollView: {
60+
flex: 1,
61+
},
62+
child: {
63+
alignSelf: 'center',
64+
width: 120,
65+
height: 16,
66+
marginVertical: 8,
67+
backgroundColor: 'lightblue',
68+
},
69+
childText: {
70+
textAlign: 'center',
71+
},
72+
});
73+
74+
export default RenderComponentThroughput;

start.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env python
2+
import os
3+
import re
4+
import subprocess
5+
6+
class AdbTool:
7+
@classmethod
8+
def wait_for_console_log(cls, regex):
9+
pattern = re.compile(r'ReactNativeJS: ' + regex)
10+
cmd = ['adb', 'logcat']
11+
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as proc:
12+
for line_in_bytes in iter(proc.stdout.readline, ''):
13+
line = line_in_bytes.decode('utf8')
14+
search = pattern.search(line)
15+
if search is not None:
16+
proc.terminate()
17+
return search
18+
19+
@classmethod
20+
def clear_log(cls):
21+
os.system('adb logcat -c')
22+
23+
24+
@classmethod
25+
def stop_app(cls, app_id):
26+
os.system('adb shell am force-stop com.rnbenchmark.{}'.format(app_id))
27+
os.system('adb shell am kill com.rnbenchmark.{}'.format(app_id))
28+
29+
@classmethod
30+
def stop_apps(cls):
31+
cls.stop_app('jsc')
32+
cls.stop_app('v8')
33+
34+
@classmethod
35+
def start_with_link(cls, app_id, path_with_query):
36+
os.system( \
37+
'adb shell am start -a android.intent.action.VIEW -d "rnbench://{}{}"' \
38+
' > /dev/null'
39+
.format(app_id, path_with_query))
40+
41+
class ApkTool:
42+
@classmethod
43+
def reinstall(cls, app_id):
44+
os.chdir('android')
45+
os.system( \
46+
'./gradlew :{app}:clean :{app}:uninstallRelease :{app}:installRelease'
47+
.format(app=app_id))
48+
os.chdir('../')
49+
50+
51+
class RenderComponentThroughput:
52+
def __init__(self, app_id, interval):
53+
self._app_id = app_id
54+
self._interval = interval
55+
56+
def run(self):
57+
AdbTool.stop_apps()
58+
AdbTool.clear_log()
59+
AdbTool.start_with_link(
60+
self._app_id,
61+
'/RenderComponentThroughput?interval={}'.format(self._interval))
62+
result = AdbTool.wait_for_console_log(r'count=(\d+)').group(1)
63+
return result
64+
65+
66+
def main():
67+
ApkTool.reinstall('jsc')
68+
ApkTool.reinstall('v8')
69+
70+
for _ in range(3):
71+
print('=========== RenderComponentThroughput 10s ===========')
72+
print('jsc', RenderComponentThroughput('jsc', 10000).run())
73+
print('v8', RenderComponentThroughput('v8', 10000).run())
74+
75+
print('=========== RenderComponentThroughput 60s ===========')
76+
print('jsc', RenderComponentThroughput('jsc', 60000).run())
77+
print('v8', RenderComponentThroughput('v8', 60000).run())
78+
79+
print('=========== RenderComponentThroughput 180s ===========')
80+
print('jsc', RenderComponentThroughput('jsc', 180000).run())
81+
print('v8', RenderComponentThroughput('v8', 180000).run())
82+
83+
return 0
84+
85+
if __name__ == '__main__':
86+
root_dir = os.path.dirname(os.path.realpath(__file__))
87+
os.chdir(root_dir)
88+
main()

0 commit comments

Comments
 (0)