// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:async'; import 'dart:io'; import 'dart:isolate'; import 'dart:math'; import 'package:expect/expect.dart'; // Implements recursive summation via tail calls: // fib(n) => n <= 1 ? 1 // : fib(n-1) + fib(n-2); Future fibonacciRecursive(List args) async { final SendPort port = args[0]; final n = args[1]; if (n <= 1) { port.send(1); return; } final left = ReceivePort(); final right = ReceivePort(); await Future.wait([ Isolate.spawn(fibonacciRecursive, [left.sendPort, n - 1]), Isolate.spawn(fibonacciRecursive, [right.sendPort, n - 2]), ]); final results = await Future.wait([left.first, right.first]); port.send(results[0] + results[1]); } Future main() async { final rpWarmup = ReceivePort(); final rpRun = ReceivePort(); final int nWarmup = 17; // enough runs to trigger optimized compilation final int nWarmupFactorial = 2584; // Runs for about 8 seconds. final int n = 21; final int nFactorial = 17711; final beforeRss = ProcessInfo.currentRss; int maxRss = beforeRss; final rssTimer = Timer.periodic(const Duration(milliseconds: 10), (_) { maxRss = max(ProcessInfo.currentRss, maxRss); }); final watch = Stopwatch(); watch.start(); // Warm up code by running a couple iterations in the main isolate. await Isolate.spawn(fibonacciRecursive, [rpWarmup.sendPort, nWarmup]); Expect.equals(nWarmupFactorial, await rpWarmup.first); final warmup = watch.elapsedMicroseconds; await Isolate.spawn(fibonacciRecursive, [rpRun.sendPort, n]); Expect.equals(nFactorial, await rpRun.first); final done = watch.elapsedMicroseconds; print('IsolateFibonacci_$n.Calculation(RunTimeRaw): ${done - warmup} us.'); print('IsolateFibonacci_$n.DeltaPeak(MemoryUse): ${maxRss - beforeRss}'); rssTimer.cancel(); }