Skip to content

Commit 46d485d

Browse files
committed
benchmark
1 parent 493f7b2 commit 46d485d

9 files changed

+646
-62
lines changed

Cargo.lock

+494-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "monkey_in_rust"
2+
name = "monkey_lang"
33
version = "0.1.0"
44
edition = "2021"
55

@@ -11,3 +11,10 @@ fxhash = "0.2.1"
1111
lazy_static = "1.4.0"
1212
byteorder = "1.4.3"
1313
clap = { version = "4.1.6", features = ["derive"] }
14+
15+
[dev-dependencies]
16+
criterion = "0.4"
17+
18+
[[bench]]
19+
name = "engine"
20+
harness = false

benches/engine.rs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use std::{cell::RefCell, rc::Rc};
2+
3+
use monkey_lang::{
4+
ast::Program, compiler::Compiler, enviroment::Enviroment, evaluator::Evaluator, lexer::Lexer,
5+
parser::Parser, vm::Vm,
6+
};
7+
8+
use criterion::{criterion_group, criterion_main, Criterion};
9+
10+
static INPUT: &str = "
11+
let fibonacci = fn(x) {
12+
if (x == 0) {
13+
return 0;
14+
} else {
15+
if (x == 1) {
16+
return 1;
17+
} else {
18+
fibonacci(x - 1) + fibonacci(x - 2);
19+
}
20+
}
21+
};
22+
fibonacci(15);
23+
";
24+
25+
fn eval(program: &Program) {
26+
let env = Rc::new(RefCell::new(Enviroment::default()));
27+
let mut evaluator = Evaluator::new(env);
28+
evaluator.eval(program);
29+
}
30+
31+
fn vm(program: &Program) {
32+
let mut compiler = Compiler::new();
33+
compiler.compile(program);
34+
let mut vm = Vm::new(compiler.bytecode());
35+
vm.run();
36+
}
37+
38+
fn criterion_benchmark(c: &mut Criterion) {
39+
let mut lexer = Lexer::new(INPUT);
40+
let mut parser = Parser::new(&mut lexer);
41+
let program = parser.parse_program();
42+
43+
let mut group = c.benchmark_group("Engine");
44+
group.bench_function("eval", |b| b.iter(|| eval(&program)));
45+
group.bench_function("vm", |b| b.iter(|| vm(&program)));
46+
group.finish();
47+
}
48+
49+
criterion_group!(benches, criterion_benchmark);
50+
criterion_main!(benches);

rust-toolchain.toml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[toolchain]
2+
profile = "default"
3+
# Use nightly for better access to the latest Rust features.
4+
# This date is aligned to stable release dates.
5+
channel = "nightly-2023-01-26"

src/evaluator.rs

+17-17
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ use std::cell::RefCell;
22
use std::collections::HashMap;
33
use std::rc::Rc;
44

5+
use crate::ast::Expression;
56
use crate::ast::{
6-
ArrayLiteral, BlockStatement, FunctionLiteral, HashLiteral, Identifier, IfExpression,
7-
IndexExpression, InfixExpression, LetStatement, PrefixExpression,
8-
Program, ReturnStatement, Statement, CallExpression,
7+
ArrayLiteral, BlockStatement, CallExpression, FunctionLiteral, HashLiteral, Identifier,
8+
IfExpression, IndexExpression, InfixExpression, LetStatement, PrefixExpression, Program,
9+
ReturnStatement, Statement,
910
};
10-
use crate::ast::Expression;
1111
use crate::builtin::Builtin;
1212
use crate::enviroment::Enviroment;
13-
use crate::makro::{EvalUnqupteCalls, MacroExpension};
13+
use crate::makro::EvalUnqupteCalls;
14+
use crate::object::Hash;
1415
use crate::object::{
15-
Array, BuiltinFunction, Function, HashKeyable, Inspector, Integer, Object,
16-
Quote, ReturnValue, RuntimeError, Str,
16+
Array, BuiltinFunction, Function, HashKeyable, Inspector, Integer, Object, Quote, ReturnValue,
17+
RuntimeError, Str,
1718
};
18-
use crate::object::Hash;
1919
use crate::traverser::Traverable;
2020

2121
#[derive(Debug)]
@@ -32,11 +32,7 @@ impl Evaluator {
3232
}
3333
}
3434

35-
pub fn eval(&mut self, program: &mut Program) -> Rc<Object> {
36-
let makro = MacroExpension::new(Rc::clone(&self.env));
37-
makro.define_macros(program);
38-
makro.expand_macros(program);
39-
35+
pub fn eval(&mut self, program: &Program) -> Rc<Object> {
4036
self.eval_program(program)
4137
}
4238

@@ -180,10 +176,10 @@ impl Evaluator {
180176
}
181177
}
182178

