|  | // Copyright (c) 2012, 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:isolate'; | 
|  | import 'dart:async'; | 
|  |  | 
|  | class Expect { | 
|  | static void equals(x, y) { | 
|  | if (x != y) throw new ArgumentError('not equal'); | 
|  | } | 
|  | } | 
|  |  | 
|  | class Fields { | 
|  | Fields(int i, int j) : fld1 = i, fld2 = j, fld5 = true {} | 
|  | int fld1; | 
|  | final int fld2; | 
|  | static int fld3; | 
|  | static const int fld4 = 10; | 
|  | bool fld5; | 
|  | } | 
|  | class FieldsTest { | 
|  | static Fields testMain() { | 
|  | Fields obj = new Fields(10, 20); | 
|  | Expect.equals(10, obj.fld1); | 
|  | Expect.equals(20, obj.fld2); | 
|  | Expect.equals(10, Fields.fld4); | 
|  | Expect.equals(true, obj.fld5); | 
|  | return obj; | 
|  | } | 
|  | } | 
|  | // Benchpress: A collection of micro-benchmarks. | 
|  | // Ported from internal v8 benchmark suite. | 
|  |  | 
|  | class Error { | 
|  | static void error(String msg) { | 
|  | throw msg; | 
|  | } | 
|  | } | 
|  |  | 
|  | // F i b o n a c c i | 
|  | class Fibonacci { | 
|  | static int fib(int n) { | 
|  | if (n <= 1) return 1; | 
|  | return fib(n - 1) + fib(n - 2); | 
|  | } | 
|  | } | 
|  |  | 
|  | class FibBenchmark extends BenchmarkBase { | 
|  | const FibBenchmark() : super("Fibonacci"); | 
|  |  | 
|  | void warmup() { | 
|  | Fibonacci.fib(10); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | var result = Fibonacci.fib(20); | 
|  | if (result != 10946) | 
|  | Error.error("Wrong result: $result. Should be: 10946."); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new FibBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // L o o p | 
|  | class Loop { | 
|  | static int loop(int outerIterations) { | 
|  | int sum = 0; | 
|  | for (int i = 0; i < outerIterations; i++) { | 
|  | for (int j = 0; j < 100; j++) { | 
|  | sum++; | 
|  | } | 
|  | } | 
|  | return sum; | 
|  | } | 
|  | } | 
|  |  | 
|  | class LoopBenchmark extends BenchmarkBase { | 
|  | const LoopBenchmark() : super("Loop"); | 
|  |  | 
|  | void warmup() { | 
|  | Loop.loop(10); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | var result = Loop.loop(200); | 
|  | if (result != 20000) | 
|  | Error.error("Wrong result: $result. Should be: 20000"); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new LoopBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // T o w e r s | 
|  | class TowersDisk { | 
|  | final int size; | 
|  | TowersDisk next; | 
|  |  | 
|  | TowersDisk(size) : this.size = size, next = null {} | 
|  | } | 
|  |  | 
|  | class Towers { | 
|  | List<TowersDisk> piles; | 
|  | int movesDone; | 
|  | Towers(int disks) | 
|  | : piles = new List<TowersDisk>(3), movesDone = 0 { | 
|  | build(0, disks); | 
|  | } | 
|  |  | 
|  | void build(int pile, int disks) { | 
|  | for (var i = disks - 1; i >= 0; i--) { | 
|  | push(pile, new TowersDisk(i)); | 
|  | } | 
|  | } | 
|  |  | 
|  | void push(int pile, TowersDisk disk) { | 
|  | TowersDisk top = piles[pile]; | 
|  | if ((top != null) && (disk.size >= top.size)) | 
|  | Error.error("Cannot put a big disk on a smaller disk."); | 
|  | disk.next = top; | 
|  | piles[pile] = disk; | 
|  | } | 
|  |  | 
|  | TowersDisk pop(int pile) { | 
|  | var top = piles[pile]; | 
|  | if (top == null) | 
|  | Error.error("Attempting to remove a disk from an empty pile."); | 
|  | piles[pile] = top.next; | 
|  | top.next = null; | 
|  | return top; | 
|  | } | 
|  |  | 
|  | void moveTop(int from, int to) { | 
|  | push(to, pop(from)); | 
|  | movesDone++; | 
|  | } | 
|  |  | 
|  | void move(int from, int to, int disks) { | 
|  | if (disks == 1) { | 
|  | moveTop(from, to); | 
|  | } else { | 
|  | int other = 3 - from - to; | 
|  | move(from, other, disks - 1); | 
|  | moveTop(from, to); | 
|  | move(other, to, disks - 1); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | class TowersBenchmark extends BenchmarkBase { | 
|  | const TowersBenchmark() : super("Towers"); | 
|  |  | 
|  | void warmup() { | 
|  | new Towers(6).move(0, 1, 6); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | var towers = new Towers(13); | 
|  | towers.move(0, 1, 13); | 
|  | if (towers.movesDone != 8191) { | 
|  | var moves = towers.movesDone; | 
|  | Error.error("Error in result: $moves should be: 8191"); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new TowersBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // S i e v e | 
|  | class SieveBenchmark extends BenchmarkBase { | 
|  | const SieveBenchmark() : super("Sieve"); | 
|  |  | 
|  | static int sieve(int size) { | 
|  | int primeCount = 0; | 
|  | List<bool> flags = new List<bool>(size + 1); | 
|  | for (int i = 1; i < size; i++) flags[i] = true; | 
|  | for (int i = 2; i < size; i++) { | 
|  | if (flags[i]) { | 
|  | primeCount++; | 
|  | for (int k = i + 1; k <= size; k += i) | 
|  | flags[k - 1] = false; | 
|  | } | 
|  | } | 
|  | return primeCount; | 
|  | } | 
|  |  | 
|  |  | 
|  | void warmup() { | 
|  | sieve(100); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | int result = sieve(1000); | 
|  | if (result != 168) | 
|  | Error.error("Wrong result: $result should be: 168"); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new SieveBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // P e r m u t e | 
|  | // The original benchmark uses one-based indexing. Even though arrays in JS and | 
|  | // lists in dart are zero-based, we stay with one-based indexing | 
|  | // (wasting one element). | 
|  | class Permute { | 
|  | int permuteCount; | 
|  | Permute() {} | 
|  |  | 
|  | void swap(int n, int k, List<int> list) { | 
|  | int tmp = list[n]; | 
|  | list[n] = list[k]; | 
|  | list[k] = tmp; | 
|  | } | 
|  |  | 
|  | void doPermute(int n, List<int> list) { | 
|  | permuteCount++; | 
|  | if (n != 1) { | 
|  | doPermute(n - 1, list); | 
|  | for (int k = n - 1; k >= 1; k--) { | 
|  | swap(n, k, list); | 
|  | doPermute(n - 1, list); | 
|  | swap(n, k, list); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | int permute(int size) { | 
|  | permuteCount = 0; | 
|  | List<int> list = new List<int>(size); | 
|  | for (int i = 1; i < size; i++) list[i] = i - 1; | 
|  | doPermute(size - 1, list); | 
|  | return permuteCount; | 
|  | } | 
|  | } | 
|  |  | 
|  | class PermuteBenchmark extends BenchmarkBase { | 
|  | const PermuteBenchmark() : super("Permute"); | 
|  |  | 
|  | void warmup() { | 
|  | new Permute().permute(4); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | int result = new Permute().permute(8); | 
|  | if (result != 8660) | 
|  | Error.error("Wrong result: $result should be: 8660"); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new PermuteBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Q u e e n s | 
|  | // The original benchmark uses one-based indexing. Even though arrays in JS and | 
|  | // lists in dart are zero-based, we stay with one-based indexing | 
|  | // (wasting one element). | 
|  | class Queens { | 
|  | static bool tryQueens(int i, | 
|  | List<bool> a, | 
|  | List<bool> b, | 
|  | List<bool> c, | 
|  | List<int> x) { | 
|  | int j = 0; | 
|  | bool q = false; | 
|  | while ((!q) && (j != 8)) { | 
|  | j++; | 
|  | q = false; | 
|  | if (b[j] && a[i + j] && c[i - j + 7]) { | 
|  | x[i] = j; | 
|  | b[j] = false; | 
|  | a[i + j] = false; | 
|  | c[i - j + 7] = false; | 
|  | if (i < 8) { | 
|  | q = tryQueens(i + 1, a, b, c, x); | 
|  | if (!q) { | 
|  | b[j] = true; | 
|  | a[i + j] = true; | 
|  | c[i - j + 7] = true; | 
|  | } | 
|  | } else { | 
|  | q = true; | 
|  | } | 
|  | } | 
|  | } | 
|  | return q; | 
|  | } | 
|  |  | 
|  | static void queens() { | 
|  | List<bool> a = new List<bool>(9); | 
|  | List<bool> b = new List<bool>(17); | 
|  | List<bool> c = new List<bool>(15); | 
|  | List<int> x = new List<int>(9); | 
|  | b[1] = false; | 
|  | for (int i = -7; i <= 16; i++) { | 
|  | if ((i >= 1) && (i <= 8)) a[i] = true; | 
|  | if (i >= 2) b[i] = true; | 
|  | if (i <= 7) c[i + 7] = true; | 
|  | } | 
|  |  | 
|  | if (!tryQueens(1, b, a, c, x)) | 
|  | Error.error("Error in queens"); | 
|  | } | 
|  | } | 
|  |  | 
|  | class QueensBenchmark extends BenchmarkBase { | 
|  | const QueensBenchmark() : super("Queens"); | 
|  |  | 
|  | void warmup() { | 
|  | Queens.queens(); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | Queens.queens(); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new QueensBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | // R e c u r s e | 
|  | class Recurse { | 
|  | static int recurse(int n) { | 
|  | if (n <= 0) return 1; | 
|  | recurse(n - 1); | 
|  | return recurse(n - 1); | 
|  | } | 
|  | } | 
|  |  | 
|  | class RecurseBenchmark extends BenchmarkBase { | 
|  | const RecurseBenchmark() : super("Recurse"); | 
|  |  | 
|  | void warmup() { | 
|  | Recurse.recurse(7); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | Recurse.recurse(13); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new RecurseBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | // S u m | 
|  | class SumBenchmark extends BenchmarkBase { | 
|  | const SumBenchmark() : super("Sum"); | 
|  |  | 
|  | static int sum(int start, int end) { | 
|  | var sum = 0; | 
|  | for (var i = start; i <= end; i++) sum += i; | 
|  | return sum; | 
|  | } | 
|  |  | 
|  | void warmup() { | 
|  | sum(1, 1000); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | int result = sum(1, 10000); | 
|  | if (result != 50005000) | 
|  | Error.error("Wrong result: $result should be 50005000"); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new SumBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | // H e l p e r   f u n c t i o n s   f o r   s o r t s | 
|  | class Random { | 
|  | static const int INITIAL_SEED = 74755; | 
|  | int seed; | 
|  | Random() : seed = INITIAL_SEED {} | 
|  |  | 
|  | int random() { | 
|  | seed = ((seed * 1309) + 13849) % 65536; | 
|  | return seed; | 
|  | } | 
|  | } | 
|  |  | 
|  | // | 
|  | class SortData { | 
|  | List<int> list; | 
|  | int min; | 
|  | int max; | 
|  |  | 
|  | SortData(int length) { | 
|  | Random r = new Random(); | 
|  | list = new List<int>(length); | 
|  | for (int i = 0; i < length; i++) list[i] = r.random(); | 
|  |  | 
|  | int min, max; | 
|  | min = max = list[0]; | 
|  | for (int i = 0; i < length; i++) { | 
|  | int e = list[i]; | 
|  | if (e > max) max = e; | 
|  | if (e < min) min = e; | 
|  | } | 
|  |  | 
|  | this.min = min; | 
|  | this.max = max; | 
|  | } | 
|  |  | 
|  | void check() { | 
|  | List<int> a = list; | 
|  | int len = a.length; | 
|  | if ((a[0] != min) || a[len - 1] != max) | 
|  | Error.error("List is not sorted"); | 
|  | for (var i = 1; i < len; i++) { | 
|  | if (a[i - 1] > a[i]) Error.error("List is not sorted"); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | // B u b b l e S o r t | 
|  | class BubbleSort { | 
|  | static void sort(List<int> a) { | 
|  | int len = a.length; | 
|  | for (int i = len - 2; i >= 0; i--) { | 
|  | for (int j = 0; j <= i; j++) { | 
|  | int c = a[j]; | 
|  | int n = a[j + 1]; | 
|  | if (c > n) { | 
|  | a[j] = n; | 
|  | a[j + 1] = c; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | class BubbleSortBenchmark extends BenchmarkBase { | 
|  | const BubbleSortBenchmark() : super("BubbleSort"); | 
|  |  | 
|  | void warmup() { | 
|  | SortData data = new SortData(30); | 
|  | BubbleSort.sort(data.list); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | SortData data = new SortData(130); | 
|  | BubbleSort.sort(data.list); | 
|  | data.check(); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new BubbleSortBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Q u i c k S o r t | 
|  | class QuickSort { | 
|  | static void sort(List<int> a, int low, int high) { | 
|  | int pivot = a[(low + high) >> 1]; | 
|  | int i = low; | 
|  | int j = high; | 
|  | while (i <= j) { | 
|  | while (a[i] < pivot) i++; | 
|  | while (pivot < a[j]) j--; | 
|  | if (i <= j) { | 
|  | int tmp = a[i]; | 
|  | a[i] = a[j]; | 
|  | a[j] = tmp; | 
|  | i++; | 
|  | j--; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (low < j) sort(a, low, j); | 
|  | if (i < high) sort(a, i, high); | 
|  | } | 
|  | } | 
|  |  | 
|  | class QuickSortBenchmark extends BenchmarkBase { | 
|  | const QuickSortBenchmark() : super("QuickSort"); | 
|  |  | 
|  | void warmup() { | 
|  | SortData data = new SortData(100); | 
|  | QuickSort.sort(data.list, 0, data.list.length - 1); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | SortData data = new SortData(800); | 
|  | QuickSort.sort(data.list, 0, data.list.length - 1); | 
|  | data.check(); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new QuickSortBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | // T r e e S o r t | 
|  | class TreeNodePress { | 
|  | int value; | 
|  | TreeNodePress left; | 
|  | TreeNodePress right; | 
|  |  | 
|  | TreeNodePress(int n) : value = n {} | 
|  |  | 
|  | void insert(int n) { | 
|  | if (n < value) { | 
|  | if (left == null) left = new TreeNodePress(n); | 
|  | else left.insert(n); | 
|  | } else { | 
|  | if (right == null) right = new TreeNodePress(n); | 
|  | else right.insert(n); | 
|  | } | 
|  | } | 
|  |  | 
|  | void check() { | 
|  | TreeNodePress left = this.left; | 
|  | TreeNodePress right = this.right; | 
|  | int value = this.value; | 
|  |  | 
|  | return ((left == null) || ((left.value < value) && left.check())) && | 
|  | ((right == null) || ((right.value >= value) && right.check())); | 
|  | } | 
|  | } | 
|  |  | 
|  | class TreeSort { | 
|  | static void sort(List<int> a) { | 
|  | int len = a.length; | 
|  | TreeNodePress tree = new TreeNodePress(a[0]); | 
|  | for (var i = 1; i < len; i++) tree.insert(a[i]); | 
|  | if (!tree.check()) Error.error("Invalid result, tree not sorted"); | 
|  | } | 
|  | } | 
|  |  | 
|  | class TreeSortBenchmark extends BenchmarkBase { | 
|  | const TreeSortBenchmark() : super("TreeSort"); | 
|  |  | 
|  | void warmup() { | 
|  | TreeSort.sort(new SortData(100).list); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | TreeSort.sort(new SortData(1000).list); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | // T a k | 
|  | class TakBenchmark extends BenchmarkBase { | 
|  | const TakBenchmark() : super("Tak"); | 
|  |  | 
|  | static void tak(int x, int y, int z) { | 
|  | if (y >= x) return z; | 
|  | return tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y)); | 
|  | } | 
|  |  | 
|  | void warmup() { | 
|  | tak(9, 6, 3); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | tak(18, 12, 6); | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new TakBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | // T a k l | 
|  | class ListElement { | 
|  | final int length; | 
|  | final ListElement next; | 
|  |  | 
|  | const ListElement(int length, ListElement next) | 
|  | : this.length = length, | 
|  | this.next = next; | 
|  |  | 
|  | static ListElement makeList(int length) { | 
|  | if (length == 0) return null; | 
|  | return new ListElement(length, makeList(length - 1)); | 
|  | } | 
|  |  | 
|  | static bool isShorter(ListElement x, ListElement y) { | 
|  | ListElement xTail = x; | 
|  | ListElement yTail = y; | 
|  | while (yTail != null) { | 
|  | if (xTail == null) return true; | 
|  | xTail = xTail.next; | 
|  | yTail = yTail.next; | 
|  | } | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | class Takl { | 
|  | static ListElement takl(ListElement x, ListElement y, ListElement z) { | 
|  | if (ListElement.isShorter(y, x)) { | 
|  | return takl(takl(x.next, y, z), | 
|  | takl(y.next, z, x), | 
|  | takl(z.next, x, y)); | 
|  | } else { | 
|  | return z; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | class TaklBenchmark extends BenchmarkBase { | 
|  | const TaklBenchmark() : super("Takl"); | 
|  |  | 
|  | void warmup() { | 
|  | Takl.takl(ListElement.makeList(8), | 
|  | ListElement.makeList(4), | 
|  | ListElement.makeList(3)); | 
|  | } | 
|  |  | 
|  | void exercise() { | 
|  | // This value has been copied from benchpress.js, so that we can compare | 
|  | // performance. | 
|  | ListElement result = Takl.takl(ListElement.makeList(15), | 
|  | ListElement.makeList(10), | 
|  | ListElement.makeList(6)); | 
|  | if (result.length != 10) { | 
|  | int len = result.length; | 
|  | Error.error("Wrong result: $len should be: 10"); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | new TaklBenchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // M a i n | 
|  |  | 
|  | class BenchPress { | 
|  | static void mainWithArgs(List<String> args) { | 
|  | List<BenchmarkBase> benchmarks = [ | 
|  | new BubbleSortBenchmark(), | 
|  | new FibBenchmark(), | 
|  | new LoopBenchmark(), | 
|  | new PermuteBenchmark(), | 
|  | new QueensBenchmark(), | 
|  | new QuickSortBenchmark(), | 
|  | new RecurseBenchmark(), | 
|  | new SieveBenchmark(), | 
|  | new SumBenchmark(), | 
|  | new TakBenchmark(), | 
|  | new TaklBenchmark(), | 
|  | new TowersBenchmark(), | 
|  | new TreeSortBenchmark(), | 
|  | ]; | 
|  | if (args.length > 0) { | 
|  | String benchName = args[0]; | 
|  | bool foundBenchmark = false; | 
|  | benchmarks.forEach((bench) { | 
|  | if (bench.name == benchName) { | 
|  | foundBenchmark = true; | 
|  | bench.report(); | 
|  | } | 
|  | }); | 
|  | if (!foundBenchmark) { | 
|  | Error.error("Benchmark not found: $benchName"); | 
|  | } | 
|  | return; | 
|  | } | 
|  | double logMean = 0.0; | 
|  | benchmarks.forEach((bench) { | 
|  | double benchScore = bench.measure(); | 
|  | String name = bench.name; | 
|  | print("$name: $benchScore"); | 
|  | logMean += Math.log(benchScore); | 
|  | }); | 
|  | logMean = logMean / benchmarks.length; | 
|  | double score = Math.pow(Math.E, logMean); | 
|  | print("BenchPress (average): $score"); | 
|  | } | 
|  |  | 
|  | // TODO(floitsch): let main accept arguments from the command line. | 
|  | static void main() { | 
|  | mainWithArgs([]); | 
|  | } | 
|  | } | 
|  |  | 
|  | class BenchmarkBase { | 
|  | final String name; | 
|  |  | 
|  | // Empty constructor. | 
|  | const BenchmarkBase(String name) : this.name = name; | 
|  |  | 
|  | // The benchmark code. | 
|  | // This function is not used, if both [warmup] and [exercise] are overwritten. | 
|  | void run() { } | 
|  |  | 
|  | // Runs a short version of the benchmark. By default invokes [run] once. | 
|  | void warmup() { | 
|  | run(); | 
|  | } | 
|  |  | 
|  | // Exercices the benchmark. By default invokes [run] 10 times. | 
|  | void exercise() { | 
|  | for (int i = 0; i < 10; i++) { | 
|  | run(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Not measured setup code executed prior to the benchmark runs. | 
|  | void setup() { } | 
|  |  | 
|  | // Not measures teardown code executed after the benchark runs. | 
|  | void teardown() { } | 
|  |  | 
|  | // Measures the score for this benchmark by executing it repeately until | 
|  | // time minimum has been reached. | 
|  | static double measureFor(Function f, int timeMinimum) { | 
|  | int time = 0; | 
|  | int iter = 0; | 
|  | DateTime start = new DateTime.now(); | 
|  | while (time < timeMinimum) { | 
|  | f(); | 
|  | time = (new DateTime.now().difference(start)).inMilliseconds; | 
|  | iter++; | 
|  | } | 
|  | // Force double result by using a double constant. | 
|  | return (1000.0 * iter) / time; | 
|  | } | 
|  |  | 
|  | // Measures the score for the benchmark and returns it. | 
|  | double measure() { | 
|  | setup(); | 
|  | // Warmup for at least 100ms. Discard result. | 
|  | measureFor(() { this.warmup(); }, -100); | 
|  | // Run the benchmark for at least 2000ms. | 
|  | double result = measureFor(() { this.exercise(); }, -2000); | 
|  | teardown(); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | void report() { | 
|  | double score = measure(); | 
|  | print("name: $score"); | 
|  | } | 
|  |  | 
|  | } | 
|  | class Logger { | 
|  | static print(object) { | 
|  | printobject(object); | 
|  | } | 
|  | static printobject(obj) { } | 
|  | } | 
|  |  | 
|  |  | 
|  | // | 
|  | // Dromaeo ObjectString | 
|  | // Adapted from Mozilla JavaScript performance test suite. | 
|  | // Microtests of strings (concatenation, methods). | 
|  |  | 
|  |  | 
|  | class ObjectString extends BenchmarkBase { | 
|  |  | 
|  | const ObjectString() : super("Dromaeo.ObjectString"); | 
|  |  | 
|  | static void main() { | 
|  | new ObjectString().report(); | 
|  | } | 
|  |  | 
|  | static void print(String str) { | 
|  | print(str); | 
|  | } | 
|  |  | 
|  | String getRandomString(int characters) { | 
|  | var result = ""; | 
|  | for (var i = 0; i < characters; i++) { | 
|  | result += Strings. | 
|  | createFromCodePoints([(25 * Math.random()).toInt() + 97]); | 
|  | } | 
|  | result += result; | 
|  | result += result; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | void run() { | 
|  | //JS Dromeaeo uses 16384 | 
|  | final ITERATE1 = 384; | 
|  | //JS Dromeaeo uses 80000 | 
|  | final ITERATE2 = 80; | 
|  | //JS Dromeaeo uses 5000 | 
|  | final ITERATE3 = 50; | 
|  | //JS Dromeaeo uses 5000 | 
|  | final ITERATE4 = 1; | 
|  | //JS Dromaeo uses 5000 | 
|  | final ITERATE5 = 1000; | 
|  |  | 
|  | var result; | 
|  | var text = getRandomString(ITERATE1); | 
|  |  | 
|  | ConcatStringBenchmark.test(ITERATE2); | 
|  | ConcatStringFromCharCodeBenchmark.test(ITERATE2); | 
|  | StringSplitBenchmark.test(text); | 
|  | StringSplitOnCharBenchmark.test(text); | 
|  | text += text; | 
|  | CharAtBenchmark.test(text, ITERATE3); | 
|  | NumberBenchmark.test(text, ITERATE3); | 
|  | CodeUnitAtBenchmark.test(text, ITERATE3); | 
|  | IndexOfBenchmark.test(text, ITERATE3); | 
|  | LastIndexOfBenchmark.test(text, ITERATE3); | 
|  | SliceBenchmark.test(text, ITERATE4); | 
|  | SubstrBenchmark.test(text, ITERATE4); | 
|  | SubstringBenchmark.test(text, ITERATE4); | 
|  | ToLowerCaseBenchmark.test(text, ITERATE5); | 
|  | ToUpperCaseBenchmark.test(text, ITERATE5); | 
|  | ComparingBenchmark.test(text, ITERATE5); | 
|  | } | 
|  | } | 
|  |  | 
|  | class ConcatStringBenchmark { | 
|  | ConcatStringBenchmark() {} | 
|  |  | 
|  | static String test(var iterations) { | 
|  | var str = ""; | 
|  | for (var i = 0; i < iterations; i++) { | 
|  | str += "a"; | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class ConcatStringFromCharCodeBenchmark { | 
|  | ConcatStringFromCharCodeBenchmark() {} | 
|  |  | 
|  | static String test(var iterations) { | 
|  | var str = ""; | 
|  | for (var i = 0; i < (iterations / 2); i++) { | 
|  | str += Strings.createFromCodePoints([97]); | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class StringSplitBenchmark { | 
|  | StringSplitBenchmark() {} | 
|  |  | 
|  | static List<String> test(String input) { | 
|  | return input.split(""); | 
|  | } | 
|  | } | 
|  |  | 
|  | class StringSplitOnCharBenchmark { | 
|  | StringSplitOnCharBenchmark() {} | 
|  |  | 
|  | static List<String> test(String input) { | 
|  | String multiple = input; | 
|  | multiple += multiple; | 
|  | multiple += multiple; | 
|  | multiple += multiple; | 
|  | multiple += multiple; | 
|  | return multiple.split("a"); | 
|  | } | 
|  | } | 
|  |  | 
|  | class CharAtBenchmark { | 
|  | CharAtBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < iterations; j++) { | 
|  | str = input[0]; | 
|  | str = input[input.length - 1]; | 
|  | str = input[150]; //set it to 15000 | 
|  | str = input[120]; //set it to 12000 | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class NumberBenchmark { | 
|  | NumberBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < iterations; j++) { | 
|  | str = input[0]; | 
|  | str = input[input.length - 1]; | 
|  | str = input[150]; //set it to 15000 | 
|  | str = input[100]; //set it to 10000 | 
|  | str = input[50]; //set it to 5000 | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | class CodeUnitAtBenchmark { | 
|  | CodeUnitAtBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < iterations; j++) { | 
|  | str = input.codeUnitAt(0); | 
|  | str = input.codeUnitAt(input.length - 1); | 
|  | str = input.codeUnitAt(150); //set it to 15000 | 
|  | str = input.codeUnitAt(100); //set it to 10000 | 
|  | str = input.codeUnitAt(50); //set it to 5000 | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class IndexOfBenchmark { | 
|  | IndexOfBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < iterations; j++) { | 
|  | str = input.indexOf("a", 0); | 
|  | str = input.indexOf("b", 0); | 
|  | str = input.indexOf("c", 0); | 
|  | str = input.indexOf("d", 0); | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class LastIndexOfBenchmark { | 
|  | LastIndexOfBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < iterations; j++) { | 
|  | str = input.lastIndexOf("a", input.length - 1); | 
|  | str = input.lastIndexOf("b", input.length - 1); | 
|  | str = input.lastIndexOf("c", input.length - 1); | 
|  | str = input.lastIndexOf("d", input.length - 1); | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class SliceBenchmark { | 
|  | SliceBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < iterations; j++) { | 
|  | str = input.substring(0, input.length - 1); | 
|  | str = input.substring(0, 5); | 
|  | str = input.substring(input.length - 1, input.length - 1); | 
|  | str = input.substring(input.length - 6, input.length - 1); | 
|  | str = input.substring(150, 155); //set to 15000 and 15005 | 
|  | str = input.substring(120, input.length-1); //set to 12000 | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class SubstrBenchmark { | 
|  | SubstrBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < iterations; j++) { | 
|  | str = input.substring(0, input.length-1); | 
|  | str = input.substring(0, 4); | 
|  | str = input.substring(input.length - 1, input.length - 1); | 
|  | str = input.substring(input.length - 6, input.length - 6); | 
|  | str = input.substring(150, 154); //set to 15000 and 15005 | 
|  | str = input.substring(120, 124); //set to 12000 | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class SubstringBenchmark { | 
|  | SubstringBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < iterations; j++) { | 
|  | str = input.substring(0, input.length - 1); | 
|  | str = input.substring(0, 4); | 
|  | str = input.substring(input.length - 1, input.length - 1); | 
|  | str = input.substring(input.length - 6, input.length - 2); | 
|  | str = input.substring(150, 154); //set to 15000 and 15005 | 
|  | str = input.substring(120, input.length - 2); //set to 12000 | 
|  | } | 
|  | return str; | 
|  |  | 
|  | } | 
|  | } | 
|  |  | 
|  | class ToLowerCaseBenchmark { | 
|  | ToLowerCaseBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < (iterations / 1000); j++) { | 
|  | str = Ascii.toLowerCase(input); | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class ToUpperCaseBenchmark { | 
|  | ToUpperCaseBenchmark() {} | 
|  |  | 
|  | static String test(String input, var iterations) { | 
|  | var str; | 
|  | for (var j = 0; j < (iterations / 1000); j++) { | 
|  | str = Ascii.toUpperCase(input); | 
|  | } | 
|  | return str; | 
|  | } | 
|  | } | 
|  |  | 
|  | class ComparingBenchmark { | 
|  | ComparingBenchmark() {} | 
|  |  | 
|  | static bool test(String input, var iterations) { | 
|  | var tmp = "a${input}a"; | 
|  | var tmp2 = "a${input}a"; | 
|  | var res; | 
|  | for (var j = 0; j < (iterations / 1000); j++) { | 
|  | res = (tmp.compareTo(tmp2) == 0); | 
|  | res = (tmp.compareTo(tmp2) < 0); | 
|  | res = (tmp.compareTo(tmp2) > 0); | 
|  | } | 
|  | return res; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Benchmarks basic message communication between two isolates. | 
|  |  | 
|  | class Benchmark1 { | 
|  |  | 
|  | static const MESSAGES = 10000; | 
|  | static const INIT_MESSAGE = 0; | 
|  | static const TERMINATION_MESSAGE = -1; | 
|  | static const WARMUP_TIME = 1000; | 
|  | static const RUN_TIME = 1000; | 
|  | static const RUNS = 5; | 
|  |  | 
|  |  | 
|  | static int run() { | 
|  | return _run; | 
|  | } | 
|  |  | 
|  | static void add_result(var opsms) { | 
|  | _run++; | 
|  | _opsms += opsms; | 
|  | } | 
|  |  | 
|  | static void get_result() { | 
|  | return _opsms / _run; | 
|  | } | 
|  |  | 
|  | static void init() { | 
|  | _run = 0; | 
|  | _opsms = 0.0; | 
|  | } | 
|  |  | 
|  | static void main() { | 
|  | init(); | 
|  | PingPongGame pingPongGame = new PingPongGame(); | 
|  | } | 
|  |  | 
|  | static var _run; | 
|  | static var _opsms; | 
|  | } | 
|  |  | 
|  | class PingPongGame { | 
|  |  | 
|  | PingPongGame() | 
|  | : _ping = new ReceivePort(), | 
|  | _pingPort = _ping.toSendPort(), | 
|  | _pong = null, | 
|  | _warmedup = false, | 
|  | _iterations = 0 { | 
|  | SendPort _pong = spawnFunction(pong); | 
|  | play(); | 
|  | } | 
|  |  | 
|  | void startRound() { | 
|  | _iterations++; | 
|  | _pong.send(Benchmark1.INIT_MESSAGE, _pingPort); | 
|  | } | 
|  |  | 
|  | void evaluateRound() { | 
|  | int time = (new DateTime.now().difference(_start)).inMilliseconds; | 
|  | if (!_warmedup && time < Benchmark1.WARMUP_TIME) { | 
|  | startRound(); | 
|  | } else if (!_warmedup) { | 
|  | _warmedup = true; | 
|  | _start = new DateTime.now(); | 
|  | _iterations = 0; | 
|  | startRound(); | 
|  | } else if (_warmedup && time < Benchmark1.RUN_TIME) { | 
|  | startRound(); | 
|  | } else { | 
|  | shutdown(); | 
|  | Benchmark1.add_result((1.0 * _iterations * Benchmark1.MESSAGES) / time); | 
|  | if (Benchmark1.run() < Benchmark1.RUNS) { | 
|  | new PingPongGame(); | 
|  | } else { | 
|  | print("PingPong: ", Benchmark1.get_result()); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void play() { | 
|  | _ping.receive((int message, SendPort replyTo) { | 
|  | if (message < Benchmark1.MESSAGES) { | 
|  | _pong.send(++message, null); | 
|  | } else { | 
|  | evaluateRound(); | 
|  | } | 
|  | }); | 
|  | _start = new DateTime.now(); | 
|  | startRound(); | 
|  | } | 
|  |  | 
|  | void shutdown() { | 
|  | _pong.send(Benchmark1.TERMINATION_MESSAGE, null); | 
|  | _ping.close(); | 
|  | } | 
|  |  | 
|  | DateTime _start; | 
|  | SendPort _pong; | 
|  | SendPort _pingPort; | 
|  | ReceivePort _ping; | 
|  | bool _warmedup; | 
|  | int _iterations; | 
|  | } | 
|  |  | 
|  | void pong() { | 
|  | port.receive((message, SendPort replyTo) { | 
|  | if (message == Benchmark1.INIT_MESSAGE) { | 
|  | replyTo.send(message, null); | 
|  | } else if (message == Benchmark1.TERMINATION_MESSAGE) { | 
|  | port.close(); | 
|  | } else { | 
|  | replyTo.send(message, null); | 
|  | } | 
|  | }); | 
|  | } | 
|  |  | 
|  |  | 
|  | class ManyGenericInstanceofTest { | 
|  | static testMain() { | 
|  | for (int i = 0; i < 5000; i++) { | 
|  | GenericInstanceof.testMain(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | // THE REST OF THIS FILE COULD BE AUTOGENERATED | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | // tests/isolate/spawn_test.dart | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | spawn_test_main() { | 
|  | test("spawn a new isolate", () { | 
|  | SendPort port = spawnFunction(entry); | 
|  | port.call(42).then(expectAsync1((message) { | 
|  | Expect.equals(42, message); | 
|  | })); | 
|  | }); | 
|  | } | 
|  |  | 
|  | void entry() { | 
|  | port.receive((message, SendPort replyTo) { | 
|  | Expect.equals(42, message); | 
|  | replyTo.send(42, null); | 
|  | port.close(); | 
|  | }); | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | // tests/isolate/isolate_negative_test.dart | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | void isolate_negative_entry() { | 
|  | port.receive((ignored, replyTo) { | 
|  | replyTo.send("foo", null); | 
|  | }); | 
|  | } | 
|  |  | 
|  | isolate_negative_test_main() { | 
|  | test("ensure isolate code is executed", () { | 
|  | SendPort port = spawnFunction(isolate_negative_entry); | 
|  | port.call("foo").then(expectAsync1((message) { | 
|  | Expect.equals(true, "Expected fail");   // <=-------- Should fail here. | 
|  | })); | 
|  | }); | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | // tests/isolate/message_test.dart | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | // Message passing test. | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | class MessageTest { | 
|  | static const List list1 = const ["Hello", "World", "Hello", 0xfffffffffff]; | 
|  | static const List list2 = const [null, list1, list1, list1, list1]; | 
|  | static const List list3 = const [list2, 2.0, true, false, 0xfffffffffff]; | 
|  | static const Map map1 = const { | 
|  | "a=1" : 1, "b=2" : 2, "c=3" : 3, | 
|  | }; | 
|  | static const Map map2 = const { | 
|  | "list1" : list1, "list2" : list2, "list3" : list3, | 
|  | }; | 
|  | static const List list4 = const [map1, map2]; | 
|  | static const List elms = const [ | 
|  | list1, list2, list3, list4, | 
|  | ]; | 
|  |  | 
|  | static void VerifyMap(Map expected, Map actual) { | 
|  | Expect.equals(true, expected is Map); | 
|  | Expect.equals(true, actual is Map); | 
|  | Expect.equals(expected.length, actual.length); | 
|  | testForEachMap(key, value) { | 
|  | if (value is List) { | 
|  | VerifyList(value, actual[key]); | 
|  | } else { | 
|  | Expect.equals(value, actual[key]); | 
|  | } | 
|  | } | 
|  | expected.forEach(testForEachMap); | 
|  | } | 
|  |  | 
|  | static void VerifyList(List expected, List actual) { | 
|  | for (int i = 0; i < expected.length; i++) { | 
|  | if (expected[i] is List) { | 
|  | VerifyList(expected[i], actual[i]); | 
|  | } else if (expected[i] is Map) { | 
|  | VerifyMap(expected[i], actual[i]); | 
|  | } else { | 
|  | Expect.equals(expected[i], actual[i]); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | static void VerifyObject(int index, var actual) { | 
|  | var expected = elms[index]; | 
|  | Expect.equals(true, expected is List); | 
|  | Expect.equals(true, actual is List); | 
|  | Expect.equals(expected.length, actual.length); | 
|  | VerifyList(expected, actual); | 
|  | } | 
|  | } | 
|  |  | 
|  | pingPong() { | 
|  | int count = 0; | 
|  | port.receive((var message, SendPort replyTo) { | 
|  | if (message == -1) { | 
|  | port.close(); | 
|  | replyTo.send(count, null); | 
|  | } else { | 
|  | // Check if the received object is correct. | 
|  | if (count < MessageTest.elms.length) { | 
|  | MessageTest.VerifyObject(count, message); | 
|  | } | 
|  | // Bounce the received object back so that the sender | 
|  | // can make sure that the object matches. | 
|  | replyTo.send(message, null); | 
|  | count++; | 
|  | } | 
|  | }); | 
|  | } | 
|  |  | 
|  | message_test_main() { | 
|  | test("send objects and receive them back", () { | 
|  | SendPort remote = spawnFunction(pingPong); | 
|  | // Send objects and receive them back. | 
|  | for (int i = 0; i < MessageTest.elms.length; i++) { | 
|  | var sentObject = MessageTest.elms[i]; | 
|  | // TODO(asiva): remove this local var idx once thew new for-loop | 
|  | // semantics for closures is implemented. | 
|  | var idx = i; | 
|  | remote.call(sentObject).then(expectAsync1((var receivedObject) { | 
|  | MessageTest.VerifyObject(idx, receivedObject); | 
|  | })); | 
|  | } | 
|  |  | 
|  | // Send recursive objects and receive them back. | 
|  | List local_list1 = ["Hello", "World", "Hello", 0xffffffffff]; | 
|  | List local_list2 = [null, local_list1, local_list1 ]; | 
|  | List local_list3 = [local_list2, 2.0, true, false, 0xffffffffff]; | 
|  | List sendObject = new List(5); | 
|  | sendObject[0] = local_list1; | 
|  | sendObject[1] = sendObject; | 
|  | sendObject[2] = local_list2; | 
|  | sendObject[3] = sendObject; | 
|  | sendObject[4] = local_list3; | 
|  | remote.call(sendObject).then((var replyObject) { | 
|  | Expect.equals(true, sendObject is List); | 
|  | Expect.equals(true, replyObject is List); | 
|  | Expect.equals(sendObject.length, replyObject.length); | 
|  | Expect.equals(true, identical(replyObject[1], replyObject)); | 
|  | Expect.equals(true, identical(replyObject[3], replyObject)); | 
|  | Expect.equals(true, identical(replyObject[0], replyObject[2][1])); | 
|  | Expect.equals(true, identical(replyObject[0], replyObject[2][2])); | 
|  | Expect.equals(true, identical(replyObject[2], replyObject[4][0])); | 
|  | Expect.equals(true, identical(replyObject[0][0], replyObject[0][2])); | 
|  | // Bigint literals are not canonicalized so do a == check. | 
|  | Expect.equals(true, replyObject[0][3] == replyObject[4][4]); | 
|  | }); | 
|  |  | 
|  | // Shutdown the MessageServer. | 
|  | remote.call(-1).then(expectAsync1((int message) { | 
|  | Expect.equals(MessageTest.elms.length + 1, message); | 
|  | })); | 
|  | }); | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | // tests/isolate/request_reply_test.dart | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | void request_reply_entry() { | 
|  | port.receive((message, SendPort replyTo) { | 
|  | replyTo.send(message + 87); | 
|  | port.close(); | 
|  | }); | 
|  | } | 
|  |  | 
|  | void request_reply_main() { | 
|  | test("call", () { | 
|  | SendPort port = spawnFunction(request_reply_entry); | 
|  | port.call(42).then(expectAsync1((message) { | 
|  | Expect.equals(42 + 87, message); | 
|  | })); | 
|  | }); | 
|  |  | 
|  | test("send", () { | 
|  | SendPort port = spawnFunction(request_reply_entry); | 
|  | ReceivePort reply = new ReceivePort(); | 
|  | port.send(99, reply.toSendPort()); | 
|  | reply.receive(expectAsync2((message, replyTo) { | 
|  | Expect.equals(99 + 87, message); | 
|  | reply.close(); | 
|  | })); | 
|  | }); | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | // tests/isolate/count_test.dart | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | void countMessages() { | 
|  | int count = 0; | 
|  | port.receive((int message, SendPort replyTo) { | 
|  | if (message == -1) { | 
|  | Expect.equals(10, count); | 
|  | replyTo.send(-1, null); | 
|  | port.close(); | 
|  | return; | 
|  | } | 
|  | Expect.equals(count, message); | 
|  | count++; | 
|  | replyTo.send(message * 2, null); | 
|  | }); | 
|  | } | 
|  |  | 
|  | void count_main() { | 
|  | test("count 10 consecutive messages", () { | 
|  | int count = 0; | 
|  | SendPort remote = spawnFunction(countMessages); | 
|  | ReceivePort local = new ReceivePort(); | 
|  | SendPort reply = local.toSendPort(); | 
|  |  | 
|  | local.receive(expectAsync2((int message, SendPort replyTo) { | 
|  | if (message == -1) { | 
|  | Expect.equals(11, count); | 
|  | local.close(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | Expect.equals((count - 1) * 2, message); | 
|  | remote.send(count++, reply); | 
|  | if (count == 10) { | 
|  | remote.send(-1, reply); | 
|  | } | 
|  | }, 11)); | 
|  | remote.send(count++, reply); | 
|  | }); | 
|  | } | 
|  |  | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | // tests/isolate/mandel_isolate_test.dart | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | const TERMINATION_MESSAGE = -1; | 
|  | const N = 100; | 
|  | const ISOLATES = 20; | 
|  |  | 
|  | mandel_main() { | 
|  | test("Render Mandelbrot in parallel", () { | 
|  | final state = new MandelbrotState(); | 
|  | state._validated.future.then(expectAsync1((result) { | 
|  | expect(result, isTrue); | 
|  | })); | 
|  | for (int i = 0; i < Math.min(ISOLATES, N); i++) state.startClient(i); | 
|  | }); | 
|  | } | 
|  |  | 
|  |  | 
|  | class MandelbrotState { | 
|  |  | 
|  | MandelbrotState() { | 
|  | _result = new List<List<int>>(N); | 
|  | _lineProcessedBy = new List<LineProcessorClient>(N); | 
|  | _sent = 0; | 
|  | _missing = N; | 
|  | _validated = new Completer<bool>(); | 
|  | } | 
|  |  | 
|  | void startClient(int id) { | 
|  | assert(_sent < N); | 
|  | final client = new LineProcessorClient(this, id); | 
|  | client.processLine(_sent++); | 
|  | } | 
|  |  | 
|  | void notifyProcessedLine(LineProcessorClient client, int y, List<int> line) { | 
|  | assert(_result[y] == null); | 
|  | _result[y] = line; | 
|  | _lineProcessedBy[y] = client; | 
|  |  | 
|  | if (_sent != N) { | 
|  | client.processLine(_sent++); | 
|  | } else { | 
|  | client.shutdown(); | 
|  | } | 
|  |  | 
|  | // If all lines have been computed, validate the result. | 
|  | if (--_missing == 0) { | 
|  | _printResult(); | 
|  | _validateResult(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void _validateResult() { | 
|  | // TODO(ngeoffray): Implement this. | 
|  | _validated.complete(true); | 
|  | } | 
|  |  | 
|  | void _printResult() { | 
|  | var output = new StringBuffer(); | 
|  | for (int i = 0; i < _result.length; i++) { | 
|  | List<int> line = _result[i]; | 
|  | for (int j = 0; j < line.length; j++) { | 
|  | if (line[j] < 10) output.write("0"); | 
|  | output.write(line[j]); | 
|  | } | 
|  | output.write("\n"); | 
|  | } | 
|  | // print(output); | 
|  | } | 
|  |  | 
|  | List<List<int>> _result; | 
|  | List<LineProcessorClient> _lineProcessedBy; | 
|  | int _sent; | 
|  | int _missing; | 
|  | Completer<bool> _validated; | 
|  | } | 
|  |  | 
|  |  | 
|  | class LineProcessorClient { | 
|  |  | 
|  | LineProcessorClient(MandelbrotState this._state, int this._id) { | 
|  | _port = spawnFunction(processLines); | 
|  | } | 
|  |  | 
|  | void processLine(int y) { | 
|  | _port.call(y).then((List<int> message) { | 
|  | _state.notifyProcessedLine(this, y, message); | 
|  | }); | 
|  | } | 
|  |  | 
|  | void shutdown() { | 
|  | _port.send(TERMINATION_MESSAGE, null); | 
|  | } | 
|  |  | 
|  | MandelbrotState _state; | 
|  | int _id; | 
|  | SendPort _port; | 
|  | } | 
|  |  | 
|  | List<int> processLine(int y) { | 
|  | double inverseN = 2.0 / N; | 
|  | double Civ = y * inverseN - 1.0; | 
|  | List<int> result = new List<int>(N); | 
|  | for (int x = 0; x < N; x++) { | 
|  | double Crv = x * inverseN - 1.5; | 
|  |  | 
|  | double Zrv = Crv; | 
|  | double Ziv = Civ; | 
|  |  | 
|  | double Trv = Crv * Crv; | 
|  | double Tiv = Civ * Civ; | 
|  |  | 
|  | int i = 49; | 
|  | do { | 
|  | Ziv = (Zrv * Ziv) + (Zrv * Ziv) + Civ; | 
|  | Zrv = Trv - Tiv + Crv; | 
|  |  | 
|  | Trv = Zrv * Zrv; | 
|  | Tiv = Ziv * Ziv; | 
|  | } while (((Trv + Tiv) <= 4.0) && (--i > 0)); | 
|  |  | 
|  | result[x] = i; | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | void processLines() { | 
|  | port.receive((message, SendPort replyTo) { | 
|  | if (message == TERMINATION_MESSAGE) { | 
|  | assert(replyTo == null); | 
|  | port.close(); | 
|  | } else { | 
|  | replyTo.send(processLine(message), null); | 
|  | } | 
|  | }); | 
|  | } |