diff --git a/benchmark/01-factorial.scm b/benchmark/01-factorial.scm new file mode 100644 index 0000000..ff86756 --- /dev/null +++ b/benchmark/01-factorial.scm @@ -0,0 +1,5 @@ +(letrec ((fact (lambda (n acc) + (if (< n 2) + acc + (fact (- n 1) (* n acc)))))) + (fact 20 1)) diff --git a/benchmark/01-fib31.scm b/benchmark/01-fib31.scm deleted file mode 100644 index 8db51c1..0000000 --- a/benchmark/01-fib31.scm +++ /dev/null @@ -1,5 +0,0 @@ -(letrec ((fib (lambda (n) - (if (< n 2) - n - (+ (fib (- n 1)) (fib (- n 2))))))) - (fib 31)) diff --git a/benchmark/02-dotproduct.scm b/benchmark/02-dotproduct.scm new file mode 100644 index 0000000..c70bf7a --- /dev/null +++ b/benchmark/02-dotproduct.scm @@ -0,0 +1,9 @@ +(let ((v1 (make-vector 4000000 1)) + (v2 (make-vector 4000000 2))) + (letrec ((dot (lambda (i acc) + (if (= i 4000000) + acc + (dot (+ i 1) + (+ acc (* (vector-ref v1 i) + (vector-ref v2 i)))))))) + (dot 0 0))) diff --git a/benchmark/02-fib30.scm b/benchmark/02-fib30.scm deleted file mode 100644 index 1e7975f..0000000 --- a/benchmark/02-fib30.scm +++ /dev/null @@ -1,5 +0,0 @@ -(letrec ((fib (lambda (n) - (if (< n 2) - n - (+ (fib (- n 1)) (fib (- n 2))))))) - (fib 30)) diff --git a/benchmark/03-loop2_5.scm b/benchmark/03-loop2_5.scm deleted file mode 100644 index d7c3ad3..0000000 --- a/benchmark/03-loop2_5.scm +++ /dev/null @@ -1,5 +0,0 @@ -(letrec ((loop (lambda (n acc) - (if (< n 2500000) - (loop (+ n 1) (+ acc n)) - acc)))) - (loop 0 0)) diff --git a/benchmark/03-nbody.scm b/benchmark/03-nbody.scm new file mode 100644 index 0000000..d1ec810 --- /dev/null +++ b/benchmark/03-nbody.scm @@ -0,0 +1,23 @@ +(letrec + ((iterate (lambda (x1 y1 vx1 vy1 x2 y2 vx2 vy2 steps) + (if (= steps 0) + (+ x1 x2) + (let ((dx (- x2 x1)) + (dy (- y2 y1))) + (let ((d2 (+ (* dx dx) (* dy dy)))) + (let ((f (/ 1 d2))) + (let ((ax (* f dx)) + (ay (* f dy))) + (let ((bx (- ax)) + (by (- ay))) + (iterate (+ x1 vx1) + (+ y1 vy1) + (+ vx1 ax) + (+ vy1 ay) + (+ x2 vx2) + (+ y2 vy2) + (+ vx2 bx) + (+ vy2 by) + (- steps 1)))))))))) + ) + (iterate 0 0 0 1 1 0 0 -1 1000000)) diff --git a/benchmark/04-bst.scm b/benchmark/04-bst.scm new file mode 100644 index 0000000..68c0051 --- /dev/null +++ b/benchmark/04-bst.scm @@ -0,0 +1,26 @@ +(letrec ((make-node (lambda (v l r) (cons v (cons l r)))) + (left (lambda (node) (car (cdr node)))) + (right (lambda (node) (cdr (cdr node)))) + (insert (lambda (tree n) + (if (null? tree) + (make-node n '() '()) + (let ((v (car tree))) + (if (< n v) + (make-node v + (insert (left tree) n) + (right tree)) + (make-node v + (left tree) + (insert (right tree) n)))))) + ) + (build (lambda (i max tree) + (if (= i max) + tree + (build (+ i 1) max (insert tree i))))) + (sum-tree (lambda (tree) + (if (null? tree) + 0 + (+ (car tree) + (sum-tree (left tree)) + (sum-tree (right tree))))))) + (sum-tree (build 0 2200 '()))) diff --git a/benchmark/04-loop3.scm b/benchmark/04-loop3.scm deleted file mode 100644 index 0a01425..0000000 --- a/benchmark/04-loop3.scm +++ /dev/null @@ -1,5 +0,0 @@ -(letrec ((loop (lambda (n acc) - (if (< n 3500000) - (loop (+ n 1) (+ acc n)) - acc)))) - (loop 0 0)) diff --git a/benchmark/05-loop5.scm b/benchmark/05-loop5.scm deleted file mode 100644 index cf16df3..0000000 --- a/benchmark/05-loop5.scm +++ /dev/null @@ -1,5 +0,0 @@ -(letrec ((loop (lambda (n acc) - (if (< n 5000000) - (loop (+ n 1) (+ acc n)) - acc)))) - (loop 0 0)) diff --git a/benchmark/run.ts b/benchmark/run.ts index 926e963..d851758 100644 --- a/benchmark/run.ts +++ b/benchmark/run.ts @@ -3,26 +3,39 @@ import path from 'path'; import * as FoxScheme from '../src/foxscheme'; const { Parser, Interpreter } = FoxScheme as any; -const benchmarks = [ - '01-fib31.scm', - '02-fib30.scm', - '03-loop2_5.scm', - '04-loop3.scm', - '05-loop5.scm' +interface Benchmark { + file: string; + expected: number; +} + +const benchmarks: Benchmark[] = [ + { file: '01-factorial.scm', expected: 2432902008176640000 }, + { file: '02-dotproduct.scm', expected: 8000000 }, + { file: '03-nbody.scm', expected: 1 }, + { file: '04-bst.scm', expected: 2418900 }, ]; const interp = new Interpreter(); let total = 0; -for (const file of benchmarks) { - const code = fs.readFileSync(path.join(__dirname, file), 'utf8'); +for (const bench of benchmarks) { + const code = fs.readFileSync(path.join(__dirname, bench.file), 'utf8'); const parser = new Parser(code); let obj: any; + let result: any = undefined; const start = Date.now(); while ((obj = parser.nextObject()) !== Parser.EOS) { - interp.eval(obj); + result = interp.eval(obj); } const elapsed = Date.now() - start; + if (typeof result === 'number') { + const diff = Math.abs(result - bench.expected); + if (diff > 1e-9) { + throw new Error(`${bench.file} expected ${bench.expected} but got ${result}`); + } + } else if (result != bench.expected) { + throw new Error(`${bench.file} expected ${bench.expected} but got ${result}`); + } total += elapsed; - console.log(`${file}: ${ (elapsed/1000).toFixed(3) }s`); + console.log(`${bench.file}: ${(elapsed / 1000).toFixed(3)}s`); } -console.log(`Total: ${(total/1000).toFixed(3)}s`); +console.log(`Total: ${(total / 1000).toFixed(3)}s`);