Skip to content

Commit 9dad2d9

Browse files
authored
Perf test with SkSL warm-up (flutter#56638)
1 parent c2d5e18 commit 9dad2d9

File tree

3 files changed

+161
-10
lines changed

3 files changed

+161
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2014 The Flutter 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:async';
6+
7+
import 'package:flutter_devicelab/tasks/perf_tests.dart';
8+
import 'package:flutter_devicelab/framework/adb.dart';
9+
import 'package:flutter_devicelab/framework/framework.dart';
10+
11+
Future<void> main() async {
12+
deviceOperatingSystem = DeviceOperatingSystem.android;
13+
await task(createCubicBezierPerfSkSLWarmupTest());
14+
}

dev/devicelab/lib/tasks/perf_tests.dart

+139-10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'dart:convert' show LineSplitter, json, utf8;
77
import 'dart:io';
88
import 'dart:math' as math;
99

10+
import 'package:flutter_devicelab/tasks/track_widget_creation_enabled_task.dart';
1011
import 'package:meta/meta.dart';
1112
import 'package:path/path.dart' as path;
1213

@@ -82,12 +83,20 @@ TaskFunction createCubicBezierPerfTest() {
8283
).run;
8384
}
8485

86+
TaskFunction createCubicBezierPerfSkSLWarmupTest() {
87+
return PerfTestWithSkSL(
88+
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
89+
'test_driver/cubic_bezier_perf.dart',
90+
'cubic_bezier_perf',
91+
).run;
92+
}
93+
8594
TaskFunction createBackdropFilterPerfTest({bool needsMeasureCpuGpu = false}) {
8695
return PerfTest(
8796
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
8897
'test_driver/backdrop_filter_perf.dart',
8998
'backdrop_filter_perf',
90-
needsMeasureCpuGPu: needsMeasureCpuGpu,
99+
needsMeasureCpuGpu: needsMeasureCpuGpu,
91100
).run;
92101
}
93102

@@ -96,7 +105,7 @@ TaskFunction createPostBackdropFilterPerfTest({bool needsMeasureCpuGpu = false})
96105
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
97106
'test_driver/post_backdrop_filter_perf.dart',
98107
'post_backdrop_filter_perf',
99-
needsMeasureCpuGPu: needsMeasureCpuGpu,
108+
needsMeasureCpuGpu: needsMeasureCpuGpu,
100109
).run;
101110
}
102111

@@ -105,7 +114,7 @@ TaskFunction createSimpleAnimationPerfTest({bool needsMeasureCpuGpu = false}) {
105114
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
106115
'test_driver/simple_animation_perf.dart',
107116
'simple_animation_perf',
108-
needsMeasureCpuGPu: needsMeasureCpuGpu,
117+
needsMeasureCpuGpu: needsMeasureCpuGpu,
109118
).run;
110119
}
111120

@@ -114,7 +123,7 @@ TaskFunction createAnimatedPlaceholderPerfTest({bool needsMeasureCpuGpu = false}
114123
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
115124
'test_driver/animated_placeholder_perf.dart',
116125
'animated_placeholder_perf',
117-
needsMeasureCpuGPu: needsMeasureCpuGpu,
126+
needsMeasureCpuGpu: needsMeasureCpuGpu,
118127
).run;
119128
}
120129

@@ -266,7 +275,7 @@ class PerfTest {
266275
this.testDirectory,
267276
this.testTarget,
268277
this.timelineFileName, {
269-
this.needsMeasureCpuGPu = false,
278+
this.needsMeasureCpuGpu = false,
270279
this.testDriver,
271280
});
272281

@@ -279,9 +288,19 @@ class PerfTest {
279288
/// The test file to run on the host.
280289
final String testDriver;
281290
/// Whether to collect CPU and GPU metrics.
282-
final bool needsMeasureCpuGPu;
291+
final bool needsMeasureCpuGpu;
283292

284293
Future<TaskResult> run() {
294+
return internalRun();
295+
}
296+
297+
@protected
298+
Future<TaskResult> internalRun({
299+
bool keepRunning = false,
300+
bool cacheSkSL = false,
301+
String existingApp,
302+
String writeSkslFileName,
303+
}) {
285304
return inDirectory<TaskResult>(testDirectory, () async {
286305
final Device device = await devices.workingDevice;
287306
await device.unlock();
@@ -295,7 +314,13 @@ class PerfTest {
295314
'-t',
296315
testTarget,
297316
if (testDriver != null)
298-
'--driver', testDriver,
317+
...<String>['--driver', testDriver],
318+
if (existingApp != null)
319+
...<String>['--use-existing-app', existingApp],
320+
if (writeSkslFileName != null)
321+
...<String>['--write-sksl-on-exit', writeSkslFileName],
322+
if (cacheSkSL) '--cache-sksl',
323+
if (keepRunning) '--keep-app-running',
299324
'-d',
300325
deviceId,
301326
]);
@@ -310,7 +335,7 @@ class PerfTest {
310335
);
311336
}
312337

313-
if (needsMeasureCpuGPu) {
338+
if (needsMeasureCpuGpu) {
314339
await inDirectory<void>('$testDirectory/build', () async {
315340
data.addAll(await measureIosCpuGpu(deviceId: deviceId));
316341
});
@@ -328,13 +353,117 @@ class PerfTest {
328353
'average_vsync_transitions_missed',
329354
'90th_percentile_vsync_transitions_missed',
330355
'99th_percentile_vsync_transitions_missed',
331-
if (needsMeasureCpuGPu) 'cpu_percentage',
332-
if (needsMeasureCpuGPu) 'gpu_percentage',
356+
if (needsMeasureCpuGpu) 'cpu_percentage',
357+
if (needsMeasureCpuGpu) 'gpu_percentage',
333358
]);
334359
});
335360
}
336361
}
337362

