diff --git a/agent/lib/src/adb.dart b/agent/lib/src/adb.dart index a255628902..70c393638d 100644 --- a/agent/lib/src/adb.dart +++ b/agent/lib/src/adb.dart @@ -36,6 +36,28 @@ Future realAdbGetter() async { return _currentDevice; } +/// Gets the ID of an unlocked device, unlocking it if necessary. +// TODO(yjbanov): abstract away iOS from Android. +Future getUnlockedDeviceId({ bool ios: false }) async { + if (ios) { + // We currently do not have a way to lock/unlock iOS devices, or even to + // pick one out of many. So we pick the first random iPhone and assume it's + // already unlocked. For now we'll just keep them at minimum screen + // brightness so they don't drain battery too fast. + List iosDeviceIds = grep('UniqueDeviceID', from: await eval('ideviceinfo', [])) + .map((String line) => line.split(' ').last).toList(); + + if (iosDeviceIds.isEmpty) + throw 'No connected iOS devices found.'; + + return iosDeviceIds.first; + } + + Adb device = await adb(); + device.unlock(); + return device.deviceId; +} + class Adb { Adb({String this.deviceId}); diff --git a/agent/lib/src/agent.dart b/agent/lib/src/agent.dart index 61ea1de5c9..fe60df0108 100644 --- a/agent/lib/src/agent.dart +++ b/agent/lib/src/agent.dart @@ -82,11 +82,15 @@ class Agent { List allTasks = [ createComplexLayoutScrollPerfTest(), + createComplexLayoutScrollPerfTest(ios: true), createFlutterGalleryStartupTest(), + createFlutterGalleryStartupTest(ios: true), createComplexLayoutStartupTest(), + createComplexLayoutStartupTest(ios: true), createFlutterGalleryBuildTest(), createComplexLayoutBuildTest(), createGalleryTransitionTest(), + createGalleryTransitionTest(ios: true), createBasicMaterialAppSizeTest(), createAnalyzerCliTest(sdk: dartSdkVersion, commit: task.revision, timestamp: revisionTimestamp), createAnalyzerServerTest(sdk: dartSdkVersion, commit: task.revision, timestamp: revisionTimestamp), diff --git a/agent/lib/src/commands/run.dart b/agent/lib/src/commands/run.dart index 969fe01bbd..86bfceaafe 100644 --- a/agent/lib/src/commands/run.dart +++ b/agent/lib/src/commands/run.dart @@ -57,7 +57,7 @@ class RunCommand extends Command { try { await runAndCaptureAsyncStacks(() async { // Load-balance tests across attached devices - pickNextDevice(); + await pickNextDevice(); BuildResult result = await agent.performTask(task); if (task.key != null) { diff --git a/agent/lib/src/gallery.dart b/agent/lib/src/gallery.dart index 4895a07155..e4e4648de8 100644 --- a/agent/lib/src/gallery.dart +++ b/agent/lib/src/gallery.dart @@ -10,25 +10,32 @@ import 'adb.dart'; import 'framework.dart'; import 'utils.dart'; -Task createGalleryTransitionTest() => new GalleryTransitionTest(); +Task createGalleryTransitionTest({ bool ios: false }) => new GalleryTransitionTest(ios: ios); class GalleryTransitionTest extends Task { - GalleryTransitionTest() : super('flutter_gallery__transition_perf'); + GalleryTransitionTest({ this.ios }) : super('flutter_gallery__transition_perf'); + + final bool ios; @override Future run() async { - Adb device = await adb(); - device.unlock(); + String deviceId = await getUnlockedDeviceId(ios: ios); Directory galleryDirectory = dir('${config.flutterDirectory.path}/examples/flutter_gallery'); await inDirectory(galleryDirectory, () async { await pub('get'); + + if (ios) { + // This causes an Xcode project to be created. + await flutter('build', options: ['ios', '--profile']); + } + await flutter('drive', options: [ '--profile', '--trace-startup', '-t', 'test_driver/transitions_perf.dart', '-d', - device.deviceId, + deviceId, ]); }); diff --git a/agent/lib/src/perf_tests.dart b/agent/lib/src/perf_tests.dart index 4c60f44ae4..8670e1f3e7 100644 --- a/agent/lib/src/perf_tests.dart +++ b/agent/lib/src/perf_tests.dart @@ -9,21 +9,30 @@ import 'adb.dart'; import 'framework.dart'; import 'utils.dart'; -Task createComplexLayoutScrollPerfTest() { +Task createComplexLayoutScrollPerfTest({ bool ios: false }) { return new PerfTest( - 'complex_layout_scroll_perf__timeline_summary', + 'complex_layout_scroll_perf${ios ? "_ios" : ""}__timeline_summary', '${config.flutterDirectory.path}/dev/benchmarks/complex_layout', 'test_driver/scroll_perf.dart', - 'complex_layout_scroll_perf' + 'complex_layout_scroll_perf', + ios: ios ); } -Task createFlutterGalleryStartupTest() { - return new StartupTest('flutter_gallery__start_up', '${config.flutterDirectory.path}/examples/flutter_gallery'); +Task createFlutterGalleryStartupTest({ bool ios: false }) { + return new StartupTest( + 'flutter_gallery${ios ? "_ios" : ""}__start_up', + '${config.flutterDirectory.path}/examples/flutter_gallery', + ios: ios + ); } -Task createComplexLayoutStartupTest() { - return new StartupTest('complex_layout__start_up', '${config.flutterDirectory.path}/dev/benchmarks/complex_layout'); +Task createComplexLayoutStartupTest({ bool ios: false }) { + return new StartupTest( + 'complex_layout${ios ? "_ios" : ""}__start_up', + '${config.flutterDirectory.path}/dev/benchmarks/complex_layout', + ios: ios + ); } Task createFlutterGalleryBuildTest() { @@ -37,20 +46,26 @@ Task createComplexLayoutBuildTest() { /// Measure application startup performance. class StartupTest extends Task { - StartupTest(String name, this.testDirectory) : super(name); + StartupTest(String name, this.testDirectory, { this.ios }) : super(name); final String testDirectory; + final bool ios; Future run() async { return await inDirectory(testDirectory, () async { - Adb device = await adb(); - device.unlock(); + String deviceId = await getUnlockedDeviceId(ios: ios); await pub('get'); + + if (ios) { + // This causes an Xcode project to be created. + await flutter('build', options: ['ios', '--profile']); + } + await flutter('run', options: [ '--profile', '--trace-startup', '-d', - device.deviceId + deviceId ]); Map data = JSON.decode(file('$testDirectory/build/start_up_info.json').readAsStringSync()); return new TaskResultData(data, benchmarkScoreKeys: [ @@ -65,26 +80,33 @@ class StartupTest extends Task { /// performance. class PerfTest extends Task { - PerfTest(String name, this.testDirectory, this.testTarget, this.timelineFileName) + PerfTest(String name, this.testDirectory, this.testTarget, this.timelineFileName, { this.ios }) : super(name); final String testDirectory; final String testTarget; final String timelineFileName; + final bool ios; @override Future run() { return inDirectory(testDirectory, () async { - Adb device = await adb(); - device.unlock(); + String deviceId = await getUnlockedDeviceId(ios: ios); await pub('get'); + + if (ios) { + // This causes an Xcode project to be created. + await flutter('build', options: ['ios', '--profile']); + } + await flutter('drive', options: [ + '-v', '--profile', '--trace-startup', // Enables "endless" timeline event buffering. '-t', testTarget, '-d', - device.deviceId + deviceId, ]); Map data = JSON.decode(file('$testDirectory/build/${timelineFileName}.timeline_summary.json').readAsStringSync()); return new TaskResultData(data, benchmarkScoreKeys: [ @@ -96,7 +118,6 @@ class PerfTest extends Task { } } - class BuildTest extends Task { BuildTest(String name, this.testDirectory) : super(name);