Flutter异步性能测试插件async_benchmark的使用
Flutter异步性能测试插件async_benchmark的使用
async_benchmark
是一个用于运行和分析基准测试的Dart包,支持隔离环境和性能跟踪。
使用
import 'dart:math';
import 'package:async_benchmark/async_benchmark.dart';
void main() async {
final profile =
BenchmarkProfile('custom', warmup: 10, interactions: 100, rounds: 3);
await BenchmarkPrime(seed: 12345).run(profile: profile, verbose: true);
}
class BenchmarkPrime extends Benchmark<int, Prime> {
final int? seed;
BenchmarkPrime({this.seed}) : super('PrimeCounter(seed: ${seed ?? '*'})');
@override
BenchmarkSetupResult<int, Prime> setup() {
var prime = Prime();
var rand = Random(seed);
var limit = rand.nextInt(999999);
return (setup: limit, service: prime);
}
@override
void job(int setup, Prime? service) {
var prime = service ?? Prime();
prime.countPrimes(setup);
}
}
class Prime {
int countPrimes(int limit) {
var count = 0;
for (var n = 2; n <= limit; ++n) {
if (isPrime(n)) {
++count;
}
}
return count;
}
bool isPrime(int n) {
if (n <= 1) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
var sqr = sqrt(n);
for (var b = 3; b <= sqr; b += 2) {
if (n % b == 0) return false;
}
return true;
}
@override
String toString() => 'Prime{}';
}
输出结果
╔═══════════════════════════╗
║ PrimeCounter(seed: 12345) ║
╠═══════════════════════════╝
║ BenchmarkProfile[custom]{warmup: 10, interactions: 100, rounds: 3}
╠────────────────────────────
║ Setup...
║ ─ (service: Prime{}, setup: 155253)
║ Warmup (10)...
╠────────────────────────────
║ ROUND: 1/3
║
║ ─ Running (100)...
║ ─ Teardown...
║
║ »» Duration: 0:00:01.356317
║ »» Speed: 73.7291 Hz
║ »» Interaction Time: 13.563 ms
╠────────────────────────────
║ ROUND: 2/3
║
║ ─ Running (100)...
║ ─ Teardown...
║
║ »» Duration: 0:00:01.352660
║ »» Speed: 73.9284 Hz
║ »» Interaction Time: 13.527 ms
╠────────────────────────────
║ ROUND: 3/3
║
║ ─ Running (100)...
║ ─ Teardown...
║
║ »» Duration: 0:00:01.359452
║ »» Speed: 73.5591 Hz
║ »» Interaction Time: 13.595 ms
╠────────────────────────────
║ BEST ROUND: 2
║
║ »» Duration: 0:00:01.352660
║ »» Speed: 73.9284 Hz
║ »» Interaction Time: 13.527 ms
╠────────────────────────────
║ Shutdown...
╚════════════════════════════
完整示例Demo
以下是一个完整的示例,展示了如何使用 async_benchmark
运行多个基准测试并比较它们的性能。
import 'dart:collection';
import 'dart:math';
import 'package:async_benchmark/async_benchmark.dart';
void main() async {
final profile =
BenchmarkProfile('custom', warmup: 10, interactions: 100, rounds: 3);
final seed = 123;
var benchmarks = <Benchmark<int, Prime>>[
BenchmarkPrimeCached(seed: seed),
BenchmarkPrime(seed: seed),
];
await benchmarks.runAll(profile: profile, verbose: true);
}
class BenchmarkPrimeCached extends Benchmark<int, PrimeCached> {
final int? seed;
BenchmarkPrimeCached({this.seed})
: super('PrimeCounterCached(seed: ${seed ?? '*'})');
static final Pool<PrimeCached> _primePool = Pool(() => PrimeCached());
@override
BenchmarkSetupResult<int, PrimeCached> setup() {
var prime = _primePool.catchElement();
var rand = Random(seed);
var limit = rand.nextInt(999999);
return (setup: limit, service: prime);
}
@override
void job(int setup, Prime? service) {
var prime = service ?? _primePool.catchElement();
prime.countPrimes(setup);
}
@override
void teardown(int setup, PrimeCached? service) async {
if (service != null) {
service.clearCache();
}
}
@override
void shutdown(int setup, PrimeCached? service) async {
if (service != null) {
_primePool.releaseElement(service);
}
}
}
class BenchmarkPrime extends Benchmark<int, Prime> {
final int? seed;
BenchmarkPrime({this.seed}) : super('PrimeCounter(seed: ${seed ?? '*'})');
@override
BenchmarkSetupResult<int, Prime> setup() {
var prime = Prime();
var rand = Random(seed);
var limit = rand.nextInt(999999);
return (setup: limit, service: prime);
}
@override
void job(int setup, Prime? service) {
var prime = service ?? Prime();
prime.countPrimes(setup);
}
}
class PrimeCached extends Prime {
final Set<int> _primesCache = {};
int get cacheLength => _primesCache.length;
void clearCache() {
_primesCache.clear();
_isPrimeCached = 0;
_isPrimeComputed = 0;
}
int _isPrimeCached = 0;
int _isPrimeComputed = 0;
({int cached, int computed}) get isPrimeStats =>
(cached: _isPrimeCached, computed: _isPrimeComputed);
@override
bool isPrime(int n) {
if (n <= 1) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
if (_primesCache.contains(n)) {
++_isPrimeCached;
return true;
}
var sqr = sqrt(n);
for (var b = 3; b <= sqr; b += 2) {
if (n % b == 0) return false;
}
++_isPrimeComputed;
_primesCache.add(n);
return true;
}
@override
String toString() => 'PrimeCached{cache: ${_primesCache.length}}';
}
class Prime {
int countPrimes(int limit) {
var count = 0;
for (var n = 2; n <= limit; ++n) {
if (isPrime(n)) {
++count;
}
}
return count;
}
bool isPrime(int n) {
if (n <= 1) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
var sqr = sqrt(n);
for (var b = 3; b <= sqr; b += 2) {
if (n % b == 0) return false;
}
return true;
}
@override
String toString() => 'Prime{}';
}
class Pool<E extends Object> {
final E Function() instantiator;
Pool(this.instantiator);
final Queue<E> _pool = Queue();
E catchElement() {
if (_pool.isEmpty) {
return instantiator();
} else {
return _pool.removeLast();
}
}
bool releaseElement(E? element) {
if (element != null && _pool.length < 10) {
_pool.add(element);
return true;
} else {
return false;
}
}
}
输出结果
╔═══════════════════════════════╗
║ PrimeCounterCached(seed: 123) ║
╠═══════════════════════════════╝
║ BenchmarkProfile[custom]{warmup: 10, interactions: 100, rounds: 3}
╠────────────────────────────────
║ Setup...
║ ─ (service: PrimeCached{cache: 0}, setup: 999502)
║ Warmup (10)...
╠────────────────────────────────
║ ROUND: 1/3
║
║ ─ Running (100)...
║ ─ Teardown...
║
║ »» Duration: 0:00:06.366585
║ »» Speed: 15.7070 Hz
║ »» Interaction Time: 63.666 ms
╠────────────────────────────────
║ ROUND: 2/3
║
║ ─ Running (100)...
║ ─ Teardown...
║
║ »» Duration: 0:00:06.548992
║ »» Speed: 15.2695 Hz
║ »» Interaction Time: 65.490 ms
╠────────────────────────────────
║ ROUND: 3/3
║
║ ─ Running (100)...
║ ─ Teardown...
║
║ »» Duration: 0:00:06.541619
║ »» Speed: 15.2867 Hz
║ »» Interaction Time: 65.416 ms
╠────────────────────────────────
║ BEST ROUND: 1
║
║ »» Duration: 0:00:06.366585
║ »» Speed: 15.7070 Hz
║ »» Interaction Time: 63.666 ms
╠────────────────────────────────
║ Shutdown...
╚════════════════════════════════
╔═════════════════════════╗
║ PrimeCounter(seed: 123) ║
╠═════════════════════════╝
║ BenchmarkProfile[custom]{warmup: 10, interactions: 100, rounds: 3}
╠──────────────────────────
║ Setup...
║ ─ (service: Prime{}, setup: 999502)
║ Warmup (10)...
╠──────────────────────────
║ ROUND: 1/3
║
║ ─ Running (100)...
║ ─ Teardown...
║
║ »» Duration: 0:00:17.028856
║ »» Speed: 5.8724 Hz
║ »» Interaction Time: 170.289 ms
╠──────────────────────────
║ ROUND: 2/3
║
║ ─ Running (100)...
║ ─ Teardown...
║
║ »» Duration: 0:00:16.985658
║ »» Speed: 5.8873 Hz
║ »» Interaction Time: 169.857 ms
╠──────────────────────────
║ ROUND: 3/3
║
║ ─ Running (100)...
║ ─ Teardown...
║
║ »» Duration: 0:00:17.001885
║ »» Speed: 5.8817 Hz
║ »» Interaction Time: 170.019 ms
╠──────────────────────────
║ BEST ROUND: 2
║
║ »» Duration: 0:00:16.985658
║ »» Speed: 5.8873 Hz
║ »» Interaction Time: 169.857 ms
╠──────────────────────────
║ Shutdown...
╚══════════════════════════
╔════════════════════════════════
║ BEST BENCHMARK: PrimeCounterCached(seed: 123) (round: 1)
║
║ »» Duration: 0:00:06.366585
║ »» Speed: 15.7070 Hz
║ »» Interaction Time: 63.666 ms
╠────────────────────────────────
║ BENCHMARK: PrimeCounter(seed: 123) (round: 2)
║ »» Duration: 0:00:16.985658
║ »» Speed: 5.8873 Hz
║ »» Interaction Time: 169.857 ms
║ »» Speed ratio: 0.3748 (2.6679 x)
╚════════════════════════════════
更多关于Flutter异步性能测试插件async_benchmark的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter异步性能测试插件async_benchmark的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用Flutter异步性能测试插件async_benchmark
的代码示例。async_benchmark
是一个用于测量Flutter应用中异步操作执行时间的工具。
首先,确保你已经在你的pubspec.yaml
文件中添加了async_benchmark
依赖:
dependencies:
flutter:
sdk: flutter
async_benchmark: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter应用中使用async_benchmark
来测量异步操作的性能。以下是一个示例代码:
import 'package:flutter/material.dart';
import 'package:async_benchmark/async_benchmark.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Async Benchmark Example'),
),
body: Center(
child: AsyncBenchmarkButton(),
),
),
);
}
}
class AsyncBenchmarkButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async {
// 使用async_benchmark来测量异步操作的性能
final benchmark = await runAsyncBenchmark('measure async operation') {
// 在这里放置你要测量的异步操作
await Future.delayed(Duration(seconds: 2));
};
// 打印结果
print('Benchmark result: ${benchmark.toJson()}');
// 你可以在UI中显示结果,例如使用Snackbar
ScaffoldMessenger.of(context).showSnackbar(
Snackbar(
content: Text(
'Async operation took ${benchmark.averageDuration.inMilliseconds}ms on average',
),
),
);
},
child: Text('Measure Async Operation'),
);
}
}
在这个示例中,我们创建了一个Flutter应用,其中包含一个按钮。当点击按钮时,会触发一个异步操作(在这个例子中是Future.delayed
模拟的2秒延迟),并使用async_benchmark
来测量这个操作的性能。
runAsyncBenchmark
函数接受一个描述性字符串(用于标识测量的操作)和一个闭包(包含要测量的异步操作)。它返回一个BenchmarkResult
对象,你可以打印或显示这个结果。
BenchmarkResult
对象包含了多个有用的属性,如averageDuration
(平均持续时间)、minDuration
(最小持续时间)、maxDuration
(最大持续时间)等。
注意:在实际应用中,你应该将Future.delayed
替换为你想要测量的实际异步操作。
这个示例展示了如何使用async_benchmark
来测量和显示异步操作的性能,从而帮助你优化你的Flutter应用。