363+
class PerfTestWithSkSL extends PerfTest {
364+
PerfTestWithSkSL(
365+
String testDirectory,
366+
String testTarget,
367+
String timelineFileName, {
368+
bool needsMeasureCpuGpu = false,
369+
String testDriver,
370+
}) : super(
371+
testDirectory,
372+
testTarget,
373+
timelineFileName,
374+
needsMeasureCpuGpu: needsMeasureCpuGpu,
375+
testDriver: testDriver,
376+
);
377+
378+
@override
379+
Future<TaskResult> run() async {
380+
return inDirectory<TaskResult>(testDirectory, () async {
381+
// Some initializations
382+
_device = await devices.workingDevice;
383+
_flutterPath = path.join(flutterDirectory.path, 'bin', 'flutter');
384+
385+
// Prepare the SkSL by running the driver test.
386+
await _generateSkSL();
387+
388+
// Build the app with SkSL artifacts and run that app
389+
final String observatoryUri = await _buildAndRun();
390+
391+
// Attach to the running app and run the final driver test to get metrics.
392+
final TaskResult result = await internalRun(
393+
existingApp: observatoryUri,
394+
);
395+
396+
_runProcess.kill();
397+
await _runProcess.exitCode;
398+
399+
return result;
400+
});
401+
}
402+
403+
Future<void> _generateSkSL() async {
404+
await super.internalRun(
405+
keepRunning: true,
406+
cacheSkSL: true,
407+
writeSkslFileName: _skslJsonFileName,
408+
);
409+
}
410+
411+
// Return the VMService URI.
412+
Future<String> _buildAndRun() async {
413+
await flutter('build', options: <String>[
414+
// TODO(liyuqian): also supports iOS once https://github.com/flutter/flutter/issues/53115 is fully closed.
415+
'apk',
416+
'--profile',
417+
'--bundle-sksl-path', _skslJsonFileName,
418+
'-t', testTarget,
419+
]);
420+
421+
if (File(_vmserviceFileName).existsSync()) {
422+
File(_vmserviceFileName).deleteSync();
423+
}
424+
425+
_runProcess = await startProcess(
426+
_flutterPath,
427+
<String>[
428+
'run',
429+
'--verbose',
430+
'--profile',
431+
'-d', _device.deviceId,
432+
'-t', testTarget,
433+
'--endless-trace-buffer',
434+
'--use-application-binary',
435+
'$testDirectory/build/app/outputs/flutter-apk/app-profile.apk',
436+
'--vmservice-out-file', _vmserviceFileName,
437+
],
438+
);
439+
440+
final Stream<List<int>> broadcastOut = _runProcess.stdout.asBroadcastStream();
441+
_forwardStream(broadcastOut, 'run stdout');
442+
_forwardStream(_runProcess.stderr, 'run stderr');
443+
444+
final File file = await waitForFile(_vmserviceFileName);
445+
return file.readAsStringSync();
446+
}
447+
448+
String get _skslJsonFileName => '$testDirectory/flutter_01.sksl.json';
449+
String get _vmserviceFileName => '$testDirectory/$_kVmserviceOutFileName';
450+
451+
Stream<String> _transform(Stream<List<int>> stream) =>
452+
stream.transform<String>(utf8.decoder).transform<String>(const LineSplitter());
453+
454+
void _forwardStream(Stream<List<int>> stream, String label) {
455+
_transform(stream).listen((String line) {
456+
print('$label: $line');
457+
});
458+
}
459+
460+
String _flutterPath;
461+
Device _device;
462+
Process _runProcess;
463+
464+
static const String _kVmserviceOutFileName = 'vmservice.out';
465+
}
466+
338467
/// Measures how long it takes to compile a Flutter app to JavaScript and how
339468
/// big the compiled code is.
340469
class WebCompileTest {

dev/devicelab/manifest.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ tasks:
168168
stage: devicelab
169169
required_agent_capabilities: ["mac/android"]
170170

171+
cubic_bezier_perf_sksl_warmup__timeline_summary:
172+
description: >
173+
Measures the runtime performance of cubic bezier animations on Android
174+
with SkSL shader warm-up.
175+
stage: devicelab
176+
required_agent_capabilities: ["mac/android"]
177+
flaky: true
178+
171179
backdrop_filter_perf__timeline_summary:
172180
description: >
173181
Measures the runtime performance of backdrop filter blurs on Android.

0 commit comments

Comments
 (0)