Skip to content

Commit 4899537

Browse files
authored
bench: add more WASI benchmarks (#5309)
* bench: add more WASI benchmarks This follows up on #5274 to add several more scenarios with which to benchmark WASI performance: - `open-file.wat`: opens and closes a file - `read-file.wat`: opens a file, reads 4K bytes from it, then closes it - `read-dir.wat`: reads a directory's entries Each benchmark is hand-crafted WAT to more clearly control what WASI calls are made. As with #5274, these modules' sole entry point takes a parameter indicating the number of iterations to run in order to use `criterion`'s `iter_custom` feature. * fix: reduce expected size of directory entries
1 parent d0d3245 commit 4899537

File tree

5 files changed

+189
-1
lines changed

5 files changed

+189
-1
lines changed

benches/wasi.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
//! Measure some common WASI call scenarios.
22
33
use criterion::{criterion_group, criterion_main, Criterion};
4-
use std::time::Instant;
4+
use std::{fs::File, path::Path, time::Instant};
55
use wasmtime::{Engine, Linker, Module, Store, TypedFunc};
66
use wasmtime_wasi::{sync::WasiCtxBuilder, WasiCtx};
77

88
criterion_group!(benches, bench_wasi);
99
criterion_main!(benches);
1010

1111
fn bench_wasi(c: &mut Criterion) {
12+
let _ = env_logger::try_init();
13+
14+
// Build a zero-filled test file if it does not yet exist.
15+
let test_file = Path::new("benches/wasi/test.bin");
16+
if !test_file.is_file() {
17+
let file = File::create(test_file).unwrap();
18+
file.set_len(4096).unwrap();
19+
}
20+
1221
// Benchmark each `*.wat` file in the `wasi` directory.
1322
for file in std::fs::read_dir("benches/wasi").unwrap() {
1423
let path = file.unwrap().path();
@@ -67,5 +76,11 @@ fn wasi_context() -> WasiCtx {
6776
"--flag4".to_string(),
6877
])
6978
.unwrap()
79+
.preopened_dir(
80+
wasmtime_wasi::Dir::open_ambient_dir("benches/wasi", wasmtime_wasi::ambient_authority())
81+
.unwrap(),
82+
"/",
83+
)
84+
.unwrap()
7085
.build()
7186
}

benches/wasi/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test.bin

benches/wasi/open-file.wat

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
;; Repeatedly open and close `test.bin`.
2+
(module
3+
(import "wasi_snapshot_preview1" "path_open"
4+
(func $__wasi_path_open (param i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i32)))
5+
(import "wasi_snapshot_preview1" "fd_read"
6+
(func $__wasi_fd_read (param i32 i32 i32 i32) (result i32)))
7+
(import "wasi_snapshot_preview1" "fd_close"
8+
(func $__wasi_fd_close (param i32) (result i32)))
9+
(func (export "run") (param $iters i64) (result i64)
10+
(local $i i64)
11+
(local.set $i (i64.const 0))
12+
(loop $cont
13+
;; Open the file `test.bin` under the same directory as this WAT
14+
;; file; this assumes some prior set up of the preopens in
15+
;; `wasi.rs`. See https://github.com/WebAssembly/WASI/blob/d8da230b/phases/snapshot/witx/wasi_snapshot_preview1.witx#L346.
16+
(call $__wasi_path_open
17+
;; The fd of the preopen under which to search for the file;
18+
;; the first three are the `std*` ones.
19+
(i32.const 3)
20+
;; The lookup flags (i.e., whether to follow symlinks).
21+
(i32.const 0)
22+
;; The path to the file under the initial fd.
23+
(i32.const 0)
24+
(i32.const 8)
25+
;; The open flags; in this case we will only attempt to read but
26+
;; this may attempt to create the file if it does not exist, see
27+
;; https://github.com/WebAssembly/WASI/blob/d8da230b/phases/snapshot/witxtypenames.witx#L444).
28+
(i32.const 0)
29+
;; The base rights and the inheriting rights: here we only set
30+
;; the bits for the FD_READ and FD_READDIR capabilities.
31+
(i64.const 0x2002)
32+
(i64.const 0x2002)
33+
;; The file descriptor flags (e.g., whether to append, sync,
34+
;; etc.); see https://github.com/WebAssembly/WASI/blob/d8da230b/phases/snapshot/witx/typenames.witx#L385
35+
(i32.const 0)
36+
;; The address at which to store the opened fd (if the call
37+
;; succeeds)
38+
(i32.const 16))
39+
(if (then unreachable))
40+
41+
;; Close the open file handle we stored at offset 16.
42+
(call $__wasi_fd_close (i32.load (i32.const 16)))
43+
(if (then unreachable))
44+
45+
;; Continue looping until $i reaches $iters.
46+
(local.set $i (i64.add (local.get $i) (i64.const 1)))
47+
(br_if $cont (i64.lt_u (local.get $i) (local.get $iters)))
48+
)
49+
(local.get $i)
50+
)
51+
(data (i32.const 0) "test.bin")
52+
(memory (export "memory") 1)
53+
)

benches/wasi/read-dir.wat

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
;; Read the directory entries of the preopened directory.
2+
(module
3+
(import "wasi_snapshot_preview1" "fd_readdir"
4+
(func $__wasi_fd_readdir (param i32 i32 i32 i64 i32) (result i32)))
5+
(func (export "run") (param $iters i64) (result i64)
6+
(local $i i64)
7+
(local.set $i (i64.const 0))
8+
9+
(if (i32.ne (i32.load (i32.const 0)) (i32.const 0))
10+
(then unreachable))
11+
12+
(loop $cont
13+
;; Read the file into the sole iovec buffer.
14+
(call $__wasi_fd_readdir
15+
;; The fd of the preopened directory; the first three are the
16+
;; `std*` ones.
17+
(i32.const 3)
18+
;; The buffer address at which to store the entries and the
19+
;; length of the buffer.
20+
(i32.const 16)
21+
(i32.const 4096)
22+
;; The location at which to start reading entries in the
23+
;; directory; here we start at the first entry.
24+
(i64.const 0)
25+
;; The address at which to store the number of bytes read.
26+
(i32.const 8))
27+
(drop)
28+
29+
;; Check that we indeed read at least 380 bytes of directory
30+
;; entries.
31+
(if (i32.lt_u (i32.load (i32.const 8)) (i32.const 300))
32+
(then unreachable))
33+
34+
;; Continue looping until $i reaches $iters.
35+
(local.set $i (i64.add (local.get $i) (i64.const 1)))
36+
(br_if $cont (i64.lt_u (local.get $i) (local.get $iters)))
37+
)
38+
(local.get $i)
39+
)
40+
(memory (export "memory") 1)
41+
)

benches/wasi/read-file.wat

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
;; Repeatedly read the contents of `test.bin`.
2+
(module
3+
(import "wasi_snapshot_preview1" "path_open"
4+
(func $__wasi_path_open (param i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i32)))
5+
(import "wasi_snapshot_preview1" "fd_read"
6+
(func $__wasi_fd_read (param i32 i32 i32 i32) (result i32)))
7+
(import "wasi_snapshot_preview1" "fd_close"
8+
(func $__wasi_fd_close (param i32) (result i32)))
9+
(func (export "run") (param $iters i64) (result i64)
10+
(local $i i64)
11+
(local.set $i (i64.const 0))
12+
13+
;; Set up the iovec list; the memory usage for this module should be:
14+
;; - offset 0 => file name
15+
;; - offset 16 => the opened file descriptor
16+
;; - offset 24 => the number of read bytes
17+
;; - offset 32 => the iovec list
18+
;; - offset 48 => the first (and only) iovec buffer
19+
(i32.store (i32.const 32) (i32.const 48))
20+
(i32.store (i32.const 36) (i32.const 4096))
21+
22+
(loop $cont
23+
;; Open the file `test.bin` under the same directory as this WAT
24+
;; file; this assumes some prior set up of the preopens in
25+
;; `wasi.rs`. See https://github.com/WebAssembly/WASI/blob/d8da230b/phases/snapshot/witx/wasi_snapshot_preview1.witx#L346.
26+
(call $__wasi_path_open
27+
;; The fd of the preopen under which to search for the file;
28+
;; the first three are the `std*` ones.
29+
(i32.const 3)
30+
;; The lookup flags (i.e., whether to follow symlinks).
31+
(i32.const 0)
32+
;; The path to the file under the initial fd.
33+
(i32.const 0)
34+
(i32.const 8)
35+
;; The open flags; in this case we will only attempt to read but
36+
;; this may attempt to create the file if it does not exist, see
37+
;; https://github.com/WebAssembly/WASI/blob/d8da230b/phases/snapshot/witxtypenames.witx#L444).
38+
(i32.const 0)
39+
;; The base rights and the inheriting rights: here we only set
40+
;; the bits for the FD_READ and FD_READDIR capabilities.
41+
(i64.const 0x2002)
42+
(i64.const 0x2002)
43+
;; The file descriptor flags (e.g., whether to append, sync,
44+
;; etc.); see https://github.com/WebAssembly/WASI/blob/d8da230b/phases/snapshot/witx/typenames.witx#L385
45+
(i32.const 0)
46+
;; The address at which to store the opened fd (if the call
47+
;; succeeds)
48+
(i32.const 16))
49+
(if (then unreachable))
50+
51+
;; Read the file into the sole iovec buffer.
52+
(call $__wasi_fd_read
53+
;; The now-open fd stored at offset 16.
54+
(i32.load (i32.const 16))
55+
;; The address and size of the list of iovecs; here we only use
56+
;; a list of a single iovec set up outside the loop.
57+
(i32.const 32)
58+
(i32.const 1)
59+
;; The address at which to store the number of bytes read.
60+
(i32.const 24))
61+
(if (then unreachable))
62+
;; Check that we indeed read 4096 bytes.
63+
(if (i32.ne (i32.load (i32.const 24)) (i32.const 4096))
64+
(then unreachable))
65+
66+
;; Close the open file handle we stored at offset 16.
67+
(call $__wasi_fd_close (i32.load (i32.const 16)))
68+
(if (then unreachable))
69+
70+
;; Continue looping until $i reaches $iters.
71+
(local.set $i (i64.add (local.get $i) (i64.const 1)))
72+
(br_if $cont (i64.lt_u (local.get $i) (local.get $iters)))
73+
)
74+
(local.get $i)
75+
)
76+
(data (i32.const 0) "test.bin")
77+
(memory (export "memory") 1)
78+
)

0 commit comments

Comments
 (0)