mirror of
https://github.com/extism/extism.git
synced 2026-01-14 16:28:04 -05:00
See https://github.com/extism/cpp-sdk/issues/15 - Limits a call to memset in the kernel to the size of the current memory offset instead of the total size of memory. - Adds `extism_plugin_reset` to the C API and `extism::Plugin::reset` to Rust --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: zshipko <zshipko@users.noreply.github.com>
257 lines
7.5 KiB
Rust
257 lines
7.5 KiB
Rust
use criterion::{criterion_group, criterion_main, Criterion};
|
|
use extism::*;
|
|
use extism_convert::Json;
|
|
|
|
const COUNT_VOWELS: &[u8] = include_bytes!("../../wasm/code.wasm");
|
|
const REFLECT: &[u8] = include_bytes!("../../wasm/reflect.wasm");
|
|
const ECHO: &[u8] = include_bytes!("../../wasm/echo.wasm");
|
|
const CONSUME: &[u8] = include_bytes!("../../wasm/consume.wasm");
|
|
|
|
host_fn!(hello_world (a: String) -> String { Ok(a) });
|
|
|
|
pub fn basic(c: &mut Criterion) {
|
|
let mut g = c.benchmark_group("basic");
|
|
g.measurement_time(std::time::Duration::from_secs(6));
|
|
g.bench_function("basic", |b| {
|
|
let data = "a".repeat(4096);
|
|
b.iter(|| {
|
|
let mut plugin = Plugin::new(COUNT_VOWELS, [], true).unwrap();
|
|
let _: serde_json::Value = plugin.call("count_vowels", &data).unwrap();
|
|
})
|
|
});
|
|
}
|
|
|
|
pub fn create_plugin(c: &mut Criterion) {
|
|
let mut g = c.benchmark_group("create");
|
|
g.noise_threshold(1.0);
|
|
g.significance_level(0.2);
|
|
g.bench_function("create_plugin", |b| {
|
|
b.iter(|| {
|
|
let _plugin = PluginBuilder::new(COUNT_VOWELS)
|
|
.with_wasi(true)
|
|
.build()
|
|
.unwrap();
|
|
})
|
|
});
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize, PartialEq)]
|
|
struct Count {
|
|
count: u32,
|
|
}
|
|
pub fn count_vowels(c: &mut Criterion) {
|
|
let mut g = c.benchmark_group("count_vowels");
|
|
g.sample_size(500);
|
|
let mut plugin = PluginBuilder::new(COUNT_VOWELS)
|
|
.with_wasi(true)
|
|
.build()
|
|
.unwrap();
|
|
let data = "a".repeat(4096);
|
|
g.bench_function("count_vowels(4096)", |b| {
|
|
b.iter(|| {
|
|
assert_eq!(
|
|
Count { count: 4096 },
|
|
plugin
|
|
.call::<_, Json<Count>>("count_vowels", &data)
|
|
.unwrap()
|
|
.0
|
|
);
|
|
})
|
|
});
|
|
}
|
|
|
|
pub fn consume(c: &mut Criterion) {
|
|
let mut g = c.benchmark_group("consume");
|
|
g.sample_size(500);
|
|
g.noise_threshold(1.0);
|
|
g.significance_level(0.2);
|
|
let mut plugin = PluginBuilder::new(CONSUME).build().unwrap();
|
|
|
|
for (i, elements) in [
|
|
b"a".repeat(65536),
|
|
b"a".repeat(65536 * 10),
|
|
b"a".repeat(65536 * 100),
|
|
]
|
|
.iter()
|
|
.enumerate()
|
|
{
|
|
g.throughput(criterion::Throughput::Bytes(elements.len() as u64));
|
|
g.bench_with_input(
|
|
format!("consume {} bytes", 10u32.pow(i as u32) * 65536),
|
|
elements,
|
|
|b, elems| {
|
|
b.iter(|| {
|
|
assert_eq!(b"", plugin.call::<_, &[u8]>("consume", &elems).unwrap());
|
|
});
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn echo(c: &mut Criterion) {
|
|
let mut g = c.benchmark_group("echo");
|
|
g.sample_size(500);
|
|
g.noise_threshold(1.0);
|
|
g.significance_level(0.2);
|
|
let mut plugin = PluginBuilder::new(ECHO).build().unwrap();
|
|
|
|
for (i, elements) in [
|
|
b"a".repeat(65536),
|
|
b"a".repeat(65536 * 10),
|
|
b"a".repeat(65536 * 100),
|
|
]
|
|
.iter()
|
|
.enumerate()
|
|
{
|
|
g.throughput(criterion::Throughput::Bytes(elements.len() as u64));
|
|
g.bench_with_input(
|
|
format!("echo {} bytes", 10u32.pow(i as u32) * 65536),
|
|
elements,
|
|
|b, elems| {
|
|
b.iter(|| {
|
|
plugin.call::<_, &[u8]>("echo", &elems).unwrap();
|
|
});
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn reflect(c: &mut Criterion) {
|
|
let mut g = c.benchmark_group("reflect");
|
|
|
|
let mut plugin = PluginBuilder::new(REFLECT)
|
|
.with_wasi(true)
|
|
.with_function(
|
|
"host_reflect",
|
|
[PTR],
|
|
[PTR],
|
|
UserData::default(),
|
|
hello_world,
|
|
)
|
|
.build()
|
|
.unwrap();
|
|
for (i, elements) in [
|
|
b"a".repeat(65536),
|
|
b"a".repeat(65536 * 10),
|
|
b"a".repeat(65536 * 100),
|
|
b"a".repeat(65536),
|
|
]
|
|
.iter()
|
|
.enumerate()
|
|
{
|
|
g.throughput(criterion::Throughput::Bytes(elements.len() as u64));
|
|
g.bench_with_input(
|
|
format!("{i}: reflect {} bytes", elements.len()),
|
|
elements,
|
|
|b, elems| {
|
|
b.iter(|| {
|
|
assert_eq!(elems, plugin.call::<_, &[u8]>("reflect", &elems).unwrap());
|
|
// plugin.reset().unwrap();
|
|
});
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
// This is an apples-to-apples comparison of a linked wasm "reflect" function to our host "reflect"
|
|
// function.
|
|
pub fn reflect_linked(c: &mut Criterion) {
|
|
let mut g = c.benchmark_group("reflect");
|
|
g.sample_size(500);
|
|
g.noise_threshold(1.0);
|
|
g.significance_level(0.2);
|
|
let manifest = Manifest::new([
|
|
Wasm::Data {
|
|
data: br#"(module
|
|
(import "extism:host/env" "length" (func $length (param i64) (result i64)))
|
|
(import "extism:host/env" "load_u64" (func $load_u64 (param i64) (result i64)))
|
|
(import "extism:host/env" "load_u8" (func $load_u8 (param i64) (result i32)))
|
|
(import "extism:host/env" "store_u64" (func $store_u64 (param i64 i64)))
|
|
(import "extism:host/env" "store_u8" (func $store_u8 (param i64 i32)))
|
|
|
|
(func (export "host_reflect") (param $extism_offset i64) (result i64)
|
|
(local $len i64)
|
|
(local $offset i64)
|
|
(local $len64 i64)
|
|
|
|
(local.set $offset (i64.const 0))
|
|
(local.set $len (call $length (local.get $extism_offset)))
|
|
|
|
(local.set $len64 (i64.shl (i64.shr_u (local.get $len) (i64.const 16)) (i64.const 16)))
|
|
|
|
(loop $to_upper
|
|
(call $store_u64
|
|
(i64.add (local.get $extism_offset) (local.get $offset))
|
|
(call $load_u64 (i64.add (local.get $extism_offset) (local.get $offset)))
|
|
)
|
|
|
|
(local.set $offset (i64.add (local.get $offset) (i64.const 8)))
|
|
(br_if $to_upper (i64.lt_u (local.get $offset) (local.get $len64)))
|
|
)
|
|
|
|
(if (i64.ne (local.get $len64) (local.get $len)) (then
|
|
(loop $to_upper
|
|
(call $store_u8
|
|
(i64.add (local.get $extism_offset) (local.get $offset))
|
|
(call $load_u8 (i64.add (local.get $extism_offset) (local.get $offset)))
|
|
)
|
|
|
|
(local.set $offset (i64.add (i64.const 1) (local.get $offset)))
|
|
(br_if $to_upper (i64.lt_u (local.get $offset) (local.get $len)))
|
|
)
|
|
))
|
|
local.get $extism_offset
|
|
)
|
|
)"#
|
|
.to_vec(),
|
|
meta: WasmMetadata {
|
|
name: Some("extism:host/user".to_string()),
|
|
hash: None,
|
|
},
|
|
},
|
|
Wasm::Data {
|
|
data: REFLECT.to_vec(),
|
|
meta: WasmMetadata {
|
|
name: Some("main".to_string()),
|
|
hash: None,
|
|
},
|
|
},
|
|
]);
|
|
let mut plugin = PluginBuilder::new(manifest)
|
|
.with_wasi(true)
|
|
.build()
|
|
.unwrap();
|
|
|
|
for (i, elements) in [
|
|
b"a".repeat(65536),
|
|
b"a".repeat(65536 * 10),
|
|
b"a".repeat(65536 * 100),
|
|
]
|
|
.iter()
|
|
.enumerate()
|
|
{
|
|
g.throughput(criterion::Throughput::Bytes(elements.len() as u64));
|
|
g.bench_with_input(
|
|
format!("reflect_linked {} bytes", 10u32.pow(i as u32) * 65536),
|
|
elements,
|
|
|b, elems| {
|
|
b.iter(|| {
|
|
assert_eq!(elems, plugin.call::<_, &[u8]>("reflect", &elems).unwrap());
|
|
});
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
criterion_group!(
|
|
benches,
|
|
consume,
|
|
echo,
|
|
reflect,
|
|
reflect_linked,
|
|
basic,
|
|
create_plugin,
|
|
count_vowels
|
|
);
|
|
criterion_main!(benches);
|