Skip to content

Commit b5c6da1

Browse files
committed
Port our microbenchmarks to the new world (flutter#4121)
Our microbenchmarks now run on real devices.
1 parent 4764550 commit b5c6da1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+524
-209
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.DS_Store
2+
.atom/
3+
.idea
4+
.packages
5+
.pub/
6+
build/
7+
ios/.generated/
8+
packages
9+
pubspec.lock
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# microbenchmarks
2+
3+
To run these benchmarks on a device:
4+
5+
```
6+
flutter run --release -t lib/gestures/velocity_tracker_data.dart
7+
flutter run --release -t lib/stocks/animation_bench.dart
8+
flutter run --release -t lib/stocks/build_bench.dart
9+
flutter run --release -t lib/stocks/layout_bench.dart
10+
```
11+
12+
The results should be in the device logs.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="com.yourcompany.microbenchmarks"
3+
android:versionCode="1"
4+
android:versionName="0.0.1">
5+
6+
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
7+
<uses-permission android:name="android.permission.INTERNET"/>
8+
9+
<application android:name="org.domokit.sky.shell.SkyApplication" android:label="microbenchmarks" android:icon="@mipmap/ic_launcher">
10+
<activity android:name="org.domokit.sky.shell.SkyActivity"
11+
android:launchMode="singleTop"
12+
android:theme="@android:style/Theme.Black.NoTitleBar"
13+
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
14+
android:hardwareAccelerated="true"
15+
android:windowSoftInputMode="adjustResize">
16+
<intent-filter>
17+
<action android:name="android.intent.action.MAIN"/>
18+
<category android:name="android.intent.category.LAUNCHER"/>
19+
</intent-filter>
20+
</activity>
21+
</application>
22+
</manifest>
Loading
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
name: microbenchmarks
2+
uses-material-design: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
{
2+
"images" : [
3+
{
4+
"size" : "29x29",
5+
"idiom" : "iphone",
6+
"filename" : "Icon-Small@2x.png",
7+
"scale" : "2x"
8+
},
9+
{
10+
"size" : "29x29",
11+
"idiom" : "iphone",
12+
"filename" : "Icon-Small@3x.png",
13+
"scale" : "3x"
14+
},
15+
{
16+
"size" : "40x40",
17+
"idiom" : "iphone",
18+
"filename" : "Icon-Small-40@2x.png",
19+
"scale" : "2x"
20+
},
21+
{
22+
"size" : "40x40",
23+
"idiom" : "iphone",
24+
"filename" : "Icon-Small-40@3x.png",
25+
"scale" : "3x"
26+
},
27+
{
28+
"size" : "60x60",
29+
"idiom" : "iphone",
30+
"filename" : "Icon-60@2x.png",
31+
"scale" : "2x"
32+
},
33+
{
34+
"size" : "60x60",
35+
"idiom" : "iphone",
36+
"filename" : "Icon-60@3x.png",
37+
"scale" : "3x"
38+
},
39+
{
40+
"size" : "29x29",
41+
"idiom" : "ipad",
42+
"filename" : "Icon-Small.png",
43+
"scale" : "1x"
44+
},
45+
{
46+
"size" : "29x29",
47+
"idiom" : "ipad",
48+
"filename" : "Icon-Small@2x.png",
49+
"scale" : "2x"
50+
},
51+
{
52+
"size" : "40x40",
53+
"idiom" : "ipad",
54+
"filename" : "Icon-Small-40.png",
55+
"scale" : "1x"
56+
},
57+
{
58+
"size" : "40x40",
59+
"idiom" : "ipad",
60+
"filename" : "Icon-Small-40@2x.png",
61+
"scale" : "2x"
62+
},
63+
{
64+
"size" : "76x76",
65+
"idiom" : "ipad",
66+
"filename" : "Icon-76.png",
67+
"scale" : "1x"
68+
},
69+
{
70+
"size" : "76x76",
71+
"idiom" : "ipad",
72+
"filename" : "Icon-76@2x.png",
73+
"scale" : "2x"
74+
},
75+
{
76+
"size" : "83.5x83.5",
77+
"idiom" : "ipad",
78+
"filename" : "Icon-83.5@2x.png",
79+
"scale" : "2x"
80+
},
81+
{
82+
"size" : "16x16",
83+
"idiom" : "mac",
84+
"filename" : "icon_16x16.png",
85+
"scale" : "1x"
86+
},
87+
{
88+
"size" : "16x16",
89+
"idiom" : "mac",
90+
"filename" : "icon_16x16@2x.png",
91+
"scale" : "2x"
92+
},
93+
{
94+
"size" : "32x32",
95+
"idiom" : "mac",
96+
"filename" : "icon_32x32.png",
97+
"scale" : "1x"
98+
},
99+
{
100+
"size" : "32x32",
101+
"idiom" : "mac",
102+
"filename" : "icon_32x32@2x.png",
103+
"scale" : "2x"
104+
},
105+
{
106+
"size" : "128x128",
107+
"idiom" : "mac",
108+
"filename" : "icon_128x128.png",
109+
"scale" : "1x"
110+
},
111+
{
112+
"size" : "128x128",
113+
"idiom" : "mac",
114+
"filename" : "icon_128x128@2x.png",
115+
"scale" : "2x"
116+
},
117+
{
118+
"size" : "256x256",
119+
"idiom" : "mac",
120+
"filename" : "icon_256x256.png",
121+
"scale" : "1x"
122+
},
123+
{
124+
"size" : "256x256",
125+
"idiom" : "mac",
126+
"filename" : "icon_256x256@2x.png",
127+
"scale" : "2x"
128+
},
129+
{
130+
"size" : "512x512",
131+
"idiom" : "mac",
132+
"filename" : "icon_512x512.png",
133+
"scale" : "1x"
134+
},
135+
{
136+
"size" : "512x512",
137+
"idiom" : "mac",
138+
"filename" : "icon_512x512@2x.png",
139+
"scale" : "2x"
140+
}
141+
]
142+
}
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>en</string>
7+
<key>CFBundleExecutable</key>
8+
<string>Runner</string>
9+
<key>CFBundleIdentifier</key>
10+
<string>com.yourcompany.microbenchmarks</string>
11+
<key>CFBundleInfoDictionaryVersion</key>
12+
<string>6.0</string>
13+
<key>CFBundleName</key>
14+
<string>microbenchmarks</string>
15+
<key>CFBundlePackageType</key>
16+
<string>APPL</string>
17+
<key>CFBundleShortVersionString</key>
18+
<string>1.0</string>
19+
<key>CFBundleSignature</key>
20+
<string>????</string>
21+
<key>CFBundleVersion</key>
22+
<string>1</string>
23+
<key>LSRequiresIPhoneOS</key>
24+
<true/>
25+
<key>UILaunchStoryboardName</key>
26+
<string>LaunchScreen</string>
27+
<key>UIRequiredDeviceCapabilities</key>
28+
<array>
29+
<string>arm64</string>
30+
</array>
31+
<key>UISupportedInterfaceOrientations</key>
32+
<array>
33+
<string>UIInterfaceOrientationPortrait</string>
34+
<string>UIInterfaceOrientationLandscapeLeft</string>
35+
<string>UIInterfaceOrientationLandscapeRight</string>
36+
</array>
37+
<key>UISupportedInterfaceOrientations~ipad</key>
38+
<array>
39+
<string>UIInterfaceOrientationPortrait</string>
40+
<string>UIInterfaceOrientationPortraitUpsideDown</string>
41+
<string>UIInterfaceOrientationLandscapeLeft</string>
42+
<string>UIInterfaceOrientationLandscapeRight</string>
43+
</array>
44+
<key>UIViewControllerBasedStatusBarAppearance</key>
45+
<false/>
46+
</dict>
47+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
3+
<dependencies>
4+
<deployment identifier="iOS"/>
5+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
6+
</dependencies>
7+
<scenes>
8+
<!--View Controller-->
9+
<scene sceneID="EHf-IW-A2E">
10+
<objects>
11+
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
12+
<layoutGuides>
13+
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
14+
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
15+
</layoutGuides>
16+
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
17+
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
18+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19+
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
20+
</view>
21+
</viewController>
22+
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
23+
</objects>
24+
<point key="canvasLocation" x="53" y="375"/>
25+
</scene>
26+
</scenes>
27+
</document>

packages/flutter/benchmark/gestures/velocity_tracker_data.dart renamed to dev/benchmarks/microbenchmarks/lib/gestures/data/velocity_tracker_data.dart

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Copyright 2016 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
15
import 'package:flutter/gestures.dart';
26

37
/// Data for velocity_tracker_bench.dart
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2016 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:io';
6+
import 'package:flutter/gestures.dart';
7+
import 'data/velocity_tracker_data.dart';
8+
9+
const int _kNumIters = 10000;
10+
11+
void main() {
12+
final VelocityTracker tracker = new VelocityTracker();
13+
final Stopwatch watch = new Stopwatch();
14+
print('Velocity tracker benchmark...');
15+
watch.start();
16+
for (int i = 0; i < _kNumIters; i += 1) {
17+
for (PointerEvent event in velocityEventData) {
18+
if (event is PointerDownEvent || event is PointerMoveEvent)
19+
tracker.addPosition(event.timeStamp, event.position);
20+
if (event is PointerUpEvent)
21+
tracker.getVelocity();
22+
}
23+
}
24+
watch.stop();
25+
print('Velocity tracker: ${(watch.elapsedMicroseconds / _kNumIters).toStringAsFixed(1)}µs per iteration');
26+
exit(0);
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright 2016 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:io';
6+
7+
import 'package:flutter_test/flutter_test.dart';
8+
import 'package:flutter/material.dart';
9+
import 'package:flutter/rendering.dart';
10+
import 'package:flutter/scheduler.dart';
11+
import 'package:stocks/main.dart' as stocks;
12+
import 'package:stocks/stock_data.dart' as stock_data;
13+
14+
const Duration kBenchmarkTime = const Duration(seconds: 15);
15+
16+
class BenchmarkingBinding extends LiveTestWidgetsFlutterBinding {
17+
BenchmarkingBinding(this.stopwatch);
18+
19+
final Stopwatch stopwatch;
20+
21+
@override
22+
void handleBeginFrame(Duration rawTimeStamp) {
23+
stopwatch.start();
24+
super.handleBeginFrame(rawTimeStamp);
25+
stopwatch.stop();
26+
}
27+
}
28+
29+
Future<Null> main() async {
30+
assert(false); // don't run this in checked mode! Use --release.
31+
stock_data.StockDataFetcher.actuallyFetchData = false;
32+
33+
final Stopwatch wallClockWatch = new Stopwatch();
34+
final Stopwatch cpuWatch = new Stopwatch();
35+
new BenchmarkingBinding(cpuWatch);
36+
37+
int totalOpenFrameElapsedMicroseconds = 0;
38+
int totalOpenIterationCount = 0;
39+
int totalCloseFrameElapsedMicroseconds = 0;
40+
int totalCloseIterationCount = 0;
41+
int totalSubsequentFramesElapsedMicroseconds = 0;
42+
int totalSubsequentFramesIterationCount = 0;
43+
44+
await benchmarkWidgets((WidgetTester tester) async {
45+
stocks.main();
46+
await tester.pump(); // Start startup animation
47+
await tester.pump(const Duration(seconds: 1)); // Complete startup animation
48+
49+
bool drawerIsOpen = false;
50+
wallClockWatch.start();
51+
while (wallClockWatch.elapsed < kBenchmarkTime) {
52+
cpuWatch.reset();
53+
if (drawerIsOpen) {
54+
await tester.tapAt(const Point(780.0, 250.0)); // Close drawer
55+
await tester.pump();
56+
totalCloseIterationCount += 1;
57+
totalCloseFrameElapsedMicroseconds += cpuWatch.elapsedMicroseconds;
58+
} else {
59+
await tester.tapAt(const Point(20.0, 50.0)); // Open drawer
60+
await tester.pump();
61+
totalOpenIterationCount += 1;
62+
totalOpenFrameElapsedMicroseconds += cpuWatch.elapsedMicroseconds;
63+
}
64+
drawerIsOpen = !drawerIsOpen;
65+
66+
// Time how long each frame takes
67+
cpuWatch.reset();
68+
while (SchedulerBinding.instance.hasScheduledFrame) {
69+
await tester.pump();
70+
totalSubsequentFramesIterationCount += 1;
71+
}
72+
totalSubsequentFramesElapsedMicroseconds += cpuWatch.elapsedMicroseconds;
73+
}
74+
});
75+
76+
print('Stock animation (ran for ${(wallClockWatch.elapsedMicroseconds / (1000 * 1000)).toStringAsFixed(1)}s):');
77+
print(' Opening first frame average time: ${(totalOpenFrameElapsedMicroseconds / (totalOpenIterationCount)).toStringAsFixed(1)}µs per frame ($totalOpenIterationCount frames)');
78+
print(' Closing first frame average time: ${(totalCloseFrameElapsedMicroseconds / (totalCloseIterationCount)).toStringAsFixed(1)}µs per frame ($totalCloseIterationCount frames)');
79+
print(' Subsequent frames average time: ${(totalSubsequentFramesElapsedMicroseconds / (totalSubsequentFramesIterationCount)).toStringAsFixed(1)}µs per frame ($totalSubsequentFramesIterationCount frames)');
80+
81+
exit(0);
82+
}

0 commit comments

Comments
 (0)