Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
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
15 changes: 15 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ task:
FRAMEWORK_PATH: "/tmp/master_framework"
PATH: "$FLUTTER_ENGINE/third_party/dart/tools/sdks/dart-sdk/bin:$DEPOT_TOOLS:$PATH"
USE_ANDROID: "False"
# TODO(liyuqian): currently we're using flutter-cirrus GCP project. Migrate
# to flutter-infra project once the metrics_center service is stabilized,
BENCHMARK_GCP_CREDENTIALS: ENCRYPTED[da76d2b7b39894de70fae1fc9182c97cc41400adc93f0f1c49bc7442f15fb933da8d756ed88523810a9a77c34f51a693]
setup_script: |
git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git $DEPOT_TOOLS
mkdir -p $ENGINE_PATH/src
Expand All @@ -29,6 +32,18 @@ task:
mv $CIRRUS_WORKING_DIR flutter
gclient sync
matrix:
- name: build_and_benchmark_linux_release
only_if: $CIRRUS_BRANCH == 'master' # Only run for post-submit commits.
compile_host_script: |
cd $ENGINE_PATH/src
./flutter/tools/gn --runtime-mode=release
ninja -C out/host_release
benchmark_host_script: |
cd $ENGINE_PATH/src/out/host_release/
./txt_benchmarks --benchmark_format=json > txt_benchmarks.json
cd $ENGINE_PATH/src/flutter/testing/benchmark
pub get
dart bin/parse_and_send.dart ../../../out/host_release/txt_benchmarks.json
- name: build_and_test_linux_unopt_debug
compile_host_script: |
cd $ENGINE_PATH/src
Expand Down
1 change: 1 addition & 0 deletions testing/benchmark/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
secret
2 changes: 2 additions & 0 deletions testing/benchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This is a Dart project that runs the engine benchmarks, and send the metrics to
the cloud for storage and analysis.
54 changes: 54 additions & 0 deletions testing/benchmark/bin/parse_and_send.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
Copy link
Contributor

Choose a reason for hiding this comment

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

2019?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The engine repo enforces 2013 through the license check script.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, I see.

// 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';

import 'package:git/git.dart';
import 'package:metrics_center/flutter.dart';
import 'package:metrics_center/google_benchmark.dart';

Future<String> _getGitRevision() async {
final GitDir gitDir = await GitDir.fromExisting('../../');
// Somehow gitDir.currentBranch() doesn't work in Cirrus with "fatal: 'HEAD' -
// not a valid ref". Therefore, we use "git log" to get the revision manually.
final ProcessResult logResult =
await gitDir.runCommand(<String>['log', '--pretty=format:%H', '-n', '1']);
if (logResult.exitCode != 0) {
throw 'Unexpected exit code ${logResult.exitCode}';
}
return logResult.stdout.toString();
}

Future<List<FlutterEngineMetricPoint>> _parse(String jsonFileName) async {
final String gitRevision = await _getGitRevision();
final List<MetricPoint> rawPoints =
await GoogleBenchmarkParser.parse(jsonFileName);
final List<FlutterEngineMetricPoint> points = <FlutterEngineMetricPoint>[];
for (MetricPoint rawPoint in rawPoints) {
points.add(FlutterEngineMetricPoint(
rawPoint.tags[kNameKey],
rawPoint.value,
gitRevision,
moreTags: rawPoint.tags,
));
}
Copy link

Choose a reason for hiding this comment

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

Nit: I would also put parsing an item into a sub function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

return points;
}

