Profiling and benchmarking your app
One of the key success factors of Dart is its performance. The Dart VM has a built-in optimizer to increase the execution speed. This optimizer needs a certain amount of execution time before it has enough information to do its work. This is no problem for an app in production, but when testing, you must ensure this condition is met. In this recipe, we are going to focus on how to best benchmark your application.
Getting ready
The benchmark_harness
package from the Dart team is built specifically for this purpose. Add it to the pubspec.yaml
file and import it in your code. We will illustrate this with the template_benchmark
app. Also, make sure that all the issues detected by the checked mode are solved (because these could have an effect on the execution speed) and that the app is run in the production mode (refer to the Setting up the checked and production modes recipe in Chapter 1, Working with Dart Tools).
How to do it...
Perform the following steps to get the benchmark harness working:
- Import the benchmark library:
import 'package:benchmark_harness/benchmark_harness.dart';
- Define a class
TemplateBenchmark
with its ownmain()
andrun()
methods. It is a subclass of classBenchmarkBase
in thebenchmark
library. The benchmark is started fromrun()
:class TemplateBenchmark extends BenchmarkBase { const TemplateBenchmark() : super("Template"); static void main() { new TemplateBenchmark().report(); } void run() { fib(20); } // recursive algorithms: int fib(int i) { if (i < 2) return i; return fib(i-1) + fib(i-2); } // int fib(n) => n<2 ? n : fib(n-2) + fib(n-1); // iterative algorithm: // int fib(int i){ // int a = 0; int b = 1; // for (int n=a; n < b; n++) { // a = a + b; b = a; // } // return a; // } void setup() { } void teardown() { } }
- The following code starts the whole benchmark machinery:
main() { TemplateBenchmark.main(); }
- If we benchmark the Fibonacci algorithm for the two recursive implementations (
with if
andwith the
ternary operators) and the iterative algorithm, we get the following results:Template(RunTime): 482.392667631452 us.
Template(RunTime): 498.00796812749 us.
Template(RunTime): 0.2441818187589752 us.
As we expected, the iterative algorithm performs orders of magnitude better than working recursively.
How it works...
Create a new benchmark by extending the BenchmarkBase
class (here, TemplateBenchmark
). The benchmarked code is called from the run()
method within this subclass. The setup()
and teardown()
function code are run before and after the benchmark to prepare for the benchmark or clean up after it. These are not taken into account for the benchmark itself. The top-level mai
n()
function runs the benchmark by calling main()
from the subclass of BenchmarkBase
.
See also
- Refer to the new Observatory tool to profile Dart apps at https://www.dartlang.org/tools/observatory/