]> Nishi Git Mirror - gwion.git/commitdiff
:book: Benchmarks
authorfennecdjay <astor.jeremie@wanadoo.fr>
Fri, 28 Jun 2019 10:14:05 +0000 (12:14 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Fri, 28 Jun 2019 10:14:05 +0000 (12:14 +0200)
20 files changed:
.gitignore
docs.mk
docs/01_Overview/declaration.mdr
docs/Benchmarks.mdr [new file with mode: 0644]
docs/Extending/WIP_Driver.mdr [moved from docs/WIP_Driver.mdr with 100% similarity]
docs/Extending/WIP_Plugins.mdr [moved from docs/WIP_Plugins.mdr with 100% similarity]
docs/Functions/function.mdr
docs/Make.mdr
docs/assets/benchmark/binary_trees.dat [new file with mode: 0644]
docs/assets/benchmark/binary_trees.png [new file with mode: 0644]
docs/assets/doc.css [new file with mode: 0644]
help/benchmark.sh [deleted file]
help/doc-config.sh
tests/benchmark/binary_trees.dart [new file with mode: 0644]
tests/benchmark/binary_trees.gw [new file with mode: 0644]
tests/benchmark/binary_trees.lua [new file with mode: 0644]
tests/benchmark/binary_trees.py [new file with mode: 0644]
tests/benchmark/binary_trees.rb [new file with mode: 0644]
tests/benchmark/binary_trees.wren [new file with mode: 0644]
tests/benchmark/binary_trees_gc.wren [new file with mode: 0644]

index 3b548b3ccbc12bf38d13c4a3672be34df2b63381..d741608c96073a7c5832ab84e685abaaf3123e27 100644 (file)
@@ -3,3 +3,5 @@ gwion
 config.mk
 include/generated.h
 .desk
+mkdocs.yml
+*.a
diff --git a/docs.mk b/docs.mk
index b767302d1c80e0169b137871f4eaa84bbdc05c9d..af87eff9b523d39176b75fd2a778e011ab387629 100644 (file)
--- a/docs.mk
+++ b/docs.mk
@@ -42,18 +42,18 @@ doc-deploy: $(md_list)
 
 .SUFFIXES: .gw .test
 .gw.test:
-       @${VALGRIND} ${VALGRIND_OPT} gwion $< &> log
+       @${VALGRIND} ${VALGRIND_OPT} gwion $< 2>&1 > log
        @[ -t 1 ] && $(call _interm) || $(call _noterm)
 
 define _test_check
        for a in $(CONTAINS); do grep "$$a" log >/dev/null; done && valgrind_parse vlog
 endef
 
-_interm_status=echo -e "$(INTERM_OK)" || echo -e "$(INTERM_NOT_OK)"
+_interm_status=printf "$(INTERM_OK)\n" || printf "$(INTERM_NOT_OK)\n"
 _interm=(cat log; $(call _test_check) && $(call _interm_status))
 
 _noterm_log=sed 's/$$/\<br\/>/' log
-_noterm_status=echo -e "$(NOTERM_OK)" || echo -e "$(NOTERM_NOT_OK)"
+_noterm_status=printf "$(NOTERM_OK)\n" || printf "$(NOTERM_NOT_OK)\n"
 _noterm_test=$(call _test_check) && $(call _noterm_status)
 _noterm_header=echo '<p style=$(CSS)>'
 _noterm_footer=echo '</p>'
index e359c6a3f7be8a3d62fbd35a7e5b2f8ac58345f4..9afb021cc5d601ae6b71f1d811d8407443a4ea6f 100644 (file)
@@ -19,15 +19,16 @@ Object @ref;
 new Object @=> ref;
 <<<"But now it does: ", ref>>>;
 @```
-@exec gwion decl1.gw 2>&1
+@exec make decl1.test
 
 ## Arrays
 
 ### array as refs
+
 @``` decl2.gw
 int ref[];
 <<<ref>>>;
 new int[2] @=> ref;
 <<<ref>>>;
 @```
-@exec gwion decl2.gw 2>&1
+@exec make decl2.test
diff --git a/docs/Benchmarks.mdr b/docs/Benchmarks.mdr
new file mode 100644 (file)
index 0000000..ef68474
--- /dev/null
@@ -0,0 +1,86 @@
+# Benchmarks
+
+We'll need a bash script
+
+<link rel=styleSheet href="../assets/doc.css" TYPE="text/css"><div id="org-categories"><ul class="lev1"><li><a href="#">Show the code</a></li><ul class="lev2"><a href="#">
+@``` benchmark.sh
+#!/bin/sh
+language=("gwion" "wren" "lua5.3")
+extension=("gw" "wren" "lua")
+test_dir="tests/benchmark"
+plot_script="bench.plot"
+: "${repeats:=10}"
+
+run() {
+  perf stat -r"$repeats" "$1" "$test_dir/$3.$2" 2>&1 | grep "time elapsed" |
+    sed 's/ *\([0-9]*\),\([0-9]*\) seconds time elapsed *( +- *\([0-9]*\),\([0-9]*\)% )/\1.\2 \3.\4/'
+}
+
+get_list() {
+  for file in $test_dir/*.gw
+  do basename "$file" .gw
+  done
+}
+
+get_test() {
+  for (( i=0; i<=$(( ${#language[@]} -1 )); i++ ))
+  do echo "${language[$i]} $(run "${language[$i]}" "${extension[$i]}" "$1")"
+  done > "docs/assets/benchmark/$1.dat"
+}
+
+plot() {
+  gnuplot -e "bench='$1'" "$plot_script"
+}
+
+for bench in $(get_list)
+do
+echo $bench
+  get_test "$bench"
+  plot "$bench"
+  echo "### $bench"
+  echo '<link rel=styleSheet href="../assets/doc.css" TYPE="text/css"><div id="org-categories"><ul class="lev1"><li><a href="#">Show the code</a></li><ul class="lev2"><a href="#">'
+  echo "\`\`\`"
+  cat "$test_dir/$bench.gw"
+  echo "\`\`\`"
+  echo '</a></a></li></ul></ul></div>'
+  echo "![](assets/benchmark/$bench.png)"
+done
+@```  
+</a></a></li></ul></ul></div>
+
+### and a gnuplot script
+
+<link rel=styleSheet href="../assets/doc.css" TYPE="text/css"><div id="org-categories"><ul class="lev1"><li><a href="#">Show the code</a></li><ul class="lev2"><a href="#">
+@``` bench.plot
+set terminal png truecolor
+
+#if (!exists("bench"))
+#  bench = 'bench'
+if (!exists("test_dir"))
+  test_dir = 'tests/benchmark'
+
+dat_name = sprintf("docs/assets/benchmark/%s.dat", bench)
+
+stats dat_name using 0:2 noout
+max = ceil(STATS_max_y+2)
+
+#set title bench
+set output sprintf("docs/assets/benchmark/%s.png", bench)
+set xrange [-0.5:((ceil(STATS_max_x))+0.5)]
+set yrange [0:max]
+set boxwidth 0.50
+set nokey
+set xtics nomirror
+set ytics nomirror
+
+set style fill transparent solid 0.25 # partial transparency
+set style fill noborder # no separate top/bottom lines
+
+plot dat_name using 0:2:($3/100.):xtic(2) with boxerrorbar lc "blue" notitle, \
+  '' using 0:(max-0.5):1 with labels
+@```  
+</a></a></li></ul></ul></div>
+
+## Show the results
+Then just run it
+@exec bash benchmark.sh; rm bench.plot benchmark.sh
index 5a656e45430aa94ae4333c7a15fe197b01227362..f92a174fc7b6b34aec9c3f7b2a222e7539c8a121 100644 (file)
@@ -1,7 +1,8 @@
 # Functions
 
 ## a simple (commented example)
-@```function0.gw
+
+@``` function0.gw
 // declare function 'test_function'
 // with return type int
 // taking an int as argument
index 56000b97ba3f08fc69cf4c72a11893f078abca8b..45a5452da4739df957b99ae3d16b832a59efc832 100644 (file)
@@ -1,4 +1,4 @@
-# Gwion's Makefile
+# Makefile
 
 ## Basic operations
 
diff --git a/docs/assets/benchmark/binary_trees.dat b/docs/assets/benchmark/binary_trees.dat
new file mode 100644 (file)
index 0000000..a8dc8e8
--- /dev/null
@@ -0,0 +1,3 @@
+gwion 0.244813625 0.33
+wren 0.358684268 1.43
+lua5.3 0.621848489 5.69
diff --git a/docs/assets/benchmark/binary_trees.png b/docs/assets/benchmark/binary_trees.png
new file mode 100644 (file)
index 0000000..ea48d1c
Binary files /dev/null and b/docs/assets/benchmark/binary_trees.png differ
diff --git a/docs/assets/doc.css b/docs/assets/doc.css
new file mode 100644 (file)
index 0000000..692967e
--- /dev/null
@@ -0,0 +1,7 @@
+li + .lev2 {
+  display: none;
+}
+
+li:focus-within + .lev2 {
+  display: block;
+}
diff --git a/help/benchmark.sh b/help/benchmark.sh
deleted file mode 100644 (file)
index 80bc779..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-#run benchmarks and make plots
-: "${repeats:=10}"
-
-fib_test() {
-#  echo "\"$1\"" "$(perf stat -r"$repeats" "$1" "fib_recurs.$2" 2>&1 | grep "time elapsed" | cut -d s -f 1 | sed 's/+-//' | sed 's/,/./g')"
-  printf "$(perf stat -r"$repeats" "$1" "fib_recurs.$2" 2>&1 | grep "time elapsed" | cut -d s -f 1 | sed 's/+-//' | sed 's/,/./g')"
-}
-
-cd ~/fib_recurs/ || exit 1
-printf "\"fib recurs\" "
-fib_test gwion gw
-fib_test lua   lua
-fib_test wren  wren
-#fib_test chuck ck
-#fib_test ruby  rb
-#fib_test perl  pl
-#fib_test python2 py
-#fib_test python3 py
-#fib_test runhaskell hs
index 4fccb6af28383a1dd62841ab739af2e7de36563c..6f197cec22dfdd3f8ac9936a6931ff98bdb1c29d 100644 (file)
@@ -1,15 +1,17 @@
 title() {
   TMP=$(head -n 1 $1)
-  echo ${TMP:2}
+  sed "s/'/\'/" <<< "${TMP:2}"
 }
 
 list_dir() {
+  [[ "$1" == */"assets" ]] && return
   for a in $1/*
   do
-   if [ -d "$a" ]
-   then echo "$2- '$(basename $a | sed 's/[0-9][0-9]_//' | sed 's/_/ /g' | sed 's/-/ /g')':"; list_dir $a "$2  "
-   else echo "$a" | grep "\.md$" >/dev/null  && echo "$2- $(title $a): ${a:5}"
-               fi
+    if [ -d "$a" ]
+    then [[ "$a" == */"assets" ]] ||
+         echo "$2- '$(basename $a | sed 's/[0-9][0-9]_//' | sed 's/_/ /g' | sed 's/-/ /g')':"; list_dir "$a" "$2  "
+    else echo "$a" | grep "\.md$" >/dev/null  && echo "$2- '$(title $a)': ${a:5}"
+    fi
   done
 }
 
