Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 18 additions & 1 deletion crates/herkos-tests/benches/herkos_runtime_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,28 @@ fn fibo_20_orig_bench(c: &mut Criterion) {
c.bench_function("fib 20 plain rust", |b| b.iter(|| fibo_orig(black_box(20))));
}

// ─── Memory-intensive benchmarks ─────────────────────────────────────────────

fn memsort_500_wasm_bench(c: &mut Criterion) {
let mut m = rust_e2e_memory_bench::new().unwrap();
c.bench_function("memsort 500 wasm transpiled to rust", |b| {
b.iter(|| m.mem_fill_sort_sum(black_box(500), black_box(42)))
});
}

fn memsort_500_orig_bench(c: &mut Criterion) {
c.bench_function("memsort 500 plain rust", |b| {
b.iter(|| mem_fill_sort_sum_orig(black_box(500), black_box(42)))
});
}

criterion_group!(
benches,
fibo_5_wasm_bench,
fibo_5_orig_bench,
fibo_20_wasm_bench,
fibo_20_orig_bench
fibo_20_orig_bench,
memsort_500_wasm_bench,
memsort_500_orig_bench
);
criterion_main!(benches);
18 changes: 18 additions & 0 deletions crates/herkos-tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,24 @@ fn process_rust_e2e_files(
return Ok(Vec::new());
}

// Copy common include files to OUT_DIR so include!() paths resolve
// when rustc compiles the copied sources.
let common_dir = rust_dir.join("common");
if common_dir.exists() {
let out_common = out_dir.join("common");
fs::create_dir_all(&out_common).context("failed to create common/ in OUT_DIR")?;
for entry in fs::read_dir(&common_dir).context("failed to read data/rust/common/")? {
let entry = entry?;
let path = entry.path();
if path.is_file() {
let dest = out_common.join(path.file_name().unwrap());
fs::copy(&path, &dest).with_context(|| {
format!("failed to copy {} to OUT_DIR/common/", path.display())
})?;
}
}
}

let mut entries = collect_files_with_ext(rust_dir, "rs")?;
entries.sort();
eprintln!(
Expand Down
14 changes: 14 additions & 0 deletions crates/herkos-tests/data/rust/common/fibo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
fn fibo_impl(n: i32) -> i32 {
if n <= 1 {
n
} else {
let mut a: i32 = 0;
let mut b: i32 = 1;
for _ in 2..=n {
let tmp = a.wrapping_add(b);
a = b;
b = tmp;
}
b
}
}
29 changes: 29 additions & 0 deletions crates/herkos-tests/data/rust/common/fill_sort_sum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
fn fill_sort_sum_impl(buf: &mut [i32; 1024], n: i32, seed: i32) -> i32 {
if n <= 0 {
return 0;
}
let n = (n as usize).min(buf.len());

// Fill with LCG pseudo-random values
let mut rng = seed;
for item in buf.iter_mut().take(n) {
rng = rng.wrapping_mul(1103515245).wrapping_add(12345);
*item = rng;
}

// Bubble sort — indexing required for random-access swaps
for i in 0..n {
for j in 0..(n - 1 - i) {
if buf[j] > buf[j + 1] {
buf.swap(j, j + 1);
}
}
}

// Wrapping checksum
let mut sum: i32 = 0;
for item in buf.iter().take(n) {
sum = sum.wrapping_add(*item);
}
sum
}
15 changes: 3 additions & 12 deletions crates/herkos-tests/data/rust/rust_e2e_arith.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,11 @@ pub extern "C" fn sum_recursive(n: i32) -> i32 {
}
}

include!("common/fibo.rs");

#[no_mangle]
pub extern "C" fn fibo(n: i32) -> i32 {
if n <= 1 {
n
} else {
let mut a: i32 = 0;
let mut b: i32 = 1;
for _ in 2..=n {
let tmp = a.wrapping_add(b);
a = b;
b = tmp;
}
b
}
fibo_impl(n)
}

#[no_mangle]
Expand Down
27 changes: 27 additions & 0 deletions crates/herkos-tests/data/rust/rust_e2e_memory_bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#![no_std]

#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}

include!("common/fill_sort_sum.rs");

// Work buffer in the Wasm data segment (zero-initialized, goes to BSS).
// 1024 i32s = 4 KiB — fits comfortably in 2-page memory (128 KiB).
static mut BUF: [i32; 1024] = [0i32; 1024];

/// Fill the work buffer with pseudo-random values, bubble sort them in-place,
/// and return a wrapping checksum (sum of all sorted values).
///
/// Memory access profile (for `n` elements):
/// - Fill: n stores
/// - Sort: O(n²) loads + conditional stores (bubble sort)
/// - Sum: n loads
///
/// `n`: number of i32 elements to process (capped at 1024)
/// `seed`: initial value for the LCG pseudo-random generator
#[no_mangle]
pub extern "C" fn mem_fill_sort_sum(n: i32, seed: i32) -> i32 {
unsafe { fill_sort_sum_impl(&mut BUF, n, seed) }
}
28 changes: 16 additions & 12 deletions crates/herkos-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
// Include generated modules from build.rs (in OUT_DIR)
include!(concat!(env!("OUT_DIR"), "/mod.rs"));

// Shared algorithm implementations used by both the transpiled Wasm modules
// and the native Rust baselines below.
include!("../data/rust/common/fibo.rs");
include!("../data/rust/common/fill_sort_sum.rs");

pub fn fibo_orig(n: i32) -> i32 {
if n <= 1 {
n
} else {
let mut a: i32 = 0;
let mut b: i32 = 1;
for _ in 2..=n {
let tmp = a.wrapping_add(b);
a = b;
b = tmp;
}
b
}
fibo_impl(n)
}

/// Native Rust baseline for the memory-intensive fill+sort+sum benchmark.
///
/// Uses a stack-allocated array with direct indexing (no bounds checks in
/// release mode). This is the "best case" that the transpiled Wasm version
/// is compared against.
pub fn mem_fill_sort_sum_orig(n: i32, seed: i32) -> i32 {
let mut buf = [0i32; 1024];
fill_sort_sum_impl(&mut buf, n, seed)
}