Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ GeneratedPluginRegistrant.m
GeneratedPluginRegistrant.java

packages/measure/result.json
packages/measure/resources
*instrumentscli*.trace
*.cipd

21 changes: 15 additions & 6 deletions packages/measure/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
Tools for measuring some performance metrics.

Currently there's only one tool to measure iOS CPU/GPU usages for Flutter's CI
tests.

# Install

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a section explaining what this packages does / what it is for?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


Make sure that `pub` is on your path. Then run:
First install [depot_tools][1] (we used its `cipd`).

Then install [dart](https://dart.dev/get-dart) and make sure that `pub` is on
your path.

Finally run:
```shell
pub global activate measure
```

# Run
First, make sure that `dart` is available on your path.

Then, connect an iPhone, run a Flutter app on it, and
Connect an iPhone, run a Flutter app on it, and
```shell
# assuming that you're in this directory
measure ioscpugpu new -u resources/TraceUtility -t resources/CpuGpuTemplate.tracetemplate
measure ioscpugpu new
```

Sample output:
Expand All @@ -26,3 +33,5 @@ measure help ioscpugpu
measure help ioscpugpu new
measure help ioscpugpu parse
```

[1]: https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up
5 changes: 5 additions & 0 deletions packages/measure/cipd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package: flutter/packages/measure/resources
description: Binaries and other resources for measuring performance metrics.
install_mode: copy
data:
- dir: resources
68 changes: 56 additions & 12 deletions packages/measure/lib/commands/base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
// 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 kOptionTemplate = 'template';
const String kOptionDevice = 'device';
const String kOptionProessName = 'process-name';
const String kOptionTraceUtility = 'trace-utility';
const String kOptionOutJson = 'out-json';
const String kFlagVerbose = 'verbose';

Expand All @@ -21,9 +22,57 @@ abstract class BaseCommand extends Command<void> {
argParser.addOption(
kOptionOutJson,
abbr: 'o',
help: 'json file for the measure result.',
help: 'Specifies the json file for outputing result.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for result output.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

defaultsTo: 'result.json',
);
argParser.addOption(
kOptionResourcesRoot,
abbr: 'r',
help: 'Specifies the path to download resources',
defaultsTo: defaultResourcesRoot,
);
}

static String get defaultResourcesRoot =>
'${Platform.environment['HOME']}/.measure';

static Future<void> doEnsureResources(
String rootPath,
{bool isVerbose}) async
{
final Directory root =
await Directory(rootPath).create(recursive: true);
final Directory previous = Directory.current;
Directory.current = root;
final File ensureFile = File('ensure_file.txt');
ensureFile.writeAsStringSync('flutter/packages/measure/resources latest');
if (isVerbose) {
print('Downloading resources from CIPD...');
}
final ProcessResult result = Process.runSync(
'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 {
doEnsureResources(resourcesRoot, isVerbose: isVerbose);
}

@protected
Expand All @@ -37,17 +86,12 @@ abstract class BaseCommand extends Command<void> {
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(
kOptionTraceUtility,
abbr: 'u',
help:
'Specifies path to TraceUtility binary '
'(https://github.com/Qusic/TraceUtility).',
);
argParser.addOption(
kOptionProessName,
abbr: 'p',
Expand All @@ -58,8 +102,8 @@ abstract class IosCpuGpuSubcommand extends BaseCommand {
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

@protected
String get traceUtility => argResults[kOptionTraceUtility];
@protected
String get processName => argResults[kOptionProessName];
@protected
String get traceUtilityPath => '$resourcesRoot/resources/TraceUtility';
}
17 changes: 7 additions & 10 deletions packages/measure/lib/commands/ioscpugpu/new.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ class IosCpuGpuNew extends IosCpuGpuSubcommand {
defaultsTo: '5000',
help: 'time limit (in ms) to run instruments for measuring',
);
argParser.addOption(
kOptionTemplate,
abbr: 't',
help: 'instruments template'
);
argParser.addOption(
kOptionDevice,
abbr: 'w',
Expand All @@ -37,17 +32,19 @@ class IosCpuGpuNew extends IosCpuGpuSubcommand {

String get _timeLimit => argResults[kOptionTimeLimitMs];

String get _templatePath =>
'$resourcesRoot/resources/CpuGpuTemplate.tracetemplate';

@override
Future<void> run() async {
checkRequiredOption(kOptionTemplate);
checkRequiredOption(kOptionTraceUtility);
_checkDevice();
await ensureResources();

print('Running instruments on iOS device $_device for ${_timeLimit}ms');

final List<String> args = <String>[
'-l', _timeLimit,
'-t', argResults[kOptionTemplate],
'-t', _templatePath,
'-w', _device,
];
if (isVerbose) {
Expand All @@ -58,8 +55,8 @@ class IosCpuGpuNew extends IosCpuGpuSubcommand {

print('Parsing $_traceFilename');

final CpuGpuResult result =
IosTraceParser(isVerbose, traceUtility).parseCpuGpu(_traceFilename, processName);
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');
}
Expand Down
5 changes: 3 additions & 2 deletions packages/measure/lib/commands/ioscpugpu/parse.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@ class IosCpuGpuParse extends IosCpuGpuSubcommand {

@override
Future<void> run() async {
checkRequiredOption(kOptionTraceUtility);
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, traceUtility).parseCpuGpu(path, processName);
IosTraceParser(isVerbose, traceUtilityPath).parseCpuGpu(path, processName);
result.writeToJsonFile(outJson);
print('$result\nThe result has been written into $outJson');
}
Expand Down
Binary file not shown.
41 changes: 9 additions & 32 deletions packages/measure/test/measure_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import 'dart:io';

import 'package:test/test.dart';

import 'package:measure/commands/base.dart';

void main() {
const String measureRootPath = '.';

final String resourcesRootPath = BaseCommand.defaultResourcesRoot;
BaseCommand.doEnsureResources(resourcesRootPath, isVerbose: true);

test('help works', () {
final ProcessResult result = Process.runSync(
'dart', <String>['$measureRootPath/bin/measure.dart', 'help'],
Expand All @@ -25,38 +30,16 @@ void main() {
'$measureRootPath/bin/measure.dart',
'ioscpugpu',
...extraArgs,
'-r',
resourcesRootPath,
],
);
}

test('trace-utility is required for ioscpugpu parse', () {
final ProcessResult result = _testIosCpuGpu(
<String>['parse', 'not_existed.trace'],
);
expect(result.stderr.toString(), contains(
'Option trace-utility is required.',
));
});

test('trace-utility is required for ioscpugpu new', () {
final ProcessResult result = _testIosCpuGpu(
<String>['new', '-t', 'not_existed.tracetemplate'],
);
expect(result.stderr.toString(), contains(
'Option trace-utility is required.',
));
});

ProcessResult _testParse(List<String> extraArgs) {
Process.runSync('unzip', <String>[
'-u', '$measureRootPath/resources/example_instrumentscli.trace.zip',
'-d', '$measureRootPath/resources/',
]);
return _testIosCpuGpu(<String>[
'parse',
'-u',
'$measureRootPath/resources/TraceUtility',
'$measureRootPath/resources/example_instrumentscli.trace/',
'$resourcesRootPath/resources/example_instrumentscli.trace/',
...extraArgs,
]);
}
Expand All @@ -82,13 +65,7 @@ void main() {
});

test('ioscpugpu new works', () {
final ProcessResult result = _testIosCpuGpu(<String>[
'new',
'-u',
'$measureRootPath/resources/TraceUtility',
'-t',
'$measureRootPath/resources/CpuGpuTemplate.tracetemplate',
]);
final ProcessResult result = _testIosCpuGpu(<String>['new']);
expect(
result.stdout.toString(),
contains('The result has been written into result.json'),
Expand Down