diff --git a/tests/benchmark/binary_trees.dart b/tests/benchmark/binary_trees.dart
new file mode 100644 (file)
index 0000000..f7d52d5
--- /dev/null
@@ -0,0 +1,56 @@
+// Ported from the Wren version.
+
+class Tree {
+  var _item;
+  var _left;
+  var _right;
+
+  Tree(item, depth) {
+    _item = item;
+    if (depth > 0) {
+      var item2 = item + item;
+      depth--;
+      _left = new Tree(item2 - 1, depth);
+      _right = new Tree(item2, depth);
+    }
+  }
+
+  get check {
+    if (_left == null) {
+      return _item;
+    }
+
+    return _item + _left.check - _right.check;
+  }
+}
+
+main() {
+  var minDepth = 4;
+  var maxDepth = 12;
+  var stretchDepth = maxDepth + 1;
+
+  print("stretch tree of depth ${stretchDepth} check: "
+      "${new Tree(0, stretchDepth).check}");
+
+  var longLivedTree = new Tree(0, maxDepth);
+
+  // iterations = 2 ** maxDepth
+  var iterations = 1;
+  for (var d = 0; d < maxDepth; d++) {
+    iterations = iterations * 2;
+  }
+
+  var depth = minDepth;
+  while (depth < stretchDepth) {
+    var check = 0;
+    for (var i = 1; i <= iterations; i++) {
+      check += new Tree(i, depth).check + new Tree(-i, depth).check;
+    }
+
+    print("${iterations * 2} trees of depth ${depth} check: ${check}");
+    iterations ~/= 4;
+    depth += 2;
+  }
+
+  print("long lived tree of depth ${maxDepth} check: ${longLivedTree.check}");
+}
diff --git a/tests/benchmark/binary_trees.gw b/tests/benchmark/binary_trees.gw
new file mode 100644 (file)
index 0000000..7d8c8e3
--- /dev/null
@@ -0,0 +1,51 @@
+// Ported from the Wren version.
+
+class Tree {
+  int item;
+  Tree @left, right;
+
+  fun static Tree new_Tree(int it, int depth) {
+    Tree t;
+    it => t.item;
+    if (depth > 0) {
+      it + it => int item2;
+      --depth;
+      Tree.new_Tree(item2 - 1, depth) @=> t.left;
+      Tree.new_Tree(item2, depth) @=> t.right;
+    }
+    return t;
+  }
+
+  fun int check() {
+    if (!left)
+      return item;
+    return item + left.check() - right.check();
+  }
+}
+
+4 => int minDepth;
+12 => int maxDepth;
+maxDepth + 1 => int stretchDepth;
+
+<<<"stretch tree of depth ", stretchDepth, " check: ",
+  Tree.new_Tree(0, stretchDepth).check()>>>;
+
+Tree.new_Tree(0, maxDepth) @=> Tree@ longLivedTree;
+
+// iterations = 2 ** maxDepth
+1 => int iterations;
+for (int d; d < maxDepth; ++d)
+  2 *=> iterations;
+
+minDepth => int depth;
+while (depth < stretchDepth) {
+  int check;
+  for (int i; i < iterations; ++i)
+    Tree.new_Tree(i, depth).check() + Tree.new_Tree(-i, depth).check() +=> check;
+
+  <<<iterations * 2, " trees of depth ", depth, " check: ", check>>>;
+  4 /=> iterations;
+  2 +=> depth;
+}
+
+<<<"long lived tree of depth ", maxDepth, " check: ", longLivedTree.check()>>>;
diff --git a/tests/benchmark/binary_trees.lua b/tests/benchmark/binary_trees.lua
new file mode 100644 (file)
index 0000000..e690c27
--- /dev/null
@@ -0,0 +1,50 @@
+-- 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 = 12
+local mindepth = 4
+local maxdepth = mindepth + 2
+if maxdepth < N then maxdepth = N end
+
+do
+  local stretchdepth = maxdepth + 1
+  local stretchtree = BottomUpTree(0, stretchdepth)
+  io.write(string.format("stretch tree of depth %d 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 trees of depth %d check: %d\n",
+    iterations*2, depth, check))
+end
+
+io.write(string.format("long lived tree of depth %d check: %d\n",
+  maxdepth, ItemCheck(longlivedtree)))
diff --git a/tests/benchmark/binary_trees.py b/tests/benchmark/binary_trees.py
new file mode 100644 (file)
index 0000000..eb3a9b9
--- /dev/null
@@ -0,0 +1,46 @@
+# The Computer Language Benchmarks Game
+# http://shootout.alioth.debian.org/
+#
+# contributed by Antoine Pitrou
+# modified by Dominique Wahli
+# modified by Heinrich Acker
+from __future__ import print_function
+
+import time
+
+# Map "range" to an efficient range in both Python 2 and 3.
+try:
+    range = xrange
+except NameError:
+    pass
+
+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(node):
+    item, left, right = node
+    if not left: return item
+    return item + check_tree(left) - check_tree(right)
+
+min_depth = 4
+max_depth = 12
+stretch_depth = max_depth + 1
+
+print("stretch tree of depth %d 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 range(min_depth, stretch_depth, 2):
+
+    check = 0
+    for i in range(1, iterations + 1):
+        check += check_tree(make_tree(i, depth)) + check_tree(make_tree(-i, depth))
+
+    print("%d trees of depth %d check:" % (iterations * 2, depth), check)
+    iterations //= 4
+
+print("long lived tree of depth %d check:" % max_depth, check_tree(long_lived_tree))
diff --git a/tests/benchmark/binary_trees.rb b/tests/benchmark/binary_trees.rb
new file mode 100644 (file)
index 0000000..2118083
--- /dev/null
@@ -0,0 +1,49 @@
+# 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 = 12
+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)
+
+puts "stretch tree of depth #{stretch_depth} 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} trees of depth #{depth} check: #{check}"
+end
+
+puts "long lived tree of depth #{max_depth} check: #{item_check(*long_lived_tree)}"
diff --git a/tests/benchmark/binary_trees.wren b/tests/benchmark/binary_trees.wren
new file mode 100644 (file)
index 0000000..2393462
--- /dev/null
@@ -0,0 +1,51 @@
+// Ported from the Python version.
+
+class Tree {
+  construct 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) {
+      return _item
+    }
+
+    return _item + _left.check - _right.check
+  }
+}
+
+var minDepth = 4
+var maxDepth = 12
+var stretchDepth = maxDepth + 1
+
+System.print("stretch tree of depth %(stretchDepth) check: " +
+    "%(Tree.new(0, stretchDepth).check)")
+
+var longLivedTree = Tree.new(0, maxDepth)
+
+// iterations = 2 ** maxDepth
+var iterations = 1
+for (d in 0...maxDepth) {
+  iterations = iterations * 2
+}
+
+var depth = minDepth
+while (depth < stretchDepth) {
+  var check = 0
+  for (i in 1..iterations) {
+    check = check + Tree.new(i, depth).check + Tree.new(-i, depth).check
+  }
+
+  System.print("%(iterations * 2) trees of depth %(depth) check: %(check)")
+  iterations = iterations / 4
+  depth = depth + 2
+}
+
+System.print(
+    "long lived tree of depth %(maxDepth) check: %(longLivedTree.check)")
diff --git a/tests/benchmark/binary_trees_gc.wren b/tests/benchmark/binary_trees_gc.wren
new file mode 100644 (file)
index 0000000..803202e
--- /dev/null
@@ -0,0 +1,55 @@
+// Ported from the Python version.
+
+class Tree {
+  construct 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) {
+      return _item
+    }
+
+    return _item + _left.check - _right.check
+  }
+}
+
+var minDepth = 4
+var maxDepth = 12
+var stretchDepth = maxDepth + 1
+
+System.print("stretch tree of depth %(stretchDepth) check: " +
+    "%(Tree.new(0, stretchDepth).check)")
+for (i in 1...1000) System.gc()
+
+var longLivedTree = Tree.new(0, maxDepth)
+
+// iterations = 2 ** maxDepth
+var iterations = 1
+for (d in 0...maxDepth) {
+  iterations = iterations * 2
+}
+
+var depth = minDepth
+while (depth < stretchDepth) {
+  var check = 0
+  for (i in 1..iterations) {
+    check = check + Tree.new(i, depth).check + Tree.new(-i, depth).check
+  }
+
+  System.print("%(iterations * 2) trees of depth %(depth) check: %(check)")
+  for (i in 1...1000) System.gc()
+
+  iterations = iterations / 4
+  depth = depth + 2
+}
+
+System.print(
+    "long lived tree of depth %(maxDepth) check: %(longLivedTree.check)")
+for (i in 1...1000) System.gc()