Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add benchmarks comparing to Cairo VM #692

Merged
merged 39 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a1237aa
Add benches
JulianGCalderon Jun 18, 2024
2ad28d0
Merge branch 'main' into benches_vs_vm
JulianGCalderon Jun 18, 2024
1ef0826
Fix clippy
JulianGCalderon Jun 18, 2024
243d629
Merge branch 'main' into benches_vs_vm
edg-l Jun 21, 2024
702fd8a
Merge branch 'main' into benches_vs_vm
JulianGCalderon Jun 25, 2024
642e6ff
Add more cases
JulianGCalderon Jun 25, 2024
ca6629b
Use fibonacci instead of fib
JulianGCalderon Jun 25, 2024
6ff72dd
Differenciate expect messages
JulianGCalderon Jun 25, 2024
8c726fb
Separate into groups per program
JulianGCalderon Jun 25, 2024
094c7b4
Merge branch 'main' into benches_vs_vm
JulianGCalderon Jun 28, 2024
b88d39b
Merge branch 'main' into benches_vs_vm
pefontana Jul 2, 2024
ae204ba
Merge branch 'main' into benches_vs_vm
pefontana Jul 6, 2024
332ca73
Merge branch 'main' into benches_vs_vm
edg-l Oct 2, 2024
3baaa79
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 7, 2024
897838c
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 7, 2024
4d379fe
Add result checks
JulianGCalderon Nov 7, 2024
5083718
Merge branch 'benches_vs_vm_2' into benches_vs_vm
JulianGCalderon Nov 7, 2024
6bd8a12
Fix clippy
JulianGCalderon Nov 7, 2024
f21ffda
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 7, 2024
dbb6fc7
Add compile bench
JulianGCalderon Nov 7, 2024
ce8e90a
Add linear search
JulianGCalderon Nov 7, 2024
8b30ed3
Add linear search bench
JulianGCalderon Nov 7, 2024
eab4bd6
Lower time
JulianGCalderon Nov 7, 2024
7bf2647
Fix program
JulianGCalderon Nov 8, 2024
1ebd0df
Add linear_search.c
JulianGCalderon Nov 8, 2024
16cfb8e
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 11, 2024
356b47a
Add builtin
JulianGCalderon Nov 11, 2024
7ba0be1
Fix
JulianGCalderon Nov 11, 2024
019f74e
Fix symbol number
JulianGCalderon Nov 11, 2024
0680850
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 19, 2024
8ab047c
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 20, 2024
2a08449
Update benches
JulianGCalderon Nov 20, 2024
5ee1ea5
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 25, 2024
a380aa2
Fix bench
JulianGCalderon Nov 25, 2024
2f35f5d
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 27, 2024
88d9006
Remove comp benchmark
JulianGCalderon Nov 27, 2024
d66321f
Remove extra dependency
JulianGCalderon Nov 27, 2024
9f05acf
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 27, 2024
abdfcbd
Merge branch 'main' into benches_vs_vm
JulianGCalderon Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
241 changes: 221 additions & 20 deletions benches/benches.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use cairo_lang_compiler::{
compile_prepared_db, db::RootDatabase, project::setup_project, CompilerConfig,
};
use cairo_lang_runner::{RunResultValue, SierraCasmRunner, StarknetState};
use cairo_lang_sierra::program::Program;
use cairo_lang_sierra_generator::replace_ids::DebugReplacer;
use cairo_lang_starknet::contract::{find_contracts, get_contracts_info};
use cairo_lang_utils::Upcast;
use cairo_native::{
cache::{AotProgramCache, JitProgramCache},
context::NativeContext,
utils::find_function_id,
OptLevel,
OptLevel, Value,
};
use criterion::{criterion_group, criterion_main, Criterion};
use starknet_types_core::felt::Felt;
Expand All @@ -20,6 +24,7 @@ fn criterion_benchmark(c: &mut Criterion) {
let factorial = load_contract("programs/benches/factorial_2M.cairo");
let fibonacci = load_contract("programs/benches/fib_2M.cairo");
let logistic_map = load_contract("programs/benches/logistic_map.cairo");
let linear_search = load_contract("programs/benches/linear_search.cairo");

let aot_factorial = aot_cache
.compile_and_insert(Felt::ZERO, &factorial, OptLevel::Aggressive)
Expand All @@ -30,6 +35,9 @@ fn criterion_benchmark(c: &mut Criterion) {
let aot_logistic_map = aot_cache
.compile_and_insert(Felt::from(2), &logistic_map, OptLevel::Aggressive)
.unwrap();
let aot_linear_search = aot_cache
.compile_and_insert(Felt::from(2), &linear_search, OptLevel::Aggressive)
.unwrap();

let jit_factorial = jit_cache
.compile_and_insert(Felt::ZERO, &factorial, OptLevel::Aggressive)
Expand All @@ -40,32 +48,195 @@ fn criterion_benchmark(c: &mut Criterion) {
let jit_logistic_map = jit_cache
.compile_and_insert(Felt::from(2), &logistic_map, OptLevel::Aggressive)
.unwrap();
let jit_linear_search = jit_cache
.compile_and_insert(Felt::from(2), &linear_search, OptLevel::Aggressive)
.unwrap();

let factorial_function_id =
find_function_id(&factorial, "factorial_2M::factorial_2M::main").unwrap();
let fibonacci_function_id = find_function_id(&fibonacci, "fib_2M::fib_2M::main").unwrap();
let logistic_map_function_id =
find_function_id(&logistic_map, "logistic_map::logistic_map::main").unwrap();
let linear_search_function_id =
find_function_id(&linear_search, "linear_search::linear_search::main").unwrap();

let factorial_runner = load_contract_for_vm("programs/benches/factorial_2M.cairo");
let fibonacci_runner = load_contract_for_vm("programs/benches/fib_2M.cairo");
let logistic_map_runner = load_contract_for_vm("programs/benches/logistic_map.cairo");
let linear_search_runner = load_contract_for_vm("programs/benches/linear_search.cairo");

let factorial_function = factorial_runner
.find_function("main")
.expect("failed to find main factorial function");
let fibonacci_function = fibonacci_runner
.find_function("main")
.expect("failed to find main fibonacci function");
let logistic_map_function = logistic_map_runner
.find_function("main")
.expect("failed to find main logistic map function");
let linear_search_function = linear_search_runner
.find_function("main")
.expect("failed to find main logistic map function");

{
let mut linear_search_group = c.benchmark_group("linear_search");

linear_search_group.bench_function("Cached JIT", |b| {
b.iter(|| {
let result = jit_linear_search
.invoke_dynamic(linear_search_function_id, &[], Some(u64::MAX))
.unwrap();
let value = result.return_value;
assert!(matches!(value, Value::Enum { tag: 0, .. }))
});
});
linear_search_group.bench_function("Cached AOT", |b| {
b.iter(|| {
let result = aot_linear_search
.invoke_dynamic(linear_search_function_id, &[], Some(u64::MAX))
.unwrap();
let value = result.return_value;
assert!(matches!(value, Value::Enum { tag: 0, .. }))
});
});

linear_search_group.bench_function("VM", |b| {
b.iter(|| {
let result = linear_search_runner
.run_function_with_starknet_context(
linear_search_function,
&[],
Some(usize::MAX),
StarknetState::default(),
)
.unwrap();
let value = result.value;
assert!(matches!(value, RunResultValue::Success(_)))
});
});

linear_search_group.finish();
}

{
let mut factorial_group = c.benchmark_group("factorial_2M");

factorial_group.bench_function("Cached JIT", |b| {
b.iter(|| {
let result = jit_factorial
.invoke_dynamic(factorial_function_id, &[], Some(u64::MAX))
.unwrap();
let value = result.return_value;
assert!(matches!(value, Value::Enum { tag: 0, .. }))
});
});
factorial_group.bench_function("Cached AOT", |b| {
b.iter(|| {
let result = aot_factorial
.invoke_dynamic(factorial_function_id, &[], Some(u64::MAX))
.unwrap();
let value = result.return_value;
assert!(matches!(value, Value::Enum { tag: 0, .. }))
});
});

factorial_group.bench_function("VM", |b| {
b.iter(|| {
let result = factorial_runner
.run_function_with_starknet_context(
factorial_function,
&[],
Some(usize::MAX),
StarknetState::default(),
)
.unwrap();
let value = result.value;
assert!(matches!(value, RunResultValue::Success(_)))
});
});

factorial_group.finish();
}

{
let mut fibonacci_group = c.benchmark_group("fibonacci_2M");

fibonacci_group.bench_function("Cached JIT", |b| {
b.iter(|| {
let result = jit_fibonacci
.invoke_dynamic(fibonacci_function_id, &[], Some(u64::MAX))
.unwrap();
let value = result.return_value;
assert!(matches!(value, Value::Enum { tag: 0, .. }))
});
});
fibonacci_group.bench_function("Cached AOT", |b| {
b.iter(|| {
let result = aot_fibonacci
.invoke_dynamic(fibonacci_function_id, &[], Some(u64::MAX))
.unwrap();
let value = result.return_value;
assert!(matches!(value, Value::Enum { tag: 0, .. }))
})
});
fibonacci_group.bench_function("VM", |b| {
b.iter(|| {
let result = fibonacci_runner
.run_function_with_starknet_context(
fibonacci_function,
&[],
Some(usize::MAX),
StarknetState::default(),
)
.unwrap();
let value = result.value;
assert!(matches!(value, RunResultValue::Success(_)))
});
});

fibonacci_group.finish();
}

c.bench_function("Cached JIT factorial_2M", |b| {
b.iter(|| jit_factorial.invoke_dynamic(factorial_function_id, &[], Some(u64::MAX)));
});
c.bench_function("Cached JIT fib_2M", |b| {
b.iter(|| jit_fibonacci.invoke_dynamic(fibonacci_function_id, &[], Some(u64::MAX)));
});
c.bench_function("Cached JIT logistic_map", |b| {
b.iter(|| jit_logistic_map.invoke_dynamic(logistic_map_function_id, &[], Some(u64::MAX)));
});

c.bench_function("Cached AOT factorial_2M", |b| {
b.iter(|| aot_factorial.invoke_dynamic(factorial_function_id, &[], Some(u64::MAX)));
});
c.bench_function("Cached AOT fib_2M", |b| {
b.iter(|| aot_fibonacci.invoke_dynamic(fibonacci_function_id, &[], Some(u64::MAX)));
});
c.bench_function("Cached AOT logistic_map", |b| {
b.iter(|| aot_logistic_map.invoke_dynamic(logistic_map_function_id, &[], Some(u64::MAX)));
});
{
let mut logistic_map_group = c.benchmark_group("logistic_map");

logistic_map_group.bench_function("Cached JIT", |b| {
b.iter(|| {
let result = jit_logistic_map
.invoke_dynamic(logistic_map_function_id, &[], Some(u64::MAX))
.unwrap();
let value = result.return_value;
assert!(matches!(value, Value::Enum { tag: 0, .. }))
});
});

logistic_map_group.bench_function("Cached AOT", |b| {
b.iter(|| {
let result = aot_logistic_map
.invoke_dynamic(logistic_map_function_id, &[], Some(u64::MAX))
.unwrap();
let value = result.return_value;
assert!(matches!(value, Value::Enum { tag: 0, .. }))
});
});

logistic_map_group.bench_function("VM", |b| {
b.iter(|| {
let result = logistic_map_runner
.run_function_with_starknet_context(
logistic_map_function,
&[],
Some(usize::MAX),
StarknetState::default(),
)
.unwrap();
let value = result.value;
assert!(matches!(value, RunResultValue::Success(_)))
});
});

logistic_map_group.finish();
}
}

fn load_contract(path: impl AsRef<Path>) -> Program {
Expand All @@ -84,5 +255,35 @@ fn load_contract(path: impl AsRef<Path>) -> Program {
sirrra_program.program
}

fn load_contract_for_vm(path: impl AsRef<Path>) -> SierraCasmRunner {
let mut db = RootDatabase::builder()
.detect_corelib()
.build()
.expect("failed to build database");
let main_crate_ids = setup_project(&mut db, path.as_ref()).expect("failed to setup project");
let program = compile_prepared_db(
&db,
main_crate_ids.clone(),
CompilerConfig {
replace_ids: true,
..Default::default()
},
)
.expect("failed to compile program");

let replacer = DebugReplacer { db: &db };
let contracts = find_contracts((db).upcast(), &main_crate_ids);
let contracts_info =
get_contracts_info(&db, contracts, &replacer).expect("failed to get contracts info");

SierraCasmRunner::new(
program.program.clone(),
Some(Default::default()),
contracts_info,
None,
)
.expect("failed to create runner")
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
37 changes: 37 additions & 0 deletions programs/benches/linear_search.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <assert.h>
#include <stdint.h>


typedef struct linear_search_return_values
{
uint64_t range_check_counter;
uint64_t remaining_gas;
struct {
uint8_t discriminant;
struct {
void *ptr;
uint32_t start;
uint32_t end;
uint32_t cap;
} err;
} result;
} linear_search_return_values_t;

static void run_bench(linear_search_return_values_t *, uint64_t)
__attribute__((weakref("_mlir_ciface_linear_search::linear_search::main(f4)")));

extern uint64_t* cairo_native__set_costs_builtin(uint64_t*);

int main()
{
uint64_t BuiltinCosts[7] = {1, 4050, 583, 4085, 491, 230, 604};

cairo_native__set_costs_builtin(&BuiltinCosts[0]);

linear_search_return_values_t return_values;

run_bench(&return_values, 0xFFFFFFFFFFFFFFFF);
assert((return_values.result.discriminant & 0x1) == 0);

return 0;
}
37 changes: 37 additions & 0 deletions programs/benches/linear_search.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
fn search(array: @Array<felt252>, number: felt252) -> u32 {
let mut index = 0;

while index < array.len() {
if *array[index] == number {
break;
}

index += 1;
};

return index;
}

fn init_array(length: u32) -> Array<felt252> {
let mut array = ArrayTrait::new();
for i in 0..length {
array.append(i.into());
};

return array;
}

fn main() {
let array = init_array(4001);

let index = search(@array, 4000);
assert(
index == 4000,
'invalid result'
);
let index = search(@array, 2000);
assert(
index == 2000,
'invalid result'
);
}
Loading