diff --git a/.github/workflows/benchmark-pr.yml b/.github/workflows/benchmark-pr.yml
index 9129a73d4..ed111c592 100644
--- a/.github/workflows/benchmark-pr.yml
+++ b/.github/workflows/benchmark-pr.yml
@@ -41,12 +41,14 @@ jobs:
benchmark:
runs-on: [self-hosted, bench]
# Skip unless: push to main, workflow_dispatch, or "/bench" comment on a PR
+ # (but not "/bench-suite", which runs benchmark_suite below)
if: >-
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
startsWith(github.event.comment.body, '/bench') &&
+ !startsWith(github.event.comment.body, '/bench-suite') &&
contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association))
steps:
- name: React to comment
@@ -812,3 +814,130 @@ jobs:
body
});
}
+
+ benchmark_suite:
+ runs-on: [self-hosted, bench]
+ # Triggered by "/bench-suite [prog ...]" PR comments.
+ # Programs default to the full suite; pass names to restrict.
+ if: >-
+ github.event_name == 'issue_comment' &&
+ github.event.issue.pull_request &&
+ startsWith(github.event.comment.body, '/bench-suite') &&
+ contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
+ steps:
+ - name: React to comment
+ uses: actions/github-script@v7
+ with:
+ script: |
+ await github.rest.reactions.createForIssueComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: context.payload.comment.id,
+ content: 'eyes'
+ });
+
+ - name: Get PR head ref
+ id: pr-ref
+ env:
+ GH_TOKEN: ${{ github.token }}
+ PR_NUM: ${{ github.event.issue.number }}
+ run: |
+ SHA=$(gh pr view "$PR_NUM" --repo "$GITHUB_REPOSITORY" --json headRefOid -q .headRefOid)
+ echo "sha=$SHA" >> "$GITHUB_OUTPUT"
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ steps.pr-ref.outputs.sha }}
+
+ - name: Parse program args
+ id: args
+ env:
+ COMMENT_BODY: ${{ github.event.comment.body }}
+ run: |
+ FIRST_LINE=$(printf '%s' "$COMMENT_BODY" | head -n 1 | tr -d '\r')
+ if ! echo "$FIRST_LINE" | grep -qE '^/bench-suite($|[[:space:]])'; then
+ echo "::error::Invalid command: '$FIRST_LINE'"
+ exit 1
+ fi
+ REST=$(echo "$FIRST_LINE" | sed -n 's|^/bench-suite[[:space:]]*\(.*\)|\1|p')
+ FLAGS=""
+ if [ -n "$REST" ]; then
+ for p in $REST; do
+ case "$p" in
+ fib_iterative|keccak|modular_exp|bitwise_ops|matrix_multiply)
+ FLAGS="$FLAGS --program $p"
+ ;;
+ *)
+ echo "::error::Unknown program '$p' (allowed: fib_iterative, keccak, modular_exp, bitwise_ops, matrix_multiply)"
+ exit 1
+ ;;
+ esac
+ done
+ fi
+ echo "flags=$FLAGS" >> "$GITHUB_OUTPUT"
+
+ - name: Add cargo to PATH
+ run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
+
+ - name: Compile fib_iterative ELFs
+ run: |
+ mkdir -p executor/program_artifacts/asm
+ for size in 500k 1M 2M; do
+ SRC="executor/programs/asm/fib_iterative_${size}.s"
+ OUT="executor/program_artifacts/asm/fib_iterative_${size}.elf"
+ if [ ! -f "$OUT" ] && [ -f "$SRC" ]; then
+ clang --target=riscv64 -march=rv64im -fuse-ld=lld -nostdlib -Wl,-e,main \
+ "$SRC" -o "$OUT"
+ fi
+ done
+
+ - name: Run profile suite
+ env:
+ FLAGS: ${{ steps.args.outputs.flags }}
+ run: |
+ set -o pipefail
+ bash scripts/profile_suite.sh $FLAGS 2>&1 | tee /tmp/suite_output.txt
+
+ - name: Package artifacts
+ if: always()
+ run: |
+ mkdir -p /tmp/suite_artifact
+ [ -f /tmp/suite_output.txt ] && cp /tmp/suite_output.txt /tmp/suite_artifact/
+ [ -d /tmp/bench_heap_profile ] && cp -r /tmp/bench_heap_profile /tmp/suite_artifact/
+ [ -d /tmp/bench_timing_profile ] && cp -r /tmp/bench_timing_profile /tmp/suite_artifact/
+
+ - name: Upload artifact
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: profile-suite-${{ steps.pr-ref.outputs.sha }}
+ path: /tmp/suite_artifact/
+ retention-days: 30
+
+ - name: Post PR comment
+ if: success()
+ uses: actions/github-script@v7
+ env:
+ ARTIFACT_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ with:
+ script: |
+ const fs = require('fs');
+ let out = fs.readFileSync('/tmp/suite_output.txt', 'utf8');
+ out = out.replace(/\x1b\[[0-9;]*m/g, '');
+ const LIMIT = 58000;
+ const truncated = out.length > LIMIT;
+ const body = truncated ? out.slice(0, LIMIT) : out;
+ const artifactUrl = process.env.ARTIFACT_URL;
+ let comment = `## Profile suite\n\n\`\`\`text\n${body}\n\`\`\`\n`;
+ if (truncated) {
+ comment += `\n> Output truncated. Full output in [workflow artifacts](${artifactUrl}).\n`;
+ } else {
+ comment += `\nFull artifacts in [workflow run](${artifactUrl}).\n`;
+ }
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ body: comment,
+ });
diff --git a/executor/programs/bench/bitwise_ops/.cargo/config.toml b/executor/programs/bench/bitwise_ops/.cargo/config.toml
index debd9f441..ca99a3f45 100644
--- a/executor/programs/bench/bitwise_ops/.cargo/config.toml
+++ b/executor/programs/bench/bitwise_ops/.cargo/config.toml
@@ -1,5 +1,5 @@
[target.riscv64im-lambda-vm-elf]
rustflags = [
- "-C", "link-arg=-e",
- "-C", "link-arg=main"
+ "--cfg", "getrandom_backend=\"custom\"",
+ "-C", "passes=lower-atomic"
]
diff --git a/executor/programs/bench/bitwise_ops/Cargo.lock b/executor/programs/bench/bitwise_ops/Cargo.lock
index 5a0b821ed..b295da50b 100644
--- a/executor/programs/bench/bitwise_ops/Cargo.lock
+++ b/executor/programs/bench/bitwise_ops/Cargo.lock
@@ -2,6 +2,330 @@
# It is not intended for manual editing.
version = 4
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
[[package]]
name = "bitwise_ops"
version = "0.1.0"
+dependencies = [
+ "lambda-vm-syscalls",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "const-default"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa"
+
+[[package]]
+name = "critical-section"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
+
+[[package]]
+name = "embedded-alloc"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd"
+dependencies = [
+ "const-default",
+ "critical-section",
+ "linked_list_allocator",
+ "rlsf",
+]
+
+[[package]]
+name = "embedded-hal"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
+
+[[package]]
+name = "getrandom"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasip2",
+]
+
+[[package]]
+name = "lambda-vm-syscalls"
+version = "0.1.0"
+dependencies = [
+ "embedded-alloc",
+ "getrandom 0.2.17",
+ "getrandom 0.3.4",
+ "lazy_static",
+ "rand",
+ "riscv",
+ "thiserror",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "libc"
+version = "0.2.185"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
+
+[[package]]
+name = "linked_list_allocator"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "rand"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
+dependencies = [
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
+dependencies = [
+ "getrandom 0.3.4",
+]
+
+[[package]]
+name = "riscv"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25"
+dependencies = [
+ "critical-section",
+ "embedded-hal",
+ "paste",
+ "riscv-macros",
+ "riscv-pac",
+]
+
+[[package]]
+name = "riscv-macros"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "riscv-pac"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436"
+
+[[package]]
+name = "rlsf"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a"
+dependencies = [
+ "cfg-if",
+ "const-default",
+ "libc",
+ "rustversion",
+ "svgbobdoc",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "svgbobdoc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50"
+dependencies = [
+ "base64",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "unicode-width",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasip2"
+version = "1.0.2+wasi-0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
+
+[[package]]
+name = "zerocopy"
+version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
diff --git a/executor/programs/bench/bitwise_ops/Cargo.toml b/executor/programs/bench/bitwise_ops/Cargo.toml
index 0063e8ef0..671c062d9 100644
--- a/executor/programs/bench/bitwise_ops/Cargo.toml
+++ b/executor/programs/bench/bitwise_ops/Cargo.toml
@@ -6,3 +6,4 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+lambda-vm-syscalls = { path = "../../../../syscalls" }
diff --git a/executor/programs/bench/bitwise_ops/src/main.rs b/executor/programs/bench/bitwise_ops/src/main.rs
index c22e16fe6..1bf0112ab 100644
--- a/executor/programs/bench/bitwise_ops/src/main.rs
+++ b/executor/programs/bench/bitwise_ops/src/main.rs
@@ -1,14 +1,22 @@
-#![no_std]
-#![no_main]
+use lambda_vm_syscalls as syscalls;
-use core::panic::PanicInfo;
-
-#[panic_handler]
-fn panic(_info: &PanicInfo) -> ! {
- loop {}
-}
-
-const ITERATIONS: usize = 286000;
+const ITERATIONS: usize = {
+ const fn parse(s: &str) -> usize {
+ let b = s.as_bytes();
+ let mut r = 0;
+ let mut i = 0;
+ while i < b.len() {
+ assert!(b[i] >= b'0' && b[i] <= b'9');
+ r = r * 10 + (b[i] - b'0') as usize;
+ i += 1;
+ }
+ r
+ }
+ match option_env!("ITERATIONS") {
+ Some(s) => parse(s),
+ None => 286000,
+ }
+};
#[inline(never)]
fn bitwise_mix(a: u32, b: u32) -> u32 {
@@ -18,8 +26,7 @@ fn bitwise_mix(a: u32, b: u32) -> u32 {
x.wrapping_add(y).wrapping_add(z)
}
-#[unsafe(no_mangle)]
-pub fn main() -> u32 {
+pub fn main() {
let mut result = 0x12345678u32;
let mut i = 0;
@@ -30,5 +37,5 @@ pub fn main() -> u32 {
i += 1;
}
- result
+ syscalls::syscalls::commit(&result.to_le_bytes());
}
diff --git a/executor/programs/bench/keccak/src/main.rs b/executor/programs/bench/keccak/src/main.rs
index 7b180a469..71f2bad7f 100644
--- a/executor/programs/bench/keccak/src/main.rs
+++ b/executor/programs/bench/keccak/src/main.rs
@@ -1,7 +1,23 @@
use lambda_vm_syscalls as syscalls;
use tiny_keccak::Hasher;
-const ITERATIONS: usize = 1000;
+const ITERATIONS: usize = {
+ const fn parse(s: &str) -> usize {
+ let b = s.as_bytes();
+ let mut r = 0;
+ let mut i = 0;
+ while i < b.len() {
+ assert!(b[i] >= b'0' && b[i] <= b'9');
+ r = r * 10 + (b[i] - b'0') as usize;
+ i += 1;
+ }
+ r
+ }
+ match option_env!("ITERATIONS") {
+ Some(s) => parse(s),
+ None => 1000,
+ }
+};
pub fn main() {
let mut output = [0u8; 32];
diff --git a/executor/programs/bench/matrix_multiply/.cargo/config.toml b/executor/programs/bench/matrix_multiply/.cargo/config.toml
index debd9f441..ca99a3f45 100644
--- a/executor/programs/bench/matrix_multiply/.cargo/config.toml
+++ b/executor/programs/bench/matrix_multiply/.cargo/config.toml
@@ -1,5 +1,5 @@
[target.riscv64im-lambda-vm-elf]
rustflags = [
- "-C", "link-arg=-e",
- "-C", "link-arg=main"
+ "--cfg", "getrandom_backend=\"custom\"",
+ "-C", "passes=lower-atomic"
]
diff --git a/executor/programs/bench/matrix_multiply/Cargo.lock b/executor/programs/bench/matrix_multiply/Cargo.lock
index acb0bf52c..c8d6627db 100644
--- a/executor/programs/bench/matrix_multiply/Cargo.lock
+++ b/executor/programs/bench/matrix_multiply/Cargo.lock
@@ -2,6 +2,330 @@
# It is not intended for manual editing.
version = 4
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "const-default"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa"
+
+[[package]]
+name = "critical-section"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
+
+[[package]]
+name = "embedded-alloc"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd"
+dependencies = [
+ "const-default",
+ "critical-section",
+ "linked_list_allocator",
+ "rlsf",
+]
+
+[[package]]
+name = "embedded-hal"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
+
+[[package]]
+name = "getrandom"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasip2",
+]
+
+[[package]]
+name = "lambda-vm-syscalls"
+version = "0.1.0"
+dependencies = [
+ "embedded-alloc",
+ "getrandom 0.2.17",
+ "getrandom 0.3.4",
+ "lazy_static",
+ "rand",
+ "riscv",
+ "thiserror",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "libc"
+version = "0.2.185"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
+
+[[package]]
+name = "linked_list_allocator"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
+
[[package]]
name = "matrix_multiply"
version = "0.1.0"
+dependencies = [
+ "lambda-vm-syscalls",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "rand"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
+dependencies = [
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
+dependencies = [
+ "getrandom 0.3.4",
+]
+
+[[package]]
+name = "riscv"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25"
+dependencies = [
+ "critical-section",
+ "embedded-hal",
+ "paste",
+ "riscv-macros",
+ "riscv-pac",
+]
+
+[[package]]
+name = "riscv-macros"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "riscv-pac"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436"
+
+[[package]]
+name = "rlsf"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a"
+dependencies = [
+ "cfg-if",
+ "const-default",
+ "libc",
+ "rustversion",
+ "svgbobdoc",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "svgbobdoc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50"
+dependencies = [
+ "base64",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "unicode-width",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasip2"
+version = "1.0.2+wasi-0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
+
+[[package]]
+name = "zerocopy"
+version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
diff --git a/executor/programs/bench/matrix_multiply/Cargo.toml b/executor/programs/bench/matrix_multiply/Cargo.toml
index a44fff4da..ca898e450 100644
--- a/executor/programs/bench/matrix_multiply/Cargo.toml
+++ b/executor/programs/bench/matrix_multiply/Cargo.toml
@@ -6,3 +6,4 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+lambda-vm-syscalls = { path = "../../../../syscalls" }
diff --git a/executor/programs/bench/matrix_multiply/src/main.rs b/executor/programs/bench/matrix_multiply/src/main.rs
index b3309e0a9..7bc528b66 100644
--- a/executor/programs/bench/matrix_multiply/src/main.rs
+++ b/executor/programs/bench/matrix_multiply/src/main.rs
@@ -1,14 +1,24 @@
-#![no_std]
-#![no_main]
+use lambda_vm_syscalls as syscalls;
-use core::panic::PanicInfo;
-
-#[panic_handler]
-fn panic(_info: &PanicInfo) -> ! {
- loop {}
-}
-
-const SIZE: usize = 81;
+// Three SIZE×SIZE u32 matrices live on the stack (~12·SIZE² bytes).
+// SIZE ≲ 150 is safe; beyond that, expect stack overflow.
+const SIZE: usize = {
+ const fn parse(s: &str) -> usize {
+ let b = s.as_bytes();
+ let mut r = 0;
+ let mut i = 0;
+ while i < b.len() {
+ assert!(b[i] >= b'0' && b[i] <= b'9');
+ r = r * 10 + (b[i] - b'0') as usize;
+ i += 1;
+ }
+ r
+ }
+ match option_env!("SIZE") {
+ Some(s) => parse(s),
+ None => 81,
+ }
+};
#[inline(never)]
fn matrix_multiply(a: &[[u32; SIZE]; SIZE], b: &[[u32; SIZE]; SIZE], result: &mut [[u32; SIZE]; SIZE]) {
@@ -44,25 +54,20 @@ fn init_matrix(m: &mut [[u32; SIZE]; SIZE], seed: u32) {
}
}
-#[unsafe(no_mangle)]
-pub fn main() -> u32 {
+pub fn main() {
let mut a = [[0u32; SIZE]; SIZE];
let mut b = [[0u32; SIZE]; SIZE];
let mut result = [[0u32; SIZE]; SIZE];
- // Initialize matrices with pseudo-random values
init_matrix(&mut a, 12345);
init_matrix(&mut b, 67890);
-
- // Perform matrix multiplication
matrix_multiply(&a, &b, &mut result);
- // Return checksum: sum of diagonal elements
let mut checksum = 0u32;
let mut i = 0;
while i < SIZE {
checksum = checksum.wrapping_add(result[i][i]);
i += 1;
}
- checksum
+ syscalls::syscalls::commit(&checksum.to_le_bytes());
}
diff --git a/executor/programs/bench/modular_exp/.cargo/config.toml b/executor/programs/bench/modular_exp/.cargo/config.toml
index debd9f441..ca99a3f45 100644
--- a/executor/programs/bench/modular_exp/.cargo/config.toml
+++ b/executor/programs/bench/modular_exp/.cargo/config.toml
@@ -1,5 +1,5 @@
[target.riscv64im-lambda-vm-elf]
rustflags = [
- "-C", "link-arg=-e",
- "-C", "link-arg=main"
+ "--cfg", "getrandom_backend=\"custom\"",
+ "-C", "passes=lower-atomic"
]
diff --git a/executor/programs/bench/modular_exp/Cargo.lock b/executor/programs/bench/modular_exp/Cargo.lock
index e3da22ca0..623d222cd 100644
--- a/executor/programs/bench/modular_exp/Cargo.lock
+++ b/executor/programs/bench/modular_exp/Cargo.lock
@@ -2,6 +2,330 @@
# It is not intended for manual editing.
version = 4
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "const-default"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa"
+
+[[package]]
+name = "critical-section"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
+
+[[package]]
+name = "embedded-alloc"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd"
+dependencies = [
+ "const-default",
+ "critical-section",
+ "linked_list_allocator",
+ "rlsf",
+]
+
+[[package]]
+name = "embedded-hal"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
+
+[[package]]
+name = "getrandom"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasip2",
+]
+
+[[package]]
+name = "lambda-vm-syscalls"
+version = "0.1.0"
+dependencies = [
+ "embedded-alloc",
+ "getrandom 0.2.17",
+ "getrandom 0.3.4",
+ "lazy_static",
+ "rand",
+ "riscv",
+ "thiserror",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "libc"
+version = "0.2.185"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
+
+[[package]]
+name = "linked_list_allocator"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
+
[[package]]
name = "modular_exp"
version = "0.1.0"
+dependencies = [
+ "lambda-vm-syscalls",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "rand"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
+dependencies = [
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
+dependencies = [
+ "getrandom 0.3.4",
+]
+
+[[package]]
+name = "riscv"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25"
+dependencies = [
+ "critical-section",
+ "embedded-hal",
+ "paste",
+ "riscv-macros",
+ "riscv-pac",
+]
+
+[[package]]
+name = "riscv-macros"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "riscv-pac"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436"
+
+[[package]]
+name = "rlsf"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a"
+dependencies = [
+ "cfg-if",
+ "const-default",
+ "libc",
+ "rustversion",
+ "svgbobdoc",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "svgbobdoc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50"
+dependencies = [
+ "base64",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "unicode-width",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasip2"
+version = "1.0.2+wasi-0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
+
+[[package]]
+name = "zerocopy"
+version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
diff --git a/executor/programs/bench/modular_exp/Cargo.toml b/executor/programs/bench/modular_exp/Cargo.toml
index c4a7fb705..250a81e45 100644
--- a/executor/programs/bench/modular_exp/Cargo.toml
+++ b/executor/programs/bench/modular_exp/Cargo.toml
@@ -6,3 +6,4 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+lambda-vm-syscalls = { path = "../../../../syscalls" }
diff --git a/executor/programs/bench/modular_exp/src/main.rs b/executor/programs/bench/modular_exp/src/main.rs
index 0fd0fe8cc..e0057db05 100644
--- a/executor/programs/bench/modular_exp/src/main.rs
+++ b/executor/programs/bench/modular_exp/src/main.rs
@@ -1,14 +1,22 @@
-#![no_std]
-#![no_main]
-
-use core::panic::PanicInfo;
-
-#[panic_handler]
-fn panic(_info: &PanicInfo) -> ! {
- loop {}
-}
-
-const NUM_ITERATIONS: usize = 20600;
+use lambda_vm_syscalls as syscalls;
+
+const NUM_ITERATIONS: usize = {
+ const fn parse(s: &str) -> usize {
+ let b = s.as_bytes();
+ let mut r = 0;
+ let mut i = 0;
+ while i < b.len() {
+ assert!(b[i] >= b'0' && b[i] <= b'9');
+ r = r * 10 + (b[i] - b'0') as usize;
+ i += 1;
+ }
+ r
+ }
+ match option_env!("NUM_ITERATIONS") {
+ Some(s) => parse(s),
+ None => 20600,
+ }
+};
#[inline(never)]
fn mod_exp(base: u32, exp: u32, modulus: u32) -> u32 {
@@ -32,27 +40,24 @@ fn mod_exp(base: u32, exp: u32, modulus: u32) -> u32 {
result as u32
}
-#[unsafe(no_mangle)]
-pub fn main() -> u32 {
+pub fn main() {
let mut checksum = 0u32;
let mut base = 2u32;
let mut exp = 1000u32;
- let mut modulus = 1000000007u32; // Large prime
+ let mut modulus = 1000000007u32;
let mut i = 0;
while i < NUM_ITERATIONS {
let result = mod_exp(base, exp, modulus);
checksum = checksum.wrapping_add(result);
- // Vary the parameters for each iteration
base = base.wrapping_mul(3).wrapping_add(1) % 1000;
if base == 0 { base = 2; }
exp = exp.wrapping_add(7) % 10000;
if exp == 0 { exp = 1; }
- // Keep modulus as large prime for meaningful computation
i += 1;
}
- checksum
+ syscalls::syscalls::commit(&checksum.to_le_bytes());
}
diff --git a/scripts/bench_heap_profile.sh b/scripts/bench_heap_profile.sh
index d3add6782..09e22d030 100755
--- a/scripts/bench_heap_profile.sh
+++ b/scripts/bench_heap_profile.sh
@@ -2,7 +2,11 @@
# Per-phase heap profile across program sizes.
# Shows where heap grows and how each phase scales with program size.
#
-# Usage: bench_heap_profile.sh [--no-build] [--programs "500k 1M 2M 4M"]
+# Usage: bench_heap_profile.sh [--no-build] [--programs "500k 1M 2M 4M"] [--program fib_iterative]
+#
+# --program: which program to profile (default: fib_iterative)
+# fib_iterative: uses asm/ ELFs, sizes like 500k/1M/2M
+# modular_exp, bitwise_ops, matrix_multiply, keccak: uses bench/ ELFs, sizes are iteration counts
#
# Requires: instruments + jemalloc-stats features.
# Peak heap is deterministic, so 1 run per size is enough.
@@ -19,23 +23,44 @@ BOLD='\033[1m'
NC='\033[0m'
BUILD=true
-PROGRAMS="500k 1M 2M 4M"
+PROGRAM="fib_iterative"
+PROGRAMS=""
while [[ $# -gt 0 ]]; do
case $1 in
--no-build) BUILD=false; shift ;;
+ --program) PROGRAM="$2"; shift 2 ;;
--programs) PROGRAMS="$2"; shift 2 ;;
*) echo "Unknown arg: $1"; exit 1 ;;
esac
done
+case $PROGRAM in
+ fib_iterative|keccak|modular_exp|bitwise_ops|matrix_multiply) ;;
+ *) echo "Error: unknown --program '$PROGRAM'" >&2; exit 1 ;;
+esac
+
+# Set defaults and ELF directory based on program
+if [ "$PROGRAM" = "fib_iterative" ]; then
+ ELF_DIR="$ROOT_DIR/executor/program_artifacts/asm"
+ [ -z "$PROGRAMS" ] && PROGRAMS="500k 1M 2M 4M"
+else
+ ELF_DIR="$ROOT_DIR/executor/program_artifacts/bench"
+ if [ -z "$PROGRAMS" ]; then
+ echo "Error: --programs required for bench programs" >&2
+ exit 1
+ fi
+fi
+
+TMP_DIR="$TMP_DIR/$PROGRAM"
+
suffix_to_steps() {
case $1 in
160k) echo 160000 ;; 250k) echo 250000 ;; 372k) echo 372000 ;;
500k) echo 500000 ;; 1M) echo 1000000 ;; 1200k) echo 1200000 ;;
2M) echo 2000000 ;; 4M) echo 4000000 ;; 8M) echo 8000000 ;;
16M) echo 16000000 ;; 32M) echo 32000000 ;; 64M) echo 64000000 ;; 128M) echo 128000000 ;;
- *) echo "Unknown: $1" >&2; exit 1 ;;
+ *) echo "$1" ;; # bench programs: size is the iteration count
esac
}
@@ -52,10 +77,10 @@ CLI="$ROOT_DIR/target/release/cli"
PHASES="execute trace_build air pool_alloc main_commits aux_build aux_commit"
for size in $PROGRAMS; do
- ELF="$ELF_DIR/fib_iterative_${size}.elf"
+ ELF="$ELF_DIR/${PROGRAM}_${size}.elf"
[ -f "$ELF" ] || { echo "Missing: $ELF"; continue; }
steps=$(suffix_to_steps "$size")
- echo -e "${GREEN}Running fib_iterative_${size}...${NC}"
+ echo -e "${GREEN}Running ${PROGRAM}_${size}...${NC}"
STDERR="$TMP_DIR/${size}_stderr.txt"
STDOUT="$TMP_DIR/${size}_stdout.txt"
@@ -220,7 +245,7 @@ for size in $PROGRAMS; do
PEAK_PAIRS="$PEAK_PAIRS $steps_m $peak"
done
-echo "$PEAK_PAIRS" | awk '{
+echo "$PEAK_PAIRS" | awk -v prog="$PROGRAM" '{
n = NF / 2
if (n < 2) { print " (insufficient data)"; next }
for (i = 0; i < n; i++) { x[i] = $(2*i+1); y[i] = $(2*i+2) }
@@ -242,7 +267,7 @@ echo "$PEAK_PAIRS" | awk '{
if (abs >= 1000000) lbl = sprintf("%gM", abs / 1000000)
else if (abs >= 1000) lbl = sprintf("%gk", abs / 1000)
else lbl = sprintf("%g", abs)
- printf " fib_iterative_%-6s ~%.0f MB (~%.0f GB)\n", lbl, pred, pred/1024
+ printf " %-20s ~%.0f MB (~%.0f GB)\n", prog "_" lbl, pred, pred/1024
}
}'
diff --git a/scripts/bench_timing_profile.sh b/scripts/bench_timing_profile.sh
new file mode 100755
index 000000000..f767bc979
--- /dev/null
+++ b/scripts/bench_timing_profile.sh
@@ -0,0 +1,262 @@
+#!/bin/bash
+# Per-phase timing profile across program sizes.
+# Shows how each proving phase and sub-operation scales with program size.
+#
+# Usage: bench_timing_profile.sh [--no-build] [--programs "1M 2M 4M 8M"] [--program fib_iterative]
+#
+# --program: which program to profile (default: fib_iterative)
+# fib_iterative: uses asm/ ELFs, sizes like 500k/1M/2M
+# modular_exp, bitwise_ops, matrix_multiply, keccak: uses bench/ ELFs, sizes are iteration counts
+#
+# Requires: instruments feature.
+# Timing is deterministic with instruments, so 1 run per size is enough.
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
+TMP_DIR="/tmp/bench_timing_profile"
+ELF_DIR="$ROOT_DIR/executor/program_artifacts/asm"
+
+GREEN='\033[0;32m'
+BOLD='\033[1m'
+NC='\033[0m'
+
+BUILD=true
+PROGRAM="fib_iterative"
+PROGRAMS=""
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --no-build) BUILD=false; shift ;;
+ --program) PROGRAM="$2"; shift 2 ;;
+ --programs) PROGRAMS="$2"; shift 2 ;;
+ *) echo "Unknown arg: $1"; exit 1 ;;
+ esac
+done
+
+case $PROGRAM in
+ fib_iterative|keccak|modular_exp|bitwise_ops|matrix_multiply) ;;
+ *) echo "Error: unknown --program '$PROGRAM'" >&2; exit 1 ;;
+esac
+
+# Set defaults and ELF directory based on program
+if [ "$PROGRAM" = "fib_iterative" ]; then
+ ELF_DIR="$ROOT_DIR/executor/program_artifacts/asm"
+ [ -z "$PROGRAMS" ] && PROGRAMS="500k 1M 2M 4M"
+else
+ ELF_DIR="$ROOT_DIR/executor/program_artifacts/bench"
+ if [ -z "$PROGRAMS" ]; then
+ echo "Error: --programs required for bench programs" >&2
+ exit 1
+ fi
+fi
+
+TMP_DIR="$TMP_DIR/$PROGRAM"
+
+suffix_to_steps() {
+ case $1 in
+ 160k) echo 160000 ;; 250k) echo 250000 ;; 372k) echo 372000 ;;
+ 500k) echo 500000 ;; 1M) echo 1000000 ;; 1200k) echo 1200000 ;;
+ 2M) echo 2000000 ;; 4M) echo 4000000 ;; 8M) echo 8000000 ;;
+ 16M) echo 16000000 ;; 32M) echo 32000000 ;; 64M) echo 64000000 ;; 128M) echo 128000000 ;;
+ *) echo "$1" ;; # bench programs: size is the iteration count
+ esac
+}
+
+rm -rf "$TMP_DIR" && mkdir -p "$TMP_DIR"
+
+if $BUILD; then
+ echo -e "${GREEN}Building CLI with instruments...${NC}"
+ cargo build --release -p cli --features instruments \
+ --manifest-path "$ROOT_DIR/Cargo.toml" 2>&1 | tail -1
+fi
+CLI="$ROOT_DIR/target/release/cli"
+
+# Parse instruments stderr into key=value pairs.
+# Uses occurrence counting to disambiguate expand_pool_to_lde and commit (Merkle).
+parse_timing() {
+ awk '
+ BEGIN { lde_n = 0; merkle_n = 0 }
+ function secs( s) {
+ if (match($0, /[0-9]+\.[0-9]+s/)) {
+ s = substr($0, RSTART, RLENGTH - 1)
+ return s
+ }
+ return ""
+ }
+ /^ Execute / { v = secs(); if (v) print "execute=" v }
+ /^ Trace build/ { v = secs(); if (v) print "trace_build=" v }
+ /^ AIR construction/ { v = secs(); if (v) print "air=" v }
+ /^ Pre-pass/ { v = secs(); if (v) print "prepass=" v }
+ /^ Round 1 / { v = secs(); if (v) print "round1=" v }
+ /Main trace commits/ { v = secs(); if (v) print "main_commits=" v }
+ /Aux trace build/ { v = secs(); if (v) print "aux_build=" v }
+ /Aux trace commit/ { v = secs(); if (v) print "aux_commit=" v }
+ /Rounds 2/ { v = secs(); if (v) print "rounds24=" v }
+ /expand_pool_to_lde/ && !/R1 expand/ {
+ lde_n++; v = secs()
+ if (v && lde_n == 1) print "main_lde=" v
+ if (v && lde_n == 2) print "aux_lde=" v
+ }
+ /commit \(Merkle\)/ {
+ merkle_n++; v = secs()
+ if (v && merkle_n == 1) print "main_merkle=" v
+ if (v && merkle_n == 2) print "aux_merkle=" v
+ }
+ /R1 expand_pool_to_lde/ { v = secs(); if (v) print "r1_lde=" v }
+ /R2 evaluate/ { v = secs(); if (v) print "r2_evaluate=" v }
+ /R2 decompose/ { v = secs(); if (v) print "r2_decompose=" v }
+ /R2 commit_comp/ { v = secs(); if (v) print "r2_commit_comp=" v }
+ /R3 OOD/ { v = secs(); if (v) print "r3_ood=" v }
+ /R4 deep_comp/ { v = secs(); if (v) print "r4_deep_comp=" v }
+ /R4 interpolate/ { v = secs(); if (v) print "r4_interp=" v }
+ /R4 fri::commit/ { v = secs(); if (v) print "r4_fri_commit=" v }
+ /R4 queries/ { v = secs(); if (v) print "r4_queries=" v }
+ /^ Total FFT/ { v = secs(); if (v) print "total_fft=" v }
+ /^ Total Merkle/ { v = secs(); if (v) print "total_merkle=" v }
+ /^ TOTAL / { v = secs(); if (v) print "total=" v }
+ ' "$1"
+}
+
+for size in $PROGRAMS; do
+ ELF="$ELF_DIR/${PROGRAM}_${size}.elf"
+ [ -f "$ELF" ] || { echo "Missing: $ELF"; continue; }
+ steps=$(suffix_to_steps "$size")
+ echo -e "${GREEN}Running ${PROGRAM}_${size}...${NC}"
+
+ STDERR="$TMP_DIR/${size}_stderr.txt"
+ "$CLI" prove "$ELF" -o "$TMP_DIR/proof.bin" 2>"$STDERR" >/dev/null
+ rm -f "$TMP_DIR/proof.bin"
+
+ echo "steps=$steps" > "$TMP_DIR/${size}_data.txt"
+ parse_timing "$STDERR" >> "$TMP_DIR/${size}_data.txt"
+done
+
+# --- Display ---------------------------------------------------------------
+
+get_val() {
+ grep "^${2}=" "$1" 2>/dev/null | cut -d= -f2
+}
+
+print_section() {
+ local title=$1; shift
+
+ echo ""
+ echo -e " ${BOLD}${title}${NC}"
+ printf " %-30s" ""
+ for size in $PROGRAMS; do printf " %9s" "$size"; done
+ echo ""
+ printf " %-30s" ""
+ for size in $PROGRAMS; do printf " %9s" "─────────"; done
+ echo ""
+
+ for spec in "$@"; do
+ local label="${spec%%:*}"
+ local key="${spec#*:}"
+ printf " %-30s" "$label"
+ for size in $PROGRAMS; do
+ local DATA="$TMP_DIR/${size}_data.txt"
+ local val
+ val=$(get_val "$DATA" "$key")
+ if [ -n "$val" ]; then
+ printf " %8.2fs" "$val"
+ else
+ printf " %9s" "-"
+ fi
+ done
+ echo ""
+ done
+}
+
+echo ""
+echo -e "${BOLD}=== TIMING PROFILE ACROSS SIZES ===${NC}"
+
+TABLE_K="${TABLE_PARALLELISM:-default (cores/3)}"
+echo -e " TABLE_PARALLELISM=$TABLE_K"
+
+print_section "Phase (wall time)" \
+ "TOTAL:total" \
+ "Execute:execute" \
+ "Trace build:trace_build" \
+ "AIR construction:air" \
+ "Pre-pass:prepass" \
+ "Round 1:round1" \
+ "Rounds 2-4:rounds24"
+
+print_section "Round 1 breakdown (CPU sum)" \
+ "Main LDE:main_lde" \
+ "Main Merkle:main_merkle" \
+ "Aux build (wall):aux_build" \
+ "Aux LDE:aux_lde" \
+ "Aux Merkle:aux_merkle"
+
+print_section "Rounds 2-4 sub-ops (CPU sum)" \
+ "R1 LDE (reconstruct):r1_lde" \
+ "R2 decompose+extend:r2_decompose" \
+ "R2 evaluate:r2_evaluate" \
+ "R2 commit comp poly:r2_commit_comp" \
+ "R3 OOD evaluation:r3_ood" \
+ "R4 deep comp evals:r4_deep_comp" \
+ "R4 interpolate+evaluate:r4_interp" \
+ "R4 FRI commit:r4_fri_commit" \
+ "R4 queries & openings:r4_queries"
+
+print_section "Cross-round totals (CPU sum)" \
+ "Total FFT:total_fft" \
+ "Total Merkle:total_merkle"
+
+# --- Growth rate -----------------------------------------------------------
+
+echo ""
+echo -e "${BOLD}=== GROWTH RATE (per 1M steps) ===${NC}"
+echo ""
+
+for spec in \
+ "TOTAL:total" \
+ "Trace build:trace_build" \
+ "Round 1:round1" \
+ "Rounds 2-4:rounds24" \
+ "Main LDE:main_lde" \
+ "Aux LDE:aux_lde" \
+ "R1 LDE (reconstruct):r1_lde" \
+ "R2 decompose+extend:r2_decompose" \
+ "R3 OOD evaluation:r3_ood" \
+ "Total FFT:total_fft" \
+ "Total Merkle:total_merkle"
+do
+ label="${spec%%:*}"
+ key="${spec#*:}"
+
+ PAIRS=""
+ for size in $PROGRAMS; do
+ DATA="$TMP_DIR/${size}_data.txt"
+ [ -f "$DATA" ] || continue
+ steps=$(get_val "$DATA" "steps")
+ val=$(get_val "$DATA" "$key")
+ [ -z "$val" ] && continue
+ steps_m=$(awk "BEGIN {printf \"%.6f\", $steps / 1000000}")
+ PAIRS="$PAIRS $steps_m $val"
+ done
+
+ echo "$PAIRS" | awk -v label="$label" '{
+ n = NF / 2
+ if (n < 2) { printf " %-30s (insufficient data)\n", label; next }
+ for (i = 0; i < n; i++) {
+ x[i] = $(2*i+1); y[i] = $(2*i+2)
+ }
+ sx=0; sy=0; sxx=0; sxy=0
+ for (i=0;i0) ? 1 - ss_res/ss_tot : 1
+ printf " %-30s %+.2fs/M steps (base: %.2fs, R\xc2\xb2=%.3f)\n", label, b, a, r2
+ }'
+done
+
+echo ""
+echo "Raw data in $TMP_DIR/"
diff --git a/scripts/build_bench_sizes.sh b/scripts/build_bench_sizes.sh
new file mode 100755
index 000000000..203d25f76
--- /dev/null
+++ b/scripts/build_bench_sizes.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# Build a bench program at multiple sizes via env var.
+# Places ELFs in executor/program_artifacts/bench/ with size suffix.
+#
+# Usage: build_bench_sizes.sh
+# Example: build_bench_sizes.sh modular_exp NUM_ITERATIONS 5000 10000 20000
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
+BENCH_DIR="$ROOT_DIR/executor/programs/bench"
+ARTIFACTS_DIR="$ROOT_DIR/executor/program_artifacts/bench"
+TARGET_SPEC="$ROOT_DIR/executor/programs/riscv64im-lambda-vm-elf.json"
+SHARED_TARGET_DIR="$ROOT_DIR/executor/programs/target"
+
+program=$1; shift
+env_var=$1; shift
+
+if [ ! -d "$BENCH_DIR/$program" ]; then
+ echo "Error: $BENCH_DIR/$program not found" >&2
+ exit 1
+fi
+
+mkdir -p "$ARTIFACTS_DIR"
+
+for val in "$@"; do
+ echo "Building ${program} with ${env_var}=${val}..."
+
+ cd "$BENCH_DIR/$program"
+ env CARGO_TARGET_DIR="$SHARED_TARGET_DIR" "${env_var}=${val}" \
+ rustup run nightly-2026-02-01 cargo build --release \
+ --target "$TARGET_SPEC" \
+ -Z build-std=core,alloc,std,compiler_builtins,panic_abort \
+ -Z build-std-features=compiler-builtins-mem \
+ -Z json-target-spec 2>&1 | tail -1
+
+ cp "$SHARED_TARGET_DIR/riscv64im-lambda-vm-elf/release/$program" \
+ "$ARTIFACTS_DIR/${program}_${val}.elf"
+
+ echo " -> ${program}_${val}.elf"
+done
+
+echo "Done."
diff --git a/scripts/profile_suite.sh b/scripts/profile_suite.sh
new file mode 100755
index 000000000..6b135590c
--- /dev/null
+++ b/scripts/profile_suite.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+# Run heap and timing profiles on all prepared bench programs.
+# Output:
+# /tmp/bench_heap_profile//
+# /tmp/bench_timing_profile//
+#
+# Flags:
+# --no-heap, --no-timing skip either profile type
+# --program run only the given program; repeat to select several
+# (default: all programs)
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
+
+HEAP=true
+TIMING=true
+ONLY_LIST=()
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --no-heap) HEAP=false; shift ;;
+ --no-timing) TIMING=false; shift ;;
+ --program) ONLY_LIST+=("$2"); shift 2 ;;
+ *) echo "Unknown arg: $1"; exit 1 ;;
+ esac
+done
+
+# program env_var sizes
+# env_var="-" means fib_iterative (prebuilt ELFs, no build step)
+CONFIGS=(
+ "fib_iterative - 500k 1M 2M"
+ "keccak ITERATIONS 200 500 1000"
+ "modular_exp NUM_ITERATIONS 5000 10000 20000 40000"
+ "bitwise_ops ITERATIONS 50000 100000 200000 400000"
+ "matrix_multiply SIZE 20 40 60 80"
+)
+
+if [ ${#ONLY_LIST[@]} -gt 0 ]; then
+ filtered=()
+ for only in "${ONLY_LIST[@]}"; do
+ found=false
+ for config in "${CONFIGS[@]}"; do
+ read -r prog _ <<< "$config"
+ if [ "$prog" = "$only" ]; then
+ filtered+=("$config")
+ found=true
+ break
+ fi
+ done
+ if ! $found; then
+ echo "Error: unknown program '$only'" >&2
+ exit 1
+ fi
+ done
+ CONFIGS=("${filtered[@]}")
+fi
+
+GREEN='\033[0;32m'
+NC='\033[0m'
+
+FEATURES="instruments"
+$HEAP && FEATURES="jemalloc-stats,instruments"
+
+# Clear stale results so only the current run's data remains.
+$HEAP && rm -rf /tmp/bench_heap_profile
+$TIMING && rm -rf /tmp/bench_timing_profile
+
+echo -e "${GREEN}Building CLI with $FEATURES...${NC}"
+cargo build --release -p cli --features "$FEATURES" \
+ --manifest-path "$ROOT_DIR/Cargo.toml" 2>&1 | tail -1
+
+for config in "${CONFIGS[@]}"; do
+ read -r prog env_var sizes <<< "$config"
+
+ echo ""
+ echo -e "${GREEN}=== $prog ===${NC}"
+
+ if [ "$env_var" != "-" ]; then
+ bash "$SCRIPT_DIR/build_bench_sizes.sh" "$prog" "$env_var" $sizes
+ fi
+
+ if $HEAP; then
+ bash "$SCRIPT_DIR/bench_heap_profile.sh" --no-build \
+ --program "$prog" --programs "$sizes"
+ fi
+
+ if $TIMING; then
+ bash "$SCRIPT_DIR/bench_timing_profile.sh" --no-build \
+ --program "$prog" --programs "$sizes"
+ fi
+done
+
+echo ""
+echo "Results:"
+$HEAP && echo " Heap: /tmp/bench_heap_profile//"
+$TIMING && echo " Timing: /tmp/bench_timing_profile//"