From edb9032052283724838ea68717f8704eb433b131 Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Fri, 29 Nov 2013 16:19:13 -0800 Subject: [PATCH] Get binary_trees benchmark working. Wren is actually doing well in it: wren mean: 1.9441 median: 1.9428 std_dev: 0.0260 lua mean: 3.5992 median: 3.6033 std_dev: 0.0156 python mean: 3.6667 median: 3.7097 std_dev: 0.1340 ruby mean: 1.3941 median: 1.3914 std_dev: 0.0091 --- benchmark/binary_trees.lua | 54 +++++++++++++++++++++++++++++++++ benchmark/binary_trees.py | 40 +++++++++++++++++++++++++ benchmark/binary_trees.rb | 51 +++++++++++++++++++++++++++++++ benchmark/binary_trees.wren | 60 +++++++++++++++++++++++++++++++++++++ benchmark/run_all | 49 ++++++++++++++++++++---------- src/wren_compiler.c | 3 +- 6 files changed, 240 insertions(+), 17 deletions(-) create mode 100644 benchmark/binary_trees.lua create mode 100644 benchmark/binary_trees.py create mode 100644 benchmark/binary_trees.rb create mode 100644 benchmark/binary_trees.wren diff --git a/benchmark/binary_trees.lua b/benchmark/binary_trees.lua new file mode 100644 index 00000000..2e948ddd --- /dev/null +++ b/benchmark/binary_trees.lua @@ -0,0 +1,54 @@ +-- The Computer Language Benchmarks Game +-- http://shootout.alioth.debian.org/ +-- contributed by Mike Pall + +local function BottomUpTree(item, depth) + if depth > 0 then + local i = item + item + depth = depth - 1 + local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth) + return { item, left, right } + else + return { item } + end +end + +local function ItemCheck(tree) + if tree[2] then + return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3]) + else + return tree[1] + end +end + +local N = 14 +local mindepth = 4 +local maxdepth = mindepth + 2 +if maxdepth < N then maxdepth = N end + +local start = os.clock() + +do + local stretchdepth = maxdepth + 1 + local stretchtree = BottomUpTree(0, stretchdepth) + io.write(string.format("stretch tree of depth %d\t check: %d\n", + stretchdepth, ItemCheck(stretchtree))) +end + +local longlivedtree = BottomUpTree(0, maxdepth) + +for depth=mindepth,maxdepth,2 do + local iterations = 2 ^ (maxdepth - depth + mindepth) + local check = 0 + for i=1,iterations do + check = check + ItemCheck(BottomUpTree(1, depth)) + + ItemCheck(BottomUpTree(-1, depth)) + end + io.write(string.format("%d\t trees of depth %d\t check: %d\n", + iterations*2, depth, check)) +end + +io.write(string.format("long lived tree of depth %d\t check: %d\n", + maxdepth, ItemCheck(longlivedtree))) + +io.write(string.format("elapsed: %.8f\n", os.clock() - start)) diff --git a/benchmark/binary_trees.py b/benchmark/binary_trees.py new file mode 100644 index 00000000..556278cc --- /dev/null +++ b/benchmark/binary_trees.py @@ -0,0 +1,40 @@ +# The Computer Language Benchmarks Game +# http://shootout.alioth.debian.org/ +# +# contributed by Antoine Pitrou +# modified by Dominique Wahli +# modified by Heinrich Acker + +import time + +def make_tree(item, depth): + if not depth: return item, None, None + item2 = item + item + depth -= 1 + return item, make_tree(item2 - 1, depth), make_tree(item2, depth) + +def check_tree((item, left, right)): + if not left: return item + return item + check_tree(left) - check_tree(right) + +min_depth = 4 +max_depth = max(min_depth + 2, 14) +stretch_depth = max_depth + 1 + +start = time.clock() +print "stretch tree of depth %d\t check:" % stretch_depth, check_tree(make_tree(0, stretch_depth)) + +long_lived_tree = make_tree(0, max_depth) + +iterations = 2**max_depth +for depth in xrange(min_depth, stretch_depth, 2): + + check = 0 + for i in xrange(1, iterations + 1): + check += check_tree(make_tree(i, depth)) + check_tree(make_tree(-i, depth)) + + print "%d\t trees of depth %d\t check:" % (iterations * 2, depth), check + iterations /= 4 + +print "long lived tree of depth %d\t check:" % max_depth, check_tree(long_lived_tree) +print("elapsed: " + str(time.clock() - start)) \ No newline at end of file diff --git a/benchmark/binary_trees.rb b/benchmark/binary_trees.rb new file mode 100644 index 00000000..e6e41bb3 --- /dev/null +++ b/benchmark/binary_trees.rb @@ -0,0 +1,51 @@ +# The Computer Language Shootout Benchmarks +# http://shootout.alioth.debian.org +# +# contributed by Jesse Millikan +# Modified by Wesley Moxam + + +def item_check(left, item, right) + return item if left.nil? + item + item_check(*left) - item_check(*right) +end + +def bottom_up_tree(item, depth) + return [nil, item, nil] unless depth > 0 + item_item = 2 * item + depth -= 1 + [bottom_up_tree(item_item - 1, depth), item, bottom_up_tree(item_item, depth)] +end + +max_depth = 14 +min_depth = 4 + +max_depth = min_depth + 2 if min_depth + 2 > max_depth + +stretch_depth = max_depth + 1 +stretch_tree = bottom_up_tree(0, stretch_depth) + +start = Time.now +puts "stretch tree of depth #{stretch_depth}\t check: #{item_check(*stretch_tree)}" +stretch_tree = nil + +long_lived_tree = bottom_up_tree(0, max_depth) + +min_depth.step(max_depth + 1, 2) do |depth| + iterations = 2**(max_depth - depth + min_depth) + + check = 0 + + for i in 1..iterations + temp_tree = bottom_up_tree(i, depth) + check += item_check(*temp_tree) + + temp_tree = bottom_up_tree(-i, depth) + check += item_check(*temp_tree) + end + + puts "#{iterations * 2}\t trees of depth #{depth}\t check: #{check}" +end + +puts "long lived tree of depth #{max_depth}\t check: #{item_check(*long_lived_tree)}" +puts "elapsed: " + (Time.now - start).to_s diff --git a/benchmark/binary_trees.wren b/benchmark/binary_trees.wren new file mode 100644 index 00000000..67cf4cb9 --- /dev/null +++ b/benchmark/binary_trees.wren @@ -0,0 +1,60 @@ +// Ported from the Python version. + +class Tree { + this new(item, depth) { + _item = item + if (depth > 0) { + var item2 = item + item + depth = depth - 1 + _left = Tree.new(item2 - 1, depth) + _right = Tree.new(item2, depth) + } + } + + check { + if (_left == null) { + _item + } else { + _item + _left.check - _right.check + } + } +} + +var minDepth = 4 +var maxDepth = 14 +var stretchDepth = maxDepth + 1 + +var start = OS.clock + +io.write("stretch tree of depth " + stretchDepth.toString + "\t check: " + + Tree.new(0, stretchDepth).check.toString) + +var longLivedTree = Tree.new(0, maxDepth) + +// iterations = 2 ** maxDepth +var iterations = 1 +var d = 0 +while (d < maxDepth) { + iterations = iterations * 2 + d = d + 1 +} + +var depth = minDepth +while (depth < stretchDepth) { + var check = 0 + var i = 1 + while (i < iterations + 1) { + check = check + Tree.new(i, depth).check + Tree.new(-i, depth).check + i = i + 1 + } + + io.write((iterations * 2).toString + "\t trees of depth " + depth.toString + + "\t check: " + check.toString) + iterations = iterations / 4 + depth = depth + 2 +} + +io.write("long lived tree of depth " + maxDepth.toString + "\t check: " + + longLivedTree.check.toString) + +io.write("elapsed: " + (OS.clock - start).toString) diff --git a/benchmark/run_all b/benchmark/run_all index 625be503..ad0cf77b 100755 --- a/benchmark/run_all +++ b/benchmark/run_all @@ -1,20 +1,32 @@ #!/usr/bin/python import math +import os import re import subprocess import sys -FIB_OUTPUT_PATTERN = re.compile(r"""832040 -832040 -832040 -832040 -832040 -elapsed: (\d+\.\d+)""", re.MULTILINE) +BENCHMARKS = [] -BENCHMARKS = [ - ("fib", FIB_OUTPUT_PATTERN) -] +def BENCHMARK(name, pattern): + BENCHMARKS.append((name, re.compile(pattern, re.MULTILINE))) + +BENCHMARK("binary_trees", """stretch tree of depth 15\t check: -1 +32768\t trees of depth 4\t check: -32768 +8192\t trees of depth 6\t check: -8192 +2048\t trees of depth 8\t check: -2048 +512\t trees of depth 10\t check: -512 +128\t trees of depth 12\t check: -128 +32\t trees of depth 14\t check: -32 +long lived tree of depth 14\t check: -1 +elapsed: (\\d+\\.\\d+)""") + +BENCHMARK("fib", r"""832040 +832040 +832040 +832040 +832040 +elapsed: (\d+\.\d+)""") LANGUAGES = [ ("wren", "../build/Release/wren", ".wren"), @@ -47,21 +59,26 @@ def run_benchmark_once(benchmark, language): if match: return float(match.group(1)) else: + print "Incorrect output:" + print out return None def run_benchmark(benchmark, language): print "{0} - {1:10s}".format(benchmark[0], language[0]), + if not os.path.exists(benchmark[0] + language[2]): + print "No implementation for this language" + return + times = [] for i in range(0, NUM_TRIALS): - times.append(run_benchmark_once(benchmark, language)) + time = run_benchmark_once(benchmark, language) + if not time: + return + times.append(time) sys.stdout.write(".") - if None in times: - print "error" - return - times.sort() stats = calc_stats(times) print " mean: {0:.4f} median: {1:.4f} std_dev: {2:.4f}".format( @@ -78,12 +95,12 @@ def graph_results(): time = max(result[1]) if time > highest: highest = time - print "{0:15s} 0.0 {1:76.4f}".format("", highest) + print "{0:24s} 0.0 {1:76.4f}".format("", highest) for result in results: line = ["-"] * 80 for time in result[1]: line[int(time / highest * 79)] = "O" - print "{0:15s} {1}".format(result[0], "".join(line)) + print "{0:24s} {1}".format(result[0], "".join(line)) for benchmark in BENCHMARKS: for language in LANGUAGES: diff --git a/src/wren_compiler.c b/src/wren_compiler.c index ce387393..aa23d545 100644 --- a/src/wren_compiler.c +++ b/src/wren_compiler.c @@ -401,12 +401,13 @@ static void readString(Parser* parser) case '"': addStringChar(parser, '"'); break; case '\\': addStringChar(parser, '\\'); break; case 'n': addStringChar(parser, '\n'); break; + case 't': addStringChar(parser, '\t'); break; default: // TODO(bob): Emit error token. break; } - // TODO(bob): Other escapes (/t, /r, etc.), Unicode escape sequences. + // TODO(bob): Other escapes (\r, etc.), Unicode escape sequences. } else {