Compare commits

..

4 Commits

Author SHA1 Message Date
zach
3300fed506 chore: fmt 2025-06-26 13:35:48 -07:00
zach
b026d30865 chore: clippy 2025-06-26 13:34:04 -07:00
zach
e8d0397754 test(kernel): add block re-use quickcheck test 2025-06-26 13:26:50 -07:00
zach
39685a9038 cleanup(kernel): improve re-use of freed blocks 2025-06-25 10:32:29 -07:00
6 changed files with 66 additions and 21 deletions

View File

@@ -13,7 +13,7 @@ description = "Traits to make Rust types usable with Extism"
anyhow = "1.0.75"
base64 = "~0.22"
bytemuck = {version = "1.14.0", optional = true }
prost = { version = "0.14.1", optional = true }
prost = { version = "0.13.1", optional = true }
protobuf = { version = "3.2.0", optional = true }
rmp-serde = { version = "1.1.2", optional = true }
serde = "1.0.186"

View File

@@ -263,24 +263,24 @@ impl MemoryRoot {
let mem_left = self_length - self_position - core::mem::size_of::<MemoryRoot>() as u64;
let length_with_block = length + core::mem::size_of::<MemoryBlock>() as u64;
// If the current position is large enough to hold the length of the block being
// allocated then check for existing free blocks that can be re-used before
// growing memory
if length_with_block <= self_position {
let b = self.find_free_block(length, self_position);
// If there's a free block then re-use it
if let Some(b) = b {
b.used = length as usize;
b.status
.store(MemoryStatus::Active as u8, Ordering::Release);
return Some(b);
}
}
// When the allocation is larger than the number of bytes available
// we will need to try to grow the memory
if length_with_block >= mem_left {
// If the current position is large enough to hold the length of the block being
// allocated then check for existing free blocks that can be re-used before
// growing memory
if length_with_block <= self_position {
let b = self.find_free_block(length, self_position);
// If there's a free block then re-use it
if let Some(b) = b {
b.used = length as usize;
b.status
.store(MemoryStatus::Active as u8, Ordering::Release);
return Some(b);
}
}
// Calculate the number of pages needed to cover the remaining bytes
let npages = num_pages(length_with_block - mem_left);
let x = core::arch::wasm32::memory_grow(0, npages);

View File

@@ -112,8 +112,7 @@ let mut plugin = Plugin::new(&manifest, [], true);
let res = plugin.call::<&str, &str>("count_vowels", "Yellow, world!").unwrap();
println!("{}", res);
# => {"count": 3, "total": 3, "vowels": "aeiouAEIOU"}
let manifest = Manifest::new([url]).with_config_key("vowels", "aeiouyAEIOUY");
let mut plugin = Plugin::new(&manifest, [], true).unwrap();
let mut plugin = Plugin::new(&manifest, [], true).with_config_key("vowels", "aeiouyAEIOUY");
let res = plugin.call::<&str, &str>("count_vowels", "Yellow, world!").unwrap();
println!("{}", res);
# => {"count": 4, "total": 4, "vowels": "aeiouyAEIOUY"}

Binary file not shown.

View File

@@ -225,6 +225,26 @@ fn test_kernel_allocations() {
extism_free(&mut store, instance, q);
}
#[test]
fn test_kernel_page_allocations() {
let (mut store, mut instance) = init_kernel_test();
let instance = &mut instance;
let a = extism_alloc(&mut store, instance, 65500 * 4);
let a_size = extism_length(&mut store, instance, a);
let b = extism_alloc(&mut store, instance, 65539);
extism_free(&mut store, instance, a);
let c = extism_alloc(&mut store, instance, 65500 * 2);
let c_size = extism_length(&mut store, instance, c);
let d = extism_alloc(&mut store, instance, 65500);
assert_eq!(a + (a_size - c_size), c);
assert!(c < b);
assert!(d < b);
}
#[test]
fn test_kernel_error() {
let (mut store, mut instance) = init_kernel_test();
@@ -436,3 +456,31 @@ quickcheck! {
true
}
}
quickcheck! {
fn check_block_reuse(allocs: Vec<u16>) -> bool {
let (mut store, mut instance) = init_kernel_test();
let instance = &mut instance;
let init = extism_alloc(&mut store, instance, allocs.iter().map(|x| *x as u64).sum::<u64>() + allocs.len() as u64 * 64);
let bounds = init + extism_length(&mut store, instance, init);
extism_free(&mut store, instance, init);
for a in allocs {
let ptr = extism_alloc(&mut store, instance, a as u64);
if ptr == 0 {
continue
}
if extism_length(&mut store, instance, ptr) != a as u64 {
return false
}
extism_free(&mut store, instance , ptr);
if ptr > bounds {
println!("ptr={ptr}, bounds={bounds}");
return false
}
}
true
}
}

View File

@@ -133,9 +133,7 @@ fn it_works() {
.unwrap();
let native_avg: std::time::Duration = native_sum / native_num_tests as u32;
println!(
"native function call (avg, N = {native_num_tests}): {native_avg:?}"
);
println!("native function call (avg, N = {native_num_tests}): {native_avg:?}");
let num_tests = test_times.len();
let sum: std::time::Duration = test_times