mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
191 lines
5.8 KiB
Dart
191 lines
5.8 KiB
Dart
// Copyright 2014 The Flutter 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:flutter/foundation.dart';
|
|
|
|
import '../common.dart';
|
|
|
|
const int _kNumIterations = 65536;
|
|
const int _kNumWarmUp = 100;
|
|
const int _kScale = 1000;
|
|
|
|
void main() {
|
|
assert(false, "Don't run benchmarks in debug mode! Use 'flutter run --release'.");
|
|
|
|
// In the following benchmarks, we won't remove the listeners when we don't
|
|
// want to measure removeListener because we know that everything will be
|
|
// GC'ed in the end.
|
|
// Not removing listeners would cause memory leaks in a real application.
|
|
|
|
final BenchmarkResultPrinter printer = BenchmarkResultPrinter();
|
|
|
|
void runAddListenerBenchmark(int iteration, {bool addResult = true}) {
|
|
const String name = 'add';
|
|
for (int listenerCount = 1; listenerCount <= 5; listenerCount += 1) {
|
|
final List<_Notifier> notifiers = List<_Notifier>.generate(
|
|
iteration,
|
|
(_) => _Notifier(),
|
|
growable: false,
|
|
);
|
|
|
|
final Stopwatch watch = Stopwatch();
|
|
watch.start();
|
|
for (int i = 0; i < iteration; i += 1) {
|
|
for (int l = 0; l < listenerCount; l += 1) {
|
|
notifiers[i].addListener(() {});
|
|
}
|
|
}
|
|
watch.stop();
|
|
final int elapsed = watch.elapsedMicroseconds;
|
|
final double averagePerIteration = elapsed / iteration;
|
|
if (addResult) {
|
|
printer.addResult(
|
|
description: '$name ($listenerCount listeners)',
|
|
value: averagePerIteration * _kScale,
|
|
unit: 'ns per iteration',
|
|
name: '$name$listenerCount',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
void runNotifyListenerBenchmark(int iteration, {bool addResult = true}) {
|
|
const String name = 'notify';
|
|
|
|
for (int listenerCount = 0; listenerCount <= 5; listenerCount += 1) {
|
|
final _Notifier notifier = _Notifier();
|
|
for (int i = 1; i <= listenerCount; i += 1) {
|
|
notifier.addListener(() {});
|
|
}
|
|
final Stopwatch watch = Stopwatch();
|
|
watch.start();
|
|
for (int i = 0; i < iteration; i += 1) {
|
|
notifier.notify();
|
|
}
|
|
watch.stop();
|
|
final int elapsed = watch.elapsedMicroseconds;
|
|
final double averagePerIteration = elapsed / iteration;
|
|
if (addResult) {
|
|
printer.addResult(
|
|
description: '$name ($listenerCount listeners)',
|
|
value: averagePerIteration * _kScale,
|
|
unit: 'ns per iteration',
|
|
name: '$name$listenerCount',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
void runRemoveListenerBenchmark(int iteration, {bool addResult = true}) {
|
|
const String name = 'remove';
|
|
final List<VoidCallback> listeners = <VoidCallback>[
|
|
() {},
|
|
() {},
|
|
() {},
|
|
() {},
|
|
() {},
|
|
];
|
|
for (int listenerCount = 1; listenerCount <= 5; listenerCount += 1) {
|
|
final List<_Notifier> notifiers = List<_Notifier>.generate(
|
|
iteration,
|
|
(_) {
|
|
final _Notifier notifier = _Notifier();
|
|
for (int l = 0; l < listenerCount; l += 1) {
|
|
notifier.addListener(listeners[l]);
|
|
}
|
|
return notifier;
|
|
},
|
|
growable: false,
|
|
);
|
|
|
|
final Stopwatch watch = Stopwatch();
|
|
watch.start();
|
|
for (int i = 0; i < iteration; i += 1) {
|
|
for (int l = 0; l < listenerCount; l += 1) {
|
|
notifiers[i].removeListener(listeners[l]);
|
|
}
|
|
}
|
|
watch.stop();
|
|
final int elapsed = watch.elapsedMicroseconds;
|
|
final double averagePerIteration = elapsed / iteration;
|
|
if (addResult) {
|
|
printer.addResult(
|
|
description: '$name ($listenerCount listeners)',
|
|
value: averagePerIteration * _kScale,
|
|
unit: 'ns per iteration',
|
|
name: '$name$listenerCount',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
void runRemoveListenerWhileNotifyingBenchmark(int iteration,
|
|
{bool addResult = true}) {
|
|
const String name = 'removeWhileNotify';
|
|
|
|
final List<VoidCallback> listeners = <VoidCallback>[
|
|
() {},
|
|
() {},
|
|
() {},
|
|
() {},
|
|
() {},
|
|
];
|
|
for (int listenerCount = 1; listenerCount <= 5; listenerCount += 1) {
|
|
final List<_Notifier> notifiers = List<_Notifier>.generate(
|
|
iteration,
|
|
(_) {
|
|
final _Notifier notifier = _Notifier();
|
|
notifier.addListener(() {
|
|
// This listener will remove all other listeners. So that only this
|
|
// one is called and measured.
|
|
for (int l = 0; l < listenerCount; l += 1) {
|
|
notifier.removeListener(listeners[l]);
|
|
}
|
|
});
|
|
for (int l = 0; l < listenerCount; l += 1) {
|
|
notifier.addListener(listeners[l]);
|
|
}
|
|
return notifier;
|
|
},
|
|
growable: false,
|
|
);
|
|
|
|
final Stopwatch watch = Stopwatch();
|
|
watch.start();
|
|
for (int i = 0; i < iteration; i += 1) {
|
|
notifiers[i].notify();
|
|
}
|
|
watch.stop();
|
|
final int elapsed = watch.elapsedMicroseconds;
|
|
final double averagePerIteration = elapsed / iteration;
|
|
if (addResult) {
|
|
printer.addResult(
|
|
description: '$name ($listenerCount listeners)',
|
|
value: averagePerIteration * _kScale,
|
|
unit: 'ns per iteration',
|
|
name: '$name$listenerCount',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
runAddListenerBenchmark(_kNumWarmUp, addResult: false);
|
|
runAddListenerBenchmark(_kNumIterations);
|
|
|
|
runNotifyListenerBenchmark(_kNumWarmUp, addResult: false);
|
|
runNotifyListenerBenchmark(_kNumIterations);
|
|
|
|
runRemoveListenerBenchmark(_kNumWarmUp, addResult: false);
|
|
runRemoveListenerBenchmark(_kNumIterations);
|
|
|
|
runRemoveListenerWhileNotifyingBenchmark(_kNumWarmUp, addResult: false);
|
|
runRemoveListenerWhileNotifyingBenchmark(_kNumIterations);
|
|
|
|
printer.printToStdout();
|
|
}
|
|
|
|
class _Notifier extends ChangeNotifier {
|
|
void notify() => notifyListeners();
|
|
}
|