Unverified Commit eb30745f authored by liyuqian's avatar liyuqian Committed by GitHub

Print warning if flutter drive is run in debug (#30747)

## Description

Print actionable warnings if `flutter drive` (where most of our performance benchmarks come from) is run in debug mode and it tries to gather benchmarks using `traceAction`.

## Related Issues

https://github.com/flutter/flutter/issues/30625

## Tests

I added the following tests:
* drive_perf_debug_warning devicelab test
parent 5a4eaaba
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter_devicelab/framework/adb.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/utils.dart';
Future<String> _runWithMode(String mode, String deviceId) {
return evalFlutter('drive', options: <String>[
mode,
'-t',
'test_driver/scroll_perf.dart',
'-d',
deviceId,
]);
}
Future<TaskResult> run() async {
cd('${flutterDirectory.path}/examples/flutter_gallery');
final Device device = await devices.workingDevice;
await device.unlock();
final String deviceId = device.deviceId;
await flutter('packages', options: <String>['get']);
const String warningPiece = 'THIS BENCHMARK IS BEING RUN IN DEBUG MODE';
final String debugOutput = await _runWithMode('--debug', deviceId);
if (!debugOutput.contains(warningPiece)) {
return TaskResult.failure(
'Could not find the following warning message piece: $warningPiece'
);
}
final String profileOutput = await _runWithMode('--profile', deviceId);
if (profileOutput.contains(warningPiece)) {
return TaskResult.failure(
'Unexpected warning message piece in profile mode: $warningPiece'
);
}
return TaskResult.success(null);
}
Future<void> main() async {
deviceOperatingSystem = DeviceOperatingSystem.android;
await task(run);
}
......@@ -148,6 +148,13 @@ tasks:
stage: devicelab
required_agent_capabilities: ["mac/android"]
drive_perf_debug_warning:
description: >
Check that driver will print warnings when traceAction is called in debug mode.
stage: devicelab
required_agent_capabilities: ["mac/android"]
flaky: true
cull_opacity_perf__timeline_summary:
description: >
Measures the runtime performance of culling opacity widgets on Android.
......
......@@ -150,6 +150,22 @@ class FlutterDriver {
static int _nextDriverId = 0;
// The additional blank line in the beginning is for _log.warning.
static const String _kDebugWarning = '''
┏╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍┓
┇ ⚠ THIS BENCHMARK IS BEING RUN IN DEBUG MODE ⚠ ┇
┡╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍┦
│ │
│ Numbers obtained from a benchmark while asserts are │
│ enabled will not accurately reflect the performance │
│ that will be experienced by end users using release ╎
│ builds. Benchmarks should be run using this command ┆
│ line: flutter drive --profile test_perf.dart ┊
│ ┊
└─────────────────────────────────────────────────╌┄┈ 🐢
''';
/// Connects to a Flutter application.
///
/// Resumes the application if it is currently paused (e.g. at a breakpoint).
......@@ -708,7 +724,9 @@ class FlutterDriver {
/// [getFlagList]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#getflaglist
Future<List<Map<String, dynamic>>> getVmFlags() async {
final Map<String, dynamic> result = await _peer.sendRequest('getFlagList');
return result['flags'];
return result != null
? result['flags'].cast<Map<String,dynamic>>()
: const <Map<String, dynamic>>[];
}
/// Starts recording performance traces.
......@@ -764,6 +782,16 @@ class FlutterDriver {
}
}
Future<bool> _isPrecompiledMode() async {
final List<Map<String, dynamic>> flags = await getVmFlags();
for(Map<String, dynamic> flag in flags) {
if (flag['name'] == 'precompiled_mode') {
return flag['valueAsString'] == 'true';
}
}
return false;
}
/// Runs [action] and outputs a performance trace for it.
///
/// Waits for the `Future` returned by [action] to complete prior to stopping
......@@ -778,6 +806,9 @@ class FlutterDriver {
/// If [retainPriorEvents] is true, retains events recorded prior to calling
/// [action]. Otherwise, prior events are cleared before calling [action]. By
/// default, prior events are cleared.
///
/// If this is run in debug mode, a warning message will be printed to suggest
/// running the benchmark in profile mode instead.
Future<Timeline> traceAction(
Future<dynamic> action(), {
List<TimelineStream> streams = _defaultStreams,
......@@ -788,6 +819,10 @@ class FlutterDriver {
}
await startTracing(streams: streams);
await action();
if (!(await _isPrecompiledMode())) {
_log.warning(_kDebugWarning);
}
return stopTracingAndDownloadTimeline();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment