diff --git a/benchmark/fib.lua b/benchmark/fib.lua index 576024a7..841d8379 100644 --- a/benchmark/fib.lua +++ b/benchmark/fib.lua @@ -3,4 +3,9 @@ function fib(n) return fib(n - 2) + fib(n - 1) end -io.write(fib(35) .. "\n") +local start = os.clock() +for i = 1, 5 do + io.write(fib(30) .. "\n") +end +local elapsed = os.clock() - start +io.write(string.format("elapsed: %.8f\n", elapsed)) diff --git a/benchmark/fib.py b/benchmark/fib.py index 1ce57cc5..e58ddb06 100644 --- a/benchmark/fib.py +++ b/benchmark/fib.py @@ -1,5 +1,10 @@ +import time + def fib(n): if n < 2: return n return fib(n - 1) + fib(n - 2) -print fib(35) +start = time.clock() +for i in range(0, 5): + print(fib(30)) +print("elapsed: " + str(time.clock() - start)) \ No newline at end of file diff --git a/benchmark/fib.rb b/benchmark/fib.rb new file mode 100644 index 00000000..5f224ea0 --- /dev/null +++ b/benchmark/fib.rb @@ -0,0 +1,13 @@ +def fib(n) + if n < 2 then + n + else + fib(n - 1) + fib(n - 2) + end +end + +start = Time.now +for i in 0...5 + puts fib(30) +end +puts "elapsed: " + (Time.now - start).to_s diff --git a/benchmark/fib.wren b/benchmark/fib.wren index 76973e56..1fef14d9 100644 --- a/benchmark/fib.wren +++ b/benchmark/fib.wren @@ -6,4 +6,10 @@ var fib = fn(n) { } } -io.write(fib.call(35)) +var start = OS.clock +var i = 0 +while (i < 5) { + io.write(fib.call(30)) + i = i + 1 +} +io.write("elapsed: " + (OS.clock - start).toString) diff --git a/benchmark/run_all b/benchmark/run_all new file mode 100755 index 00000000..6a6164c3 --- /dev/null +++ b/benchmark/run_all @@ -0,0 +1,65 @@ +#!/usr/bin/python + +import math +import re +import subprocess +import sys + +FIB_OUTPUT_PATTERN = re.compile(r"""832040 +832040 +832040 +832040 +832040 +elapsed: (\d+\.\d+)""", re.MULTILINE) + +BENCHMARKS = [ + ("fib", FIB_OUTPUT_PATTERN) +] + +LANGUAGES = [ + ("wren", "../build/Release/wren", ".wren"), + ("lua", "lua", ".lua"), + ("python", "python", ".py"), + ("ruby", "ruby", ".rb") +] + +def calc_stats(nums): + """Calculates the mean, median, and std deviation of a list of numbers.""" + mean = sum(nums) / len(nums) + nums.sort() + median = nums[(len(nums) - 1) / 2] + diffs = ((n - mean) * (n - mean) for n in nums) + std_dev = math.sqrt(sum(diffs) / len(nums)) + return [mean, median, std_dev] + + +def run_benchmark_once(benchmark, language): + args = [language[1], benchmark[0] + language[2]] + out = subprocess.check_output(args, universal_newlines=True) + match = benchmark[1].match(out) + if match: + return float(match.group(1)) + else: + return None + + +def run_benchmark(benchmark, language): + print "{0} - {1:10s}".format(benchmark[0], language[0]), + + times = [] + for i in range(0, 7): + times.append(run_benchmark_once(benchmark, language)) + 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( + stats[0], stats[1], stats[2]) + +for benchmark in BENCHMARKS: + for language in LANGUAGES: + run_benchmark(benchmark, language) diff --git a/src/primitives.c b/src/primitives.c index 03c2e7a0..2ea6204d 100644 --- a/src/primitives.c +++ b/src/primitives.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "compiler.h" #include "primitives.h" @@ -93,7 +94,7 @@ DEF_PRIMITIVE(num_toString) { // TODO(bob): What size should this be? char temp[100]; - sprintf(temp, "%g", AS_NUM(args[0])); + sprintf(temp, "%.14g", AS_NUM(args[0])); return (Value)newString(vm, temp, strlen(temp)); } @@ -235,6 +236,12 @@ DEF_PRIMITIVE(io_write) return args[1]; } +DEF_PRIMITIVE(os_clock) +{ + double time = (double)clock() / CLOCKS_PER_SEC; + return NUM_VAL(time); +} + static const char* CORE_LIB = "class Object {}\n" "class Bool {}\n" @@ -244,7 +251,8 @@ static const char* CORE_LIB = "class Null {}\n" "class String {}\n" "class IO {}\n" -"var io = IO.new\n"; +"var io = IO.new\n" +"class OS {}\n"; void loadCore(VM* vm) { @@ -301,6 +309,9 @@ void loadCore(VM* vm) ObjClass* ioClass = AS_CLASS(findGlobal(vm, "IO")); PRIMITIVE(ioClass, "write ", io_write); + ObjClass* osClass = AS_CLASS(findGlobal(vm, "OS")); + PRIMITIVE(osClass->metaclass, "clock", os_clock); + ObjClass* unsupportedClass = newClass(vm, vm->objectClass); // TODO(bob): Make this a distinct object type. diff --git a/src/vm.c b/src/vm.c index 511139b2..fcbffd83 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1031,7 +1031,7 @@ void printValue(Value value) #ifdef NAN_TAGGING if (IS_NUM(value)) { - printf("%g", AS_NUM(value)); + printf("%.14g", AS_NUM(value)); } else if (IS_OBJ(value)) { @@ -1059,7 +1059,7 @@ void printValue(Value value) { case VAL_FALSE: printf("false"); break; case VAL_NULL: printf("null"); break; - case VAL_NUM: printf("%g", AS_NUM(value)); break; + case VAL_NUM: printf("%.14g", AS_NUM(value)); break; case VAL_TRUE: printf("true"); break; case VAL_OBJ: switch (value.obj->type)