From d4525101cfd4d5ffb8f74fef5c8ab18d3a53e707 Mon Sep 17 00:00:00 2001 From: Julio Date: Sat, 24 Nov 2018 08:26:21 -0800 Subject: [PATCH] Instructions refactor (#756) * operation lookup table from map to static array * added comments to make operations array human readable and added more benchmark tests * added quicksort to context switch benchmark * fix fib benchmark, fn was being called with 0 as param * more sensible numbers for fib benchmark * reverted to previous more readable composite literal, maintaing array structure --- compiler/bytecode/instruction.go | 1 + vm/benchmark_test.go | 62 ++++++++++++++++++++++++++++++++ vm/instruction.go | 4 +-- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/compiler/bytecode/instruction.go b/compiler/bytecode/instruction.go index 2cf3f91ff..fa0ad4e50 100644 --- a/compiler/bytecode/instruction.go +++ b/compiler/bytecode/instruction.go @@ -45,6 +45,7 @@ const ( Pop Dup Leave + InstructionCount ) // InstructionNameTable is the table the maps instruction's op code with its readable name diff --git a/vm/benchmark_test.go b/vm/benchmark_test.go index fbc67b1f9..726bbcc85 100644 --- a/vm/benchmark_test.go +++ b/vm/benchmark_test.go @@ -76,3 +76,65 @@ func BenchmarkConcurrency(b *testing.B) { runBench(b, script) }) } + +func BenchmarkContextSwitch(b *testing.B) { + b.Run("fib", func(b *testing.B) { + script := ` + def fib(n) + if n <= 1 + return n + else + return fib(n - 1) + fib(n - 2) + end + end + + 25.times do |i| + fib(i/2) + end +` + runBench(b, script) + }) + + b.Run("quicksort", func(b *testing.B) { + script := ` + def quicksort(arr, l, r) + if l >= r + return + end + + pivot = arr[l] + i = l - 1 + j = r + 1 + + while true do + i += 1 + while arr[i] < pivot do + i += 1 + end + + j -= 1 + while arr[j] > pivot do + j -= 1 + end + + if i >= j + break + end + + # swap + tmp = arr[i] + arr[i] = arr[j] + arr[j] = tmp + end + + + quicksort(arr, l, j) + quicksort(arr, j + 1, r) + end + + arr = [ 0, 5, 3, 2, 5, 7, 3, 5, 6, 9] * 10 + quicksort(arr, 0, arr.length - 1) +` + runBench(b, script) + }) +} diff --git a/vm/instruction.go b/vm/instruction.go index d87ba5496..39c92b0dd 100644 --- a/vm/instruction.go +++ b/vm/instruction.go @@ -22,11 +22,11 @@ type instructionSet struct { paramTypes *bytecode.ArgSet } -var operations map[operationType]operation +var operations [bytecode.InstructionCount]operation // This is for avoiding initialization loop func init() { - operations = map[operationType]operation{ + operations = [bytecode.InstructionCount]operation{ bytecode.Pop: func(t *Thread, sourceLine int, cf *normalCallFrame, args ...interface{}) { t.Stack.Pop() },