Remove gauge (#217)

It's now replaced by https://github.com/flutter/engine/pull/18752
This commit is contained in:
Yuqian Li
2020-10-06 14:33:25 -07:00
committed by GitHub
parent 4e11063109
commit e059cecae8
17 changed files with 1 additions and 735 deletions

View File

@ -11,8 +11,7 @@ task:
activate_script: pub global activate flutter_plugin_tools
matrix:
- name: analyze
# TODO(goderbauer): remove custom-analysis once gauge has proper API docs.
script: ./script/incremental_build.sh analyze --custom-analysis gauge
script: ./script/incremental_build.sh analyze
- name: publishable
script: ./script/check_publish.sh
depends_on:

2
.gitignore vendored
View File

@ -14,8 +14,6 @@ GeneratedPluginRegistrant.m
GeneratedPluginRegistrant.java
packages/gauge/result.json
packages/gauge/resources
*instrumentscli*.trace
*.cipd

View File

@ -35,7 +35,6 @@ These are the available packages in this repository.
|--------|-----|
| [animations](./packages/animations/) | [![pub package](https://img.shields.io/pub/v/animations.svg)](https://pub.dev/packages/animations) |
| [fuchsia_ctl](./packages/fuchsia_ctl/) | [![pub package](https://img.shields.io/pub/v/fuchsia_ctl.svg)](https://pub.dev/packages/fuchsia_ctl) |
| [gauge](./packages/gauge/) | [![pub package](https://img.shields.io/pub/v/gauge.svg)](https://pub.dev/packages/gauge) |
| [multicast_dns](./packages/multicast_dns/) | [![pub package](https://img.shields.io/pub/v/multicast_dns.svg)](https://pub.dev/packages/multicast_dns) |
| [palette_generator](./packages/palette_generator/) | [![pub package](https://img.shields.io/pub/v/palette_generator.svg)](https://pub.dartlang.org/packages/palette_generator) |
| [pigeon](./packages/pigeon/) | [![pub package](https://img.shields.io/pub/v/pigeon.svg)](https://pub.dev/packages/pigeon) |

View File

@ -1,24 +0,0 @@
## 0.1.5
* Print more logs for debugging.
## 0.1.4
* Download depot_tools automatically.
## 0.1.3
* More fixes from health suggestions.
## 0.1.2
* Fix the resource downloading bug.
## 0.1.1
* Improve tests and remove unnecessary resources.
## 0.1.0
* Initial release.

View File

@ -1,27 +0,0 @@
Copyright 2019 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,36 +0,0 @@
Tools for gauging/measuring some performance metrics.
Currently there's only one tool to measure iOS CPU/GPU usages for Flutter's CI
tests. It's only tested on Xcode 10 and it's known that Xcode 11 may not be
compatible.
# Install
First install Xcode 10.3 (https://developer.apple.com/download/more/),
[dart](https://dart.dev/get-dart), and
[git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
Make sure that `pub`, `git`, and `instruments` are on your path.
Then run:
```shell
pub global activate gauge
```
# Run
Connect an iPhone, run a Flutter app on it, and
```shell
pub global run gauge ioscpugpu new
```
Sample output:
```
gpu: 12.4%, cpu: 22.525%
```
For more information, try
```shell
pub global run gauge help
pub global run gauge help ioscpugpu
pub global run gauge help ioscpugpu new
pub global run gauge help ioscpugpu parse
```

View File

@ -1,6 +0,0 @@
include: ../../analysis_options.yaml
analyzer:
linter:
rules:
public_member_api_docs: false # TODO(goderbauer): enable when package is ready.

View File

@ -1,16 +0,0 @@
// 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 'package:args/command_runner.dart';
import 'package:gauge/commands/ioscpugpu.dart';
void main(List<String> args) {
final CommandRunner<void> runner = CommandRunner<void>(
'gauge',
'Tools for gauging/measuring some performance metrics.',
);
runner.addCommand(IosCpuGpu());
runner.run(args);
}

View File

@ -1,5 +0,0 @@
package: flutter/packages/gauge/resources
description: Binaries and other resources for measuring performance metrics.
install_mode: copy
data:
- dir: resources

View File

@ -1,130 +0,0 @@
// 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:io';
import 'package:args/command_runner.dart';
import 'package:meta/meta.dart';
const String kOptionResourcesRoot = 'resources-root';
const String kOptionTimeLimitMs = 'time-limit-ms';
const String kOptionDevice = 'device';
const String kOptionProessName = 'process-name';
const String kOptionOutJson = 'out-json';
const String kFlagVerbose = 'verbose';
const String kDefaultProccessName = 'Runner'; // Flutter app's default process
abstract class BaseCommand extends Command<void> {
BaseCommand() {
argParser.addFlag(kFlagVerbose);
argParser.addOption(
kOptionOutJson,
abbr: 'o',
help: 'Specifies the json file for result output.',
defaultsTo: 'result.json',
);
argParser.addOption(
kOptionResourcesRoot,
abbr: 'r',
help: 'Specifies the path to download resources',
defaultsTo: defaultResourcesRoot,
);
}
static String get defaultResourcesRoot =>
'${Platform.environment['HOME']}/.gauge';
static void _getDepotTools() {
final ProcessResult result = Process.runSync(
'git',
<String>[
'clone',
'--depth',
'1',
'https://chromium.googlesource.com/chromium/tools/depot_tools.git'
],
);
if (result.exitCode != 0) {
print('git clone stdout:\n${result.stdout}\n');
print('git clone stderr:\n${result.stderr}\n');
throw Exception('Failed to clone depot_tools.');
}
}
static Future<void> doEnsureResources(String rootPath,
{bool isVerbose = false}) async {
final Directory root = await Directory(rootPath).create(recursive: true);
final Directory previous = Directory.current;
Directory.current = root;
if (!Directory('depot_tools').existsSync()) {
if (isVerbose) {
print('Downloading depot_tools...');
}
_getDepotTools();
}
final File ensureFile = File('ensure_file.txt');
ensureFile.writeAsStringSync('flutter/packages/gauge/resources latest');
if (isVerbose) {
print('Downloading resources from CIPD...');
}
final ProcessResult result = Process.runSync(
'./depot_tools/cipd',
<String>[
'ensure',
'-ensure-file',
'ensure_file.txt',
'-root',
'.',
],
);
if (result.exitCode != 0) {
print('cipd ensure stdout:\n${result.stdout}\n');
print('cipd ensure stderr:\n${result.stderr}\n');
throw Exception('Failed to download the CIPD package.');
}
if (isVerbose) {
print('Download completes.');
}
Directory.current = previous;
}
@protected
Future<void> ensureResources() async {
await doEnsureResources(resourcesRoot, isVerbose: isVerbose);
}
@protected
void checkRequiredOption(String option) {
if (argResults[option] == null) {
throw Exception('Option $option is required.');
}
}
@protected
bool get isVerbose => argResults[kFlagVerbose];
@protected
String get outJson => argResults[kOptionOutJson];
@protected
String get resourcesRoot => argResults[kOptionResourcesRoot];
}
abstract class IosCpuGpuSubcommand extends BaseCommand {
IosCpuGpuSubcommand() {
argParser.addOption(
kOptionProessName,
abbr: 'p',
help: 'Specifies the process name used for filtering the instruments CPU '
'measurements.',
defaultsTo: kDefaultProccessName,
);
}
@protected
String get processName => argResults[kOptionProessName];
@protected
String get traceUtilityPath => '$resourcesRoot/resources/TraceUtility';
}

View File

@ -1,19 +0,0 @@
// 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 'package:args/command_runner.dart';
import 'package:gauge/commands/ioscpugpu/new.dart';
import 'package:gauge/commands/ioscpugpu/parse.dart';
class IosCpuGpu extends Command<void> {
IosCpuGpu() {
addSubcommand(IosCpuGpuNew());
addSubcommand(IosCpuGpuParse());
}
@override
String get name => 'ioscpugpu';
@override
String get description => 'Measure the iOS CPU/GPU percentage.';
}

View File

@ -1,112 +0,0 @@
// 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 'dart:io';
import 'package:gauge/commands/base.dart';
import 'package:gauge/parser.dart';
/// See also: [IosCpuGpu]
class IosCpuGpuNew extends IosCpuGpuSubcommand {
IosCpuGpuNew() {
argParser.addOption(
kOptionTimeLimitMs,
abbr: 'l',
defaultsTo: '5000',
help: 'time limit (in ms) to run instruments for measuring',
);
argParser.addOption(
kOptionDevice,
abbr: 'w',
help: 'device identifier recognizable by instruments '
'(e.g., 00008020-000364CE0AF8003A)',
);
}
@override
String get name => 'new';
@override
String get description => 'Take a new measurement on the iOS CPU/GPU '
'percentage (of Flutter Runner).';
String get _timeLimit => argResults[kOptionTimeLimitMs];
String get _templatePath =>
'$resourcesRoot/resources/CpuGpuTemplate.tracetemplate';
@override
Future<void> run() async {
_checkDevice();
await ensureResources();
print('Running instruments on iOS device $_device for ${_timeLimit}ms');
final List<String> args = <String>[
'-l',
_timeLimit,
'-t',
_templatePath,
'-w',
_device,
];
if (isVerbose) {
print('instruments args: $args');
}
final ProcessResult processResult = Process.runSync('instruments', args);
_parseTraceFilename(processResult.stdout.toString());
print('Parsing $_traceFilename');
final IosTraceParser parser = IosTraceParser(isVerbose, traceUtilityPath);
final CpuGpuResult result = parser.parseCpuGpu(_traceFilename, processName);
result.writeToJsonFile(outJson);
print('$result\nThe result has been written into $outJson');
}
String _traceFilename;
void _parseTraceFilename(String out) {
const String kPrefix = 'Instruments Trace Complete: ';
final int prefixIndex = out.indexOf(kPrefix);
if (prefixIndex == -1) {
throw Exception('Failed to parse instruments output:\n$out');
}
_traceFilename = out.substring(prefixIndex + kPrefix.length).trim();
}
String _device;
void _checkDevice() {
_device = argResults[kOptionDevice];
if (_device != null) {
return;
}
final ProcessResult result = Process.runSync(
'instruments',
<String>['-s', 'devices'],
);
for (String line in result.stdout.toString().split('\n')) {
if (line.contains('iPhone') && !line.contains('Simulator')) {
_device = RegExp(r'\[(.+)\]').firstMatch(line).group(1);
break;
}
}
if (_device == null) {
print('''
Option device (-w) is not provided, and failed to find an iPhone(not a
simulator) from `instruments -s devices`.
stdout of `instruments -s device`:
===========================
${result.stdout}
===========================
stderr of `instruments -s device`:
===========================
${result.stderr}
===========================
''');
throw Exception('Failed to determine the device.');
}
}
}

View File

@ -1,40 +0,0 @@
// 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:gauge/commands/base.dart';
import 'package:gauge/parser.dart';
/// See also: [IosCpuGpu]
class IosCpuGpuParse extends IosCpuGpuSubcommand {
@override
String get name => 'parse';
@override
String get description =>
'Parse an existing instruments trace with CPU/GPU measurements.';
@override
String get usage {
return super.usage.split('\n').map((String line) {
return line + (line.startsWith('Usage:') ? ' <trace-file-path>' : '');
}).join('\n');
}
@override
Future<void> run() async {
if (argResults.rest.length != 1) {
print(usage);
throw Exception('exactly one argument <trace-file-path> expected');
}
final String path = argResults.rest[0];
await ensureResources();
final CpuGpuResult result = IosTraceParser(isVerbose, traceUtilityPath)
.parseCpuGpu(path, processName);
result.writeToJsonFile(outJson);
print('$result\nThe result has been written into $outJson');
}
}

View File

@ -1,128 +0,0 @@
// 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:convert';
import 'dart:io';
/// Class that represents the CPU and GPU usage percentage.
///
/// See also: [IosTraceParser.parseCpuGpu]
class CpuGpuResult {
CpuGpuResult(this.gpuPercentage, this.cpuPercentage);
final double gpuPercentage;
final double cpuPercentage;
@override
String toString() {
return 'gpu: $gpuPercentage%, cpu: $cpuPercentage%';
}
void writeToJsonFile(String filename) {
final String output = json.encode(<String, double>{
'gpu_percentage': gpuPercentage,
'cpu_percentage': cpuPercentage
});
File(filename).writeAsStringSync(output);
}
}
/// Parser that distills the output from TraceUtility.
///
/// See also: https://github.com/Qusic/TraceUtility
class IosTraceParser {
/// Creates a [IosTraceParser] that runs the TraceUtility executable at
/// [traceUtilityPath], verbosely if [isVerbose] is true.
IosTraceParser(this.isVerbose, this.traceUtilityPath);
final bool isVerbose;
final String traceUtilityPath;
List<String> _lines;
List<String> _gpuMeasurements;
List<String> _cpuMeasurements;
/// Runs TraceUtility on the file at [filename] and parses the output for the
/// process named [processName] that is needed for [CpuGpuResult].
CpuGpuResult parseCpuGpu(String filename, String processName) {
final ProcessResult result = Process.runSync(
traceUtilityPath,
<String>[filename],
);
if (result.exitCode != 0) {
print('TraceUtility stdout:\n${result.stdout.toString}\n\n');
print('TraceUtility stderr:\n${result.stderr.toString}\n\n');
throw Exception('TraceUtility failed with exit code ${result.exitCode}');
}
_lines = result.stderr.toString().split('\n');
// toSet to remove duplicates
_gpuMeasurements =
_lines.where((String s) => s.contains('GPU')).toSet().toList();
_cpuMeasurements =
_lines.where((String s) => s.contains(processName)).toSet().toList();
_gpuMeasurements.sort();
_cpuMeasurements.sort();
if (isVerbose) {
_gpuMeasurements.forEach(print);
_cpuMeasurements.forEach(print);
}
return CpuGpuResult(_computeGpuPercent(), _computeCpuPercent());
}
static final RegExp _percentagePattern = RegExp(r'(\d+(\.\d*)?)%');
double _parseSingleGpuMeasurement(String line) {
return double.parse(_percentagePattern.firstMatch(line).group(1));
}
double _computeGpuPercent() {
return _average(_gpuMeasurements.map(_parseSingleGpuMeasurement));
}
// The return is a list of 2: the 1st is the time key string, the 2nd is the
// double percentage
List<dynamic> _parseSingleCpuMeasurement(String line) {
final String timeKey = line.substring(0, line.indexOf(','));
final RegExpMatch match = _percentagePattern.firstMatch(line);
return <dynamic>[
timeKey,
match == null
? 0
: double.parse(_percentagePattern.firstMatch(line).group(1))
];
}
double _computeCpuPercent() {
final Iterable<List<dynamic>> results =
_cpuMeasurements.map(_parseSingleCpuMeasurement);
final Map<String, double> sums = <String, double>{};
for (List<dynamic> pair in results) {
sums[pair[0]] = 0;
}
for (List<dynamic> pair in results) {
sums[pair[0]] += pair[1];
}
// This key always has 0% usage. Remove it.
assert(sums['00:00.000.000'] == 0);
sums.remove('00:00.000.000');
if (isVerbose) {
print('CPU maps: $sums');
}
return _average(sums.values);
}
double _average(Iterable<double> values) {
if (values == null || values.isEmpty) {
print('TraceUtility output:\n${_lines.join('\n')}\n\n');
print('GPU measurements:\n${_gpuMeasurements.join('\n')}\n\n');
print('CPU measurements:\n${_cpuMeasurements.join('\n')}\n\n');
throw Exception('No valid measurements found.');
}
return values.reduce((double a, double b) => a + b) / values.length;
}
}

View File

@ -1,21 +0,0 @@
name: gauge
description:
Tools for gauging/measuring some performance metrics.
Currently there's only one tool to measure iOS CPU/GPU usages for Flutter's CI
tests.
homepage: https://github.com/flutter/packages/tree/master/packages/gauge
version: 0.1.5
executables:
gauge: gauge
dependencies:
args: ^1.5.2
meta: ^1.1.7
dev_dependencies:
test: ^1.6.8
environment:
sdk: ">=2.2.2 <3.0.0"

View File

@ -1,90 +0,0 @@
// 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.
@TestOn('posix')
import 'dart:io';
import 'package:gauge/commands/base.dart';
import 'package:test/test.dart';
void main() {
final String gaugeRootPath = Directory.current.absolute.path;
test('help works', () {
final ProcessResult result = Process.runSync(
'dart',
<String>['$gaugeRootPath/bin/gauge.dart', 'help'],
);
expect(
result.stdout.toString(),
contains(
'Tools for gauging/measuring some performance metrics.',
));
});
test('ioscpugpu parse help works', () {
final ProcessResult result = Process.runSync(
'dart',
<String>['$gaugeRootPath/bin/gauge.dart', 'ioscpugpu', 'parse'],
);
final String help = result.stdout.toString();
expect(
help.split('\n')[0],
equals('Parse an existing instruments trace with CPU/GPU measurements.'),
);
expect(
help,
contains('Usage: gauge ioscpugpu parse [arguments] <trace-file-path>'),
);
});
test('cipd downloading is triggered.', () {
final ProcessResult result = Process.runSync(
'dart',
<String>[
'$gaugeRootPath/bin/gauge.dart',
'ioscpugpu',
'parse',
'non-existent-file',
'--verbose'
],
);
expect(
result.stdout.toString(),
contains('Downloading resources from CIPD...'),
);
expect(
Directory('${BaseCommand.defaultResourcesRoot}/resources').existsSync(),
isTrue,
);
});
test('depot_tools is downloaded.', () {
final Directory depotToolsDir =
Directory('${BaseCommand.defaultResourcesRoot}/depot_tools');
if (depotToolsDir.existsSync()) {
depotToolsDir.deleteSync(recursive: true);
}
expect(
depotToolsDir.existsSync(),
isFalse,
);
Process.runSync(
'dart',
<String>[
'$gaugeRootPath/bin/gauge.dart',
'ioscpugpu',
'parse',
'non-existent-file',
'--verbose'
],
);
expect(
depotToolsDir.existsSync(),
isTrue,
);
});
}

View File

@ -1,76 +0,0 @@
// 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.
@TestOn('mac-os')
import 'dart:io';
import 'package:test/test.dart';
import 'package:gauge/commands/base.dart';
void main() {
final String gaugeRootPath = Directory.current.absolute.path;
final String resourcesRootPath = BaseCommand.defaultResourcesRoot;
BaseCommand.doEnsureResources(resourcesRootPath);
ProcessResult _testIosCpuGpu(List<String> extraArgs) {
return Process.runSync(
'dart',
<String>[
'$gaugeRootPath/bin/gauge.dart',
'ioscpugpu',
...extraArgs,
'-r',
resourcesRootPath,
],
);
}
ProcessResult _testParse(List<String> extraArgs) {
return _testIosCpuGpu(<String>[
'parse',
'$resourcesRootPath/resources/example_instrumentscli.trace/',
...extraArgs,
]);
}
test('ioscpugpu parse works', () {
final ProcessResult result = _testParse(<String>[]);
expect(
result.stdout.toString(),
contains(
'gpu: 12.6%, cpu: 18.15%',
));
expect(
File('result.json').readAsStringSync(),
contains(
'{"gpu_percentage":12.6,"cpu_percentage":18.15}',
));
});
test('ioscpugpu parse works with verbose', () {
final ProcessResult result = _testParse(<String>['--verbose']);
expect(
result.stdout.toString(),
contains(
'00:00.000.000 0 FPS 13.0% GPU',
));
expect(
result.stdout.toString(),
contains(
'00:00.477.632, 1.55 s, Runner (2209), n/a, 2209, mobile, 23.7%',
));
});
test('ioscpugpu new works', () {
final ProcessResult result = _testIosCpuGpu(<String>['new']);
expect(
result.stdout.toString(),
contains('The result has been written into result.json'),
reason: '\n\nioscpugpu new failed. Do you have a single connected iPhone '
'that has a Flutter app running?',
);
});
}