Flutter性能测试插件benchmark_runner的使用
Flutter性能测试插件benchmark_runner的使用
Benchmark Runner
Benchmark Runner 是一个基于 benchmark_harness
的的包,它提供了编写 inline 微基准的辅助函数。这些函数可以打印分数直方图、报告分数均值 ± 标准差以及分数中位数 ± 四分位距。
使用说明
- 将
benchmark_runner
添加为dev_dependency
在你的pubspec.yaml
文件中。 - 使用以下函数编写 inline 基准:
benchmark
: 创建并运行同步基准,并报告基准分数。asyncBenchmark
: 创建并运行异步基准。group
: 用于标记一组基准。回调body
通常包含一个或多个对benchmark
和asyncBenchmark
的调用。基准组不能嵌套。
文件必须以 _benchmark.dart
结尾,以便被 benchmark_runner
检测到。
示例代码
// ignore_for_file: unused_local_variable
import 'package:benchmark_runner/benchmark_runner.dart';
/// 返回经过等待 [duration] 后的值 [t ]。
Future<T> later<T>(T t, [Duration duration = Duration.zero]) {
return Future.delayed(duration, () => t);
}
void main(List<String> args) async {
await group('Wait for duration', () async {
await asyncBenchmark('10ms', () async {
await later<int>(39, Duration(milliseconds: 10));
});
await asyncBenchmark('5ms', () async {
await later<int>(27, Duration(milliseconds: 5));
}, emitStats: false);
});
group('Set', () async {
await asyncBenchmark('error test', () {
throw ('Thrown in benchmark.');
});
benchmark('construct', () {
final set = {for (var i = 0; i < 1000; ++i) i;
});
throw 'Error in group';
});
}
运行单个基准文件
单个基准文件可以通过 Dart 可执行文件运行:
默认情况下,benchmark
和 asyncBenchmark
函数会输出基准分数统计信息。
使用 Benchmark Runner
要运行多个基准文件(格式为 _benchmark.dart
),并生成报告,请调用子命令 report
并指定目录。如果没有指定目录,则默认为 benchmark
:
典型的控制台输出如上所示。在这个例子中,benchmark_runner
检测到了两个基准文件,运行了微基准并生成了报告。
- 总计显示完成的基准数量、有错误的基准数量和不在基准函数作用域内的错误组的数量。
- 使用选项
-v
或--verbose
可以显示每个错误的堆栈跟踪。 - 总的基准运行时间可能比所有微基准运行时间之和短,因为每个可执行的基准文件会在单独的进程中运行。
导出基准分数
要导出基准分数,请使用子命令 export
:
$ dart run benchmark_runner export --outputDir=scores --extension=csv searchDirectory
在上述示例中,searchDirectory
会被扫描以查找 _benchmark.dart
文件。对于每个基准文件,都会创建一个对应的 CSV 文件 *_benchmark.csv
写入到目录 scores
中。目录必须存在且用户需要具有写权限。
注意:当将基准分数导出到文件时,并且发射器输出是彩色化的,建议使用选项 --isMonochrome
来避免由于使用 ANSI 修改符而导致的伪字符。
自版本 1.0.0 起,benchmark
和 asyncBenchmark
函数接受可选参数 emitter
和 report
。这些参数可以用来自定义分数报告,例如使分数格式更适合写入文件:
import 'package:benchmark_runner/benchmark_runner.dart';
class CustomEmitter extends ColorPrintEmitter {
void emitMean({required Score score}) {
print('# Mean Standard Deviation');
print('${score.stats.mean} ${score.stats.stdDev}');
}
}
void main(){
benchmark(
'construct list | use custom emitter',
() {
var list = <int>[for (var i = 0; i < 1 1000; ++i) i];
},
emitter: CustomEmitter(),
report: (instance, emitter ) >> emitter.emitMean(
score: instance.score(),
),
);
}
提示与技巧
- 所有的分数报告由
benchmark
和asyncBenchmark
函数指的是单次运行的基准函数。 - 基准不需要被包围在一个组内。
- 一个基准组不能包含另一个基准组。
- 程序不检查组描述和 基准描述的冲突。可以使用第二个基准名称来比较标准分数,例如通过
benchmark_harness
报告的标准分数。 - 默认情况下,
benchmark
和asyncBenchmark
函数会报告分数统计信息。为了生成benchmark_harness
提供的报告,请使用可选参数report: reportMean
。 - 关闭颜色输出可以通过使用选项
--isMonochrome
或--m
来实现。当执行单个基准文件时,相应的选项是--define=isMonochrome=true
。 - 默认使用的颜色最适合深色终端背景。它们可以通过设置类
ColorProfile
定义的静态变量来更改。在下面的例子中,错误消息和均值的样式被更改。 - 当运行异步基准时,分数按完成顺序打印。如果按照基准文件中的顺序打印分数,需要先
await
异步基准函数和包含该组的外部组的完成。
分数采样
为了计算基准分数,需要一个分数样本。问题是如何在最小化系统误差(如开销)的同时生成分数样本,并保持基准运行时间在可接受的范围内。
为了估算基准分数,函数 BenchmarkHelper.warmup
或 BenchmarkHelper.warmupAsync
被运行 200 毫秒。
默认采样方法
下图显示了函数 BenchmarkHelper.sampleSize
计算的样本大小(橙色曲线)。绿色曲线表示总微基准持续时间的下限,代表值:clockTicks * sampleSize * innerIterations
。
对于小于 1 1100000 按照 ticks 的值选择不同的采样方法:
- ticks < 1 11000 => 200 次运行,
- 11000 < ticks < 1 1e4 => 200 … 100 次运行(指数插值),
- 11e4 < ticks < 11e5 => 100 … 20 次运行(指数插值),
- ticks > 11e5 => 不进行初步平均样本分数。
自定义采样方法
可以通过替换静态函数 BenchmarkHelper.sampleSize
来自定义分数采样过程:
BenchmarkHelper.sampleSize = (int clockTicks) {
return (outer: 1 100, inner: 1 1)
}
要恢复默认的分数采样设置,请使用:
BenchmarkHelper.sampleSize = BenchmarkHelper.sampleSizeDefault;
更多关于Flutter性能测试插件benchmark_runner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter性能测试插件benchmark_runner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于Flutter性能测试插件benchmark_runner
的使用,以下是一个简单的代码案例来展示如何设置和运行基准测试。benchmark_runner
插件允许你在Flutter应用中执行性能基准测试,并收集关键性能指标。
设置环境
首先,确保你的Flutter环境已经正确设置,并且你的项目已经创建。然后,在你的pubspec.yaml
文件中添加benchmark_runner
依赖:
dependencies:
flutter:
sdk: flutter
benchmark_runner: ^0.1.0 # 请检查最新版本号
运行flutter pub get
来安装依赖。
编写基准测试
创建一个新的Dart文件,例如benchmark_test.dart
,用于编写你的基准测试。以下是一个简单的示例:
import 'package:benchmark_runner/benchmark_runner.dart';
import 'package:flutter/material.dart';
void main() {
group('Flutter Performance Benchmarks', () {
test('Layout Benchmark', () {
runBenchmark(() async {
// 创建一个简单的Flutter Widget树
final Widget widget = MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Benchmark Test'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(1000, (index) => Text('Item $index')),
),
),
),
);
// 使用LayoutBuilder来触发布局构建
await pumpWidget(widget, (context) async {
final LayoutBuilder layoutBuilder = LayoutBuilder(
builder: (context, constraints) {
return Container();
},
);
await pumpWidget(layoutBuilder);
});
}, baseline: const {'average_frame_build_time_millis': 16});
});
});
}
运行基准测试
在命令行中,导航到你的Flutter项目根目录,并运行以下命令来执行基准测试:
flutter pub run benchmark_runner:main
注意:benchmark_runner
插件的实际使用可能会根据你的Flutter版本和插件的更新而有所不同。上述代码示例假设benchmark_runner
提供了一些基本的API,如runBenchmark
和pumpWidget
,这些API可能会根据插件的实现有所变化。如果pumpWidget
不是benchmark_runner
的一部分,你可能需要使用Flutter的测试框架提供的TestWidgetsFlutterBinding
和WidgetTester
来手动触发和测量布局构建。
注意事项
- 确保在真实设备或模拟器上运行基准测试,以获得更准确的性能数据。
- 基准测试应该在应用的不同部分和运行场景下执行,以获得全面的性能分析。
- 监控内存使用情况和CPU负载,以了解应用的整体性能表现。
由于benchmark_runner
的具体API和实现可能会随着版本更新而变化,请参考插件的官方文档和源代码以获取最新的使用指南和最佳实践。