183-
fn eval_program(&mut self, program: &mut Program) -> Rc<Object> {
179+
fn eval_program(&mut self, program: &Program) -> Rc<Object> {
184180
let mut result = Rc::clone(&self.env.borrow().null_object);
185181

186-
for stmt in program.statements.iter_mut() {
182+
for stmt in program.statements.iter() {
187183
result = self.eval_statement(stmt);
188184

189185
match *result {
@@ -539,11 +535,15 @@ mod tests {
539535
enviroment::Enviroment,
540536
lexer::Lexer,
541537
object::{Boolean, HashKey, HashKeyable, Integer, Object, Str},
542-
parser::Parser, test_helper::{test_integer_object, test_boolean_object, test_null_object, test_string_object, test_error_object},
538+
parser::Parser,
539+
test_helper::{
540+
test_boolean_object, test_error_object, test_integer_object, test_null_object,
541+
test_string_object,
542+
},
543543
};
544544

545545
fn test_eval(input: &str) -> Rc<Object> {
546-
let mut lexer = Lexer::new(input.into());
546+
let mut lexer = Lexer::new(input);
547547
let mut parser = Parser::new(&mut lexer);
548548
let env = Rc::new(RefCell::new(Enviroment::default()));
549549
let mut program = parser.parse_program();

src/lib.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use clap::ValueEnum;
2+
3+
pub mod ast;
4+
mod builtin;
5+
pub mod enviroment;
6+
pub mod evaluator;
7+
pub mod lexer;
8+
mod object;
9+
pub mod parser;
10+
pub mod repl;
11+
mod token;
12+
mod traverser;
13+
pub mod makro;
14+
mod code;
15+
pub mod compiler;
16+
mod symbol_table;
17+
pub mod vm;
18+
mod frame;
19+
20+
#[cfg(test)]
21+
pub mod test_helper;
22+
23+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
24+
pub enum Engine {
25+
Vm,
26+
Eval
27+
}
28+
29+

src/main.rs

+16-39
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,11 @@
1-
use std::{env::args, fs, process, cell::RefCell, rc::Rc, path::PathBuf};
1+
#![feature(test)]
2+
use std::{cell::RefCell, env::args, fs, path::PathBuf, process, rc::Rc};
23

3-
use clap::{Parser, ValueEnum};
4-
use enviroment::Enviroment;
5-
use evaluator::Evaluator;
6-
use lexer::Lexer;
7-
use crate::{repl::Repl, compiler::Compiler, vm::Vm};
8-
9-
mod ast;
10-
mod builtin;
11-
mod enviroment;
12-
mod evaluator;
13-
mod lexer;
14-
mod object;
15-
mod parser;
16-
mod repl;
17-
mod token;
18-
mod traverser;
19-
mod makro;
20-
mod code;
21-
mod compiler;
22-
mod symbol_table;
23-
mod vm;
24-
mod frame;
25-
26-
#[cfg(test)]
27-
mod test_helper;
28-
29-
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
30-
pub enum Engine {
31-
Vm,
32-
Eval
33-
}
4+
use clap::Parser;
5+
use monkey_lang::{
6+
compiler::Compiler, enviroment::Enviroment, evaluator::Evaluator, lexer::Lexer,
7+
makro::MacroExpension, parser, repl::Repl, vm::Vm, Engine,
8+
};
349

3510
#[derive(Parser)]
3611
#[command(author, version, about, long_about= None)]
@@ -53,14 +28,12 @@ fn main() {
5328

5429
fn run(file: &PathBuf, engine: &Engine) {
5530
let script = fs::read_to_string(file).expect("Unable to read file");
56-
let env = Rc::new(RefCell::new(Enviroment::default()));
57-
let mut evaluator = Evaluator::new(env);
5831
let mut lexer = Lexer::new(&script);
5932
let mut parser = parser::Parser::new(&mut lexer);
6033
let mut program = parser.parse_program();
61-
if !parser.errors.is_empty() {
34+
if !parser.errors.is_empty() {
6235
for error in parser.errors.iter() {
63-
println!("\t{}", error);
36+
println!("\t{error}");
6437
}
6538
process::exit(1);
6639
}
@@ -72,13 +45,17 @@ fn run(file: &PathBuf, engine: &Engine) {
7245
vm.run();
7346
let result = vm.last_popped_stack_elem();
7447
println!("{}", result.inspect());
75-
},
48+
}
7649
Engine::Eval => {
50+
let env = Rc::new(RefCell::new(Enviroment::default()));
51+
let makro = MacroExpension::new(Rc::clone(&env));
52+
makro.define_macros(&mut program);
53+
makro.expand_macros(&mut program);
54+
let mut evaluator = Evaluator::new(env);
7755
let result = evaluator.eval(&mut program);
7856
println!("{}", result.inspect());
79-
},
57+
}
8058
};
81-
8259
}
8360

8461
fn repl(engine: &Engine) {

src/repl.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66

77
use crate::{
88
compiler::Compiler, enviroment::Enviroment, evaluator::Evaluator, lexer::Lexer, parser::Parser,
9-
vm::Vm, Engine,
9+
vm::Vm, Engine, makro::MacroExpension,
1010
};
1111

1212
const MONKEY_FACE: &str = r#" __,__
@@ -96,6 +96,11 @@ impl<'a> Repl<'a> {
9696
continue;
9797
}
9898

99+
let makro = MacroExpension::new(Rc::clone(&env));
100+
makro.define_macros(&mut program);
101+
makro.expand_macros(&mut program);
102+
103+
99104
let mut evaluator = Evaluator::new(Rc::clone(&env));
100105
let result = evaluator.eval(&mut program);
101106
println!("{}", result.inspect());

src/vm.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1034,4 +1034,25 @@ mod tests {
10341034

10351035
run_vm_tests(&tests);
10361036
}
1037+
1038+
#[test]
1039+
fn test_recursive_fibonacci() {
1040+
let test = VmTestCase(
1041+
"let fibonacci = fn(x) {
1042+
if (x == 0) {
1043+
return 0;
1044+
} else {
1045+
if (x == 1) {
1046+
return 1;
1047+
} else {
1048+
fibonacci(x - 1) + fibonacci(x - 2);
1049+
}
1050+
}
1051+
};
1052+
fibonacci(15);",
1053+
ExpectedValue::Integer(610),
1054+
);
1055+
1056+
run_vm_tests(&[test]);
1057+
}
10371058
}

0 commit comments

Comments
 (0)