Future<void> main(List<String> args) async {
if (args.length != 1) {
Copy link

Choose a reason for hiding this comment

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

Consider using ArgParser()..addFlag, https://dart.dev/tutorials/server/cmdline

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe addFlag is only for boolean, and I didn't use addOption because I think a simple positional argument is better than a named option here. Also, I didn't find a way to make an option as required using args package... Overall, I found args package to bring more overhead than convenience in this case.

throw 'Must have one argument: <benchmark_json_file>';
}
final List<FlutterEngineMetricPoint> points = await _parse(args[0]);
Copy link
Contributor

@keyonghan keyonghan Dec 21, 2019

Choose a reason for hiding this comment

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

One check to make sure the file(args[0]) exists before moving forward?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The current code generates the following error when the file does not exist:

Unhandled exception:
FileSystemException: Cannot open file, path = 'test.json' (OS Error: No such file or directory, errno = 2)

Does that look good?

// The data will be sent to the Datastore of the GCP project specified through
// environment variable BENCHMARK_GCP_CREDENTIALS. The engine Cirrus job has
// currently configured the GCP project to flutter-cirrus for test. We'll
// eventually migrate to flutter-infra project once the test is done.
final FlutterDestination destination =
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe good to document which DB this link points to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

await FlutterDestination.makeFromCredentialsJson(
jsonDecode(Platform.environment['BENCHMARK_GCP_CREDENTIALS']),
);
await destination.update(points);
}
32 changes: 32 additions & 0 deletions testing/benchmark/example/txt_benchmarks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"context": {
"date": "2019-12-17 15:14:14",
"num_cpus": 56,
"mhz_per_cpu": 2594,
"cpu_scaling_enabled": true,
"library_build_type": "release"
},
"benchmarks": [
{
"name": "BM_PaintRecordInit",
"iterations": 6749079,
"real_time": 101,
"cpu_time": 101,
"time_unit": "ns"
},
{
"name": "BM_ParagraphShortLayout",
"iterations": 151761,
"real_time": 4460,
"cpu_time": 4460,
"time_unit": "ns"
},
{
"name": "BM_ParagraphStylesBigO_BigO",
"cpu_coefficient": 6548,
"real_coefficient": 6548,
"big_o": "N",
"time_unit": "ns"
}
]
}
15 changes: 15 additions & 0 deletions testing/benchmark/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: flutter_engine_benchmark

dependencies:
git: any
metrics_center:
# TODO(liyuqian): once metrics_center is properly reviewed, add it to
# flutter/packages, publish on pub.dev, and use the published package here.
git: https://github.com/liyuqian/metrics_center.git
Copy link

Choose a reason for hiding this comment

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

What does metrics center do and why not integrating parse_and_send.dart into metrics center?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Metric center is mainly responsible for extract, transform, and load from some metric database (e.g., cocoon) to some other metric database (e.g., skiaperf). Metric center is itself a database so a client (the engine repo) can directly write metrics into it.

In this case, I intended to only put the client code/logic in the engine repo. That said, I should probably put the transform code (_parse) in the metric center repo, so if some future client also needs to transform https://github.com/google/benchmark results, it doesn't have to rewrite the code.

Thanks for the suggestion!


dev_dependencies:
test: any
pedantic: ^1.8.0

environment:
sdk: ">=2.2.2 <3.0.0"
24 changes: 24 additions & 0 deletions testing/benchmark/test/parse_and_send_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
Copy link
Contributor

Choose a reason for hiding this comment

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

same here. 2019?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same enforcement of 2013 unfortunately...

// 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:test/test.dart';

void main() {
// In order to run this test, one should download a service account
// credentials json from a test GCP project, and put that json as
// `secret/test_gcp_credentials.json`. There's a `flutter-test` project for
// Flutter team members.
test('parse_and_send with example json does not crash.', () async {
final String testCred =
File('secret/test_gcp_credentials.json').readAsStringSync();
Copy link

Choose a reason for hiding this comment

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

This "secret" directory is git-ignored, then how could another one run this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One should download a service account credentials json from a test GCP project, and put that json as secret/test_gcp_credentials.json. There's a flutter-test project for Flutter team members. I'll add this instruction to the code.

Process.runSync('dart', <String>[
'bin/parse_and_send.dart',
'example/txt_benchmarks.json',
], environment: <String, String>{
'BENCHMARK_GCP_CREDENTIALS': testCred,
});
});
}