diff --git a/.gitignore b/.gitignore index 3e64010..6e91045 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ target/ lcov.info build_artifacts/ + +*.so +*.a diff --git a/bench/.gitignore b/bench/.gitignore new file mode 100644 index 0000000..7b6a50d --- /dev/null +++ b/bench/.gitignore @@ -0,0 +1,2 @@ +bench_* +*.so diff --git a/bench/bench.c b/bench/bench.c index e2dfe8c..f3289c4 100644 --- a/bench/bench.c +++ b/bench/bench.c @@ -1,21 +1,70 @@ #include #include +#include +#include #include -extern uint64_t factorial_concrete(uint64_t n); -extern uint64_t factorial_rust(uint64_t n); +extern uint64_t concrete_function(uint64_t n); +extern uint64_t rust_function(uint64_t n); -int main() { +struct timespec timer_start() { + struct timespec start_time; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time); + return start_time; +} + +long timer_end(struct timespec start_time) { + struct timespec end_time; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time); + long diffInNanos = (end_time.tv_sec - start_time.tv_sec) * (long)1e9 + + (end_time.tv_nsec - start_time.tv_nsec); + return diffInNanos; +} + +int main(int argc, const char **argv) { + if (argc < 2) { + fprintf(stderr, "missing iteration arguments\n"); + return 1; + } + + if (argc < 3) { + fprintf(stderr, "missing input number argument\n"); + return 1; + } + + int num_iters = atoi(argv[1]); + int input = atoi(argv[2]); + + uint64_t result_concrete; + uint64_t result_rust; + + // warmup + sanity check + for (size_t i = 0; i < 3; ++i) { + assert(concrete_function(input) == rust_function(input)); + } + + printf("Running %d iterations\n", num_iters); + printf("Using input value:\t%d\n", input); - clock_t begin = clock(); - uint64_t result_concrete = factorial_concrete(20); - clock_t end = clock(); - double time_spent = (double)(end - begin) / CLOCKS_PER_SEC; + { + struct timespec vartime = timer_start(); + for (size_t i = 0; i < num_iters; ++i) { + result_concrete = concrete_function(input); + } + long time_elapsed_nanos = timer_end(vartime); + printf("Concrete Result =\t%lu\t\tTime taken : %.2Lf ms\n", result_concrete, + (long double)time_elapsed_nanos / 1000000.0L); + } - clock_t begin2 = clock(); - uint64_t result_rust = factorial_rust(20); - clock_t end2 = clock(); - double time_spent2 = (double)(end - begin) / CLOCKS_PER_SEC; + { + struct timespec vartime = timer_start(); + for (size_t i = 0; i < num_iters; ++i) { + result_rust = rust_function(input); + } + long time_elapsed_nanos = timer_end(vartime); + printf("Rust Result =\t\t%lu\t\tTime taken : %.2Lf ms\n", result_rust, + (long double)time_elapsed_nanos / 1000000.0L); + } assert(result_concrete == result_rust); diff --git a/bench/bench.sh b/bench/bench.sh new file mode 100755 index 0000000..4f926c1 --- /dev/null +++ b/bench/bench.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +cd "$(dirname "$0")" + +RED='\033[0;31m' +NC='\033[0m' # No Color + +# name without extension, num_iters, input number +function bench_program() { + local name=$1 + local num_iters=$2 + local input=$3 + + echo -e "### ${RED}Benchmarking $name ${NC}" + + rustc --crate-type=cdylib "$name.rs" -C opt-level=3 -o "${name}_rs.so" > /dev/null 2>&1 + cargo r -- "$name.con" --library --release > /dev/null 2>&1 + cp "./build_artifacts/$name.so" "${name}_con.so" + + cc bench.c -L . -l:./"${name}"_rs.so -l:./"${name}"_con.so -Wl,-rpath -o bench_"${name}" + + ./bench_"${name}" "$num_iters" "$input" +} + +bench_program "factorial" 5000000 20 +bench_program "fib" 5000 20 + +rm ./*.so diff --git a/bench/compile.sh b/bench/compile.sh deleted file mode 100644 index e69de29..0000000 diff --git a/bench/factorial_if.con b/bench/factorial.con similarity index 50% rename from bench/factorial_if.con rename to bench/factorial.con index 2a9b20e..1d8773d 100644 --- a/bench/factorial_if.con +++ b/bench/factorial.con @@ -1,9 +1,9 @@ mod Factorial { - fn factorial_concrete(n: u64) -> u64 { + fn concrete_function(n: u64) -> u64 { if n == 0 { return 1; } else { - return n * factorial_concrete(n - 1); + return n * concrete_function(n - 1); } } } diff --git a/bench/factorial.rs b/bench/factorial.rs new file mode 100644 index 0000000..ff26f6d --- /dev/null +++ b/bench/factorial.rs @@ -0,0 +1,8 @@ +#[no_mangle] +pub extern "C" fn rust_function(n: u64) -> u64 { + if n == 0 { + return 1; + } else { + return n * rust_function(n - 1); + } +} diff --git a/bench/factorial_con.so b/bench/factorial_con.so deleted file mode 100755 index 4858da5..0000000 Binary files a/bench/factorial_con.so and /dev/null differ diff --git a/bench/factorial_if.rs b/bench/factorial_if.rs deleted file mode 100644 index f3f02dc..0000000 --- a/bench/factorial_if.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[no_mangle] -pub extern "C" fn factorial_rust(n: u64) -> u64 { - if n == 0 { - return 1; - } else { - return n * factorial_rust(n - 1); - } -} diff --git a/bench/factorial_rs.so b/bench/factorial_rs.so deleted file mode 100755 index a624209..0000000 Binary files a/bench/factorial_rs.so and /dev/null differ diff --git a/bench/fib.con b/bench/fib.con new file mode 100644 index 0000000..a02aef8 --- /dev/null +++ b/bench/fib.con @@ -0,0 +1,9 @@ +mod Fibonacci { + pub fn concrete_function(n: u64) -> u64 { + if n < 2 { + return n; + } + + return concrete_function(n - 1) + concrete_function(n - 2); + } +} diff --git a/bench/fib.rs b/bench/fib.rs new file mode 100644 index 0000000..3f2a73d --- /dev/null +++ b/bench/fib.rs @@ -0,0 +1,8 @@ +#[no_mangle] +pub extern "C" fn rust_function(n: u64) -> u64 { + if n < 2 { + return n; + } + + return rust_function(n - 1) + rust_function(n - 2); +}