From 05f00da31fefd3942298648b332627c2004dfdf8 Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Wed, 6 Feb 2019 17:55:40 -0800 Subject: [PATCH] Start working on a benchmark for the spread desugaring. I'm not entirely sure if this measures what we want it to, but I wanted to get something started. --- .../spread-collections/benchmarks/.gitignore | 1 + .../spread-collections/benchmarks/Makefile | 34 +++++ .../benchmarks/bin/profile_list_spread.dart | 135 ++++++++++++++++++ .../benchmarks/pubspec.yaml | 1 + 4 files changed, 171 insertions(+) create mode 100644 accepted/future-releases/spread-collections/benchmarks/.gitignore create mode 100644 accepted/future-releases/spread-collections/benchmarks/Makefile create mode 100644 accepted/future-releases/spread-collections/benchmarks/bin/profile_list_spread.dart create mode 100644 accepted/future-releases/spread-collections/benchmarks/pubspec.yaml diff --git a/accepted/future-releases/spread-collections/benchmarks/.gitignore b/accepted/future-releases/spread-collections/benchmarks/.gitignore new file mode 100644 index 0000000000..e2e7327cde --- /dev/null +++ b/accepted/future-releases/spread-collections/benchmarks/.gitignore @@ -0,0 +1 @@ +/out diff --git a/accepted/future-releases/spread-collections/benchmarks/Makefile b/accepted/future-releases/spread-collections/benchmarks/Makefile new file mode 100644 index 0000000000..e548ecad50 --- /dev/null +++ b/accepted/future-releases/spread-collections/benchmarks/Makefile @@ -0,0 +1,34 @@ +# Runs the benchmarks on a few platforms. + +# Note: this assumes: +# +# - The language repo's root directory is adjacent to the root directory of the +# Dart SDK repo, which is named "dart". +# +# - "node" is on your PATH. +# +# - You have built the AoT runtime by running this from the SDK root directory: +# +# tools/build.py -m release runtime dart_precompiled_runtime + +SDK := "../../../../../dart/sdk" + +all: jit dart2js aot + +aot: + @ echo "AoT" + @ mkdir -p out + @ $(SDK)/pkg/vm/tool/precompiler2 bin/profile_list_spread.dart out/profile_list_spread.snapshot + @ $(SDK)/pkg/vm/tool/dart_precompiled_runtime2 out/profile_list_spread.snapshot + +dart2js: + @ echo "dart2js" + @ mkdir -p out + @ $(SDK)/sdk/bin/dart2js bin/profile_list_spread.dart -o out/profile_list_spread.js + @ node out/profile_list_spread.js + +jit: + @ echo "VM JIT" + @ $(SDK)/sdk/bin/dart bin/profile_list_spread.dart + +.PHONY: all aot dart2js jit diff --git a/accepted/future-releases/spread-collections/benchmarks/bin/profile_list_spread.dart b/accepted/future-releases/spread-collections/benchmarks/bin/profile_list_spread.dart new file mode 100644 index 0000000000..b79bfa251e --- /dev/null +++ b/accepted/future-releases/spread-collections/benchmarks/bin/profile_list_spread.dart @@ -0,0 +1,135 @@ +import 'dart:collection'; + +const trialMs = 100; +const lengths = [0, 1, 2, 5, 10, 20, 50, 100, 1000]; + +var csv = StringBuffer(); + +class CustomList extends ListBase { + final List _inner; + + int get length => _inner.length; + + set length(int value) => _inner.length = value; + + CustomList(this._inner); + + T operator [](int index) => _inner[index]; + + void operator []=(int index, T value) => _inner[index] = value; +} + +void main() { + for (var length in lengths) { + var baseline = runBench("iterate", length, iterate); + runBench("List for", length, addList, baseline); + runBench("resize and set", length, resizeAndSet, baseline); + runBench("addAll()", length, addAll, baseline); + runBench("forEach()", length, forEach, baseline); + print(""); + } + +// print(""); +// print(csv); +} + +double runBench( + String name, int length, void Function(List, List) action, + [double baseline]) { + var from = []; + for (var i = 0; i < length; i++) { + from.add(String.fromCharCode(i % 26 + 65)); + } + + var froms = [from, CustomList(from)]; + + var rate = benchBest(froms, action); + + if (baseline == null) { + print("${length.toString().padLeft(4)} ${name.padRight(15)} " + "${rate.toStringAsFixed(2).padLeft(10)} spreads/ms " + " ${'-' * 20}"); + } else { + var comparison = rate / baseline; + var bar = "=" * (comparison * 20).toInt(); + if (comparison > 4.0) bar = "!!!"; + print("${length.toString().padLeft(4)} ${name.padRight(15)} " + "${rate.toStringAsFixed(2).padLeft(10)} spreads/ms " + "${comparison.toStringAsFixed(2).padLeft(6)}x baseline $bar"); + } + + csv.writeln("$length,$name,$rate"); + return rate; +} + +/// Runs [bench] a number of times and returns the best (highest) result. +double benchBest( + List> froms, void Function(List, List) action) { + var best = 0.0; + for (var i = 0; i < 4; i++) { + var result = bench(froms, action); + if (result > best) best = result; + } + + return best; +} + +/// Spreads each list in [froms] into the middle of a list using [action]. +/// +/// Returns the number of times it was able to do this per millisecond, on +/// average. Higher is better. +double bench(List> froms, + void Function(List, List) action) { + var elapsed = 0; + var count = 0; + var watch = Stopwatch()..start(); + do { + for (var i = 0; i < froms.length; i++) { + var from = froms[i]; + var to = ["a", "b"]; + + action(from, to); + to.add("b"); + to.add("c"); + + count++; + } + elapsed = watch.elapsedMilliseconds; + } while (elapsed < trialMs); + + return count / elapsed; +} + +void iterate(List from, List to) { + for (var e in from) { + to.add(e); + } +} + +void addList(List from, List to) { + var length = from.length; + for (var i = 0; i < length; i++) { + to.add(from[i]); + } +} + +void resizeAndSet(List from, List to) { + var length = from.length; + var j = to.length; + to.length = to.length + length; + for (var i = 0; i < length; i++) { + to[j] = from[i]; + } +} + +void addAll(List from, List to) { + to.addAll(from); +} + +void forEach(List from, List to) { + var temp = to; + from.forEach((s) { + temp.add(s); + }); + temp = null; +} diff --git a/accepted/future-releases/spread-collections/benchmarks/pubspec.yaml b/accepted/future-releases/spread-collections/benchmarks/pubspec.yaml new file mode 100644 index 0000000000..7d1c5d928e --- /dev/null +++ b/accepted/future-releases/spread-collections/benchmarks/pubspec.yaml @@ -0,0 +1 @@ +name: benchmarks