Skip to content

Commit da29125

Browse files
committed
Add new benchmarks for varying sizes of sandboxes and guest function parameters
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent e4a661a commit da29125

File tree

1 file changed

+201
-24
lines changed

1 file changed

+201
-24
lines changed

src/hyperlight_host/benches/benchmarks.rs

Lines changed: 201 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -75,37 +75,65 @@ fn guest_call_benchmark(c: &mut Criterion) {
7575
group.finish();
7676
}
7777

78-
fn guest_call_benchmark_large_param(c: &mut Criterion) {
78+
fn guest_call_benchmark_large_params(c: &mut Criterion) {
7979
let mut group = c.benchmark_group("guest_functions_with_large_parameters");
8080
#[cfg(target_os = "windows")]
8181
group.sample_size(10); // This benchmark is very slow on Windows, so we reduce the sample size to avoid long test runs.
8282

83-
// This benchmark includes time to first clone a vector and string, so it is not a "pure' benchmark of the guest call, but it's still useful
84-
group.bench_function("guest_call_with_large_parameters", |b| {
85-
const SIZE: usize = 50 * 1024 * 1024; // 50 MB
86-
let large_vec = vec![0u8; SIZE];
87-
let large_string = unsafe { String::from_utf8_unchecked(large_vec.clone()) }; // Safety: indeed above vec is valid utf8
83+
// Helper function to create a benchmark for a specific size
84+
let create_benchmark = |group: &mut criterion::BenchmarkGroup<_>, size_mb: usize| {
85+
let benchmark_name = format!("guest_call_with_2_large_parameters_{}mb each", size_mb);
86+
group.bench_function(&benchmark_name, |b| {
87+
let size = size_mb * 1024 * 1024; // Convert MB to bytes
88+
let large_vec = vec![0u8; size];
89+
let large_string = unsafe { String::from_utf8_unchecked(large_vec.clone()) }; // Safety: indeed above vec is valid utf8
8890

89-
let mut config = SandboxConfiguration::default();
90-
config.set_input_data_size(2 * SIZE + (1024 * 1024)); // 2 * SIZE + 1 MB, to allow 1MB for the rest of the serialized function call
91-
config.set_heap_size(SIZE as u64 * 15);
91+
let mut config = SandboxConfiguration::default();
92+
config.set_input_data_size(2 * size + (1024 * 1024));
9293

93-
let sandbox = UninitializedSandbox::new(
94-
GuestBinary::FilePath(simple_guest_as_string().unwrap()),
95-
Some(config),
96-
)
97-
.unwrap();
98-
let mut sandbox = sandbox.evolve().unwrap();
94+
if size < 50 * 1024 * 1024 {
95+
config.set_heap_size(size as u64 * 16);
96+
} else {
97+
config.set_heap_size(size as u64 * 11); // Set to 1GB for larger sizes
98+
}
9999

100-
b.iter(|| {
101-
sandbox
102-
.call_guest_function_by_name::<()>(
103-
"LargeParameters",
104-
(large_vec.clone(), large_string.clone()),
105-
)
106-
.unwrap()
100+
let sandbox = UninitializedSandbox::new(
101+
GuestBinary::FilePath(simple_guest_as_string().unwrap()),
102+
Some(config),
103+
)
104+
.unwrap();
105+
let mut sandbox = sandbox.evolve().unwrap();
106+
107+
b.iter_custom(|iters| {
108+
let mut total_duration = std::time::Duration::new(0, 0);
109+
110+
for _ in 0..iters {
111+
// Clone the data (not measured)
112+
let vec_clone = large_vec.clone();
113+
let string_clone = large_string.clone();
114+
115+
// Measure only the guest function call
116+
let start = std::time::Instant::now();
117+
sandbox
118+
.call_guest_function_by_name::<()>(
119+
"LargeParameters",
120+
(vec_clone, string_clone),
121+
)
122+
.unwrap();
123+
total_duration += start.elapsed();
124+
}
125+
126+
total_duration
127+
});
107128
});
108-
});
129+
};
130+
131+
// Create benchmarks for different sizes
132+
create_benchmark(&mut group, 5); // 5MB
133+
create_benchmark(&mut group, 10); // 10MB
134+
create_benchmark(&mut group, 20); // 20MB
135+
create_benchmark(&mut group, 40); // 40MB
136+
create_benchmark(&mut group, 60); // 60MB
109137

110138
group.finish();
111139
}
@@ -138,9 +166,158 @@ fn sandbox_benchmark(c: &mut Criterion) {
138166
group.finish();
139167
}
140168

169+
fn sandbox_heap_size_benchmark(c: &mut Criterion) {
170+
let mut group = c.benchmark_group("sandbox_heap_sizes");
171+
172+
// Helper function to create sandbox with specific heap size
173+
let create_sandbox_with_heap_size = |heap_size_mb: Option<u64>| {
174+
let path = simple_guest_as_string().unwrap();
175+
let config = if let Some(size_mb) = heap_size_mb {
176+
let mut config = SandboxConfiguration::default();
177+
config.set_heap_size(size_mb * 1024 * 1024); // Convert MB to bytes
178+
Some(config)
179+
} else {
180+
None
181+
};
182+
183+
let uninit_sandbox =
184+
UninitializedSandbox::new(GuestBinary::FilePath(path), config).unwrap();
185+
uninit_sandbox.evolve().unwrap()
186+
};
187+
188+
// Benchmark sandbox creation with default heap size
189+
group.bench_function("create_sandbox_default_heap", |b| {
190+
b.iter_with_large_drop(|| create_sandbox_with_heap_size(None));
191+
});
192+
193+
// Benchmark sandbox creation with 50MB heap
194+
group.bench_function("create_sandbox_50mb_heap", |b| {
195+
b.iter_with_large_drop(|| create_sandbox_with_heap_size(Some(50)));
196+
});
197+
198+
// Benchmark sandbox creation with 100MB heap
199+
group.bench_function("create_sandbox_100mb_heap", |b| {
200+
b.iter_with_large_drop(|| create_sandbox_with_heap_size(Some(100)));
201+
});
202+
203+
// Benchmark sandbox creation with 250MB heap
204+
group.bench_function("create_sandbox_250mb_heap", |b| {
205+
b.iter_with_large_drop(|| create_sandbox_with_heap_size(Some(250)));
206+
});
207+
208+
// Benchmark sandbox creation with 500MB heap
209+
group.bench_function("create_sandbox_500mb_heap", |b| {
210+
b.iter_with_large_drop(|| create_sandbox_with_heap_size(Some(500)));
211+
});
212+
213+
// Benchmark sandbox creation with 995MB heap (close to the limit of 1GB for a Sandbox )
214+
group.bench_function("create_sandbox_995mb_heap", |b| {
215+
b.iter_with_large_drop(|| create_sandbox_with_heap_size(Some(995)));
216+
});
217+
218+
group.finish();
219+
}
220+
221+
fn guest_call_heap_size_benchmark(c: &mut Criterion) {
222+
let mut group = c.benchmark_group("guest_call_restore_heap_sizes");
223+
224+
// Helper function to create sandbox with specific heap size
225+
let create_sandbox_with_heap_size = |heap_size_mb: Option<u64>| {
226+
let path = simple_guest_as_string().unwrap();
227+
let config = if let Some(size_mb) = heap_size_mb {
228+
let mut config = SandboxConfiguration::default();
229+
config.set_heap_size(size_mb * 1024 * 1024); // Convert MB to bytes
230+
Some(config)
231+
} else {
232+
None
233+
};
234+
235+
let uninit_sandbox =
236+
UninitializedSandbox::new(GuestBinary::FilePath(path), config).unwrap();
237+
uninit_sandbox.evolve().unwrap()
238+
};
239+
240+
// Benchmark guest function call with default heap size
241+
group.bench_function("guest_call_restore_default_heap", |b| {
242+
let mut sandbox = create_sandbox_with_heap_size(None);
243+
let snapshot = sandbox.snapshot().unwrap();
244+
245+
b.iter(|| {
246+
sandbox
247+
.call_guest_function_by_name::<String>("Echo", "hello\n".to_string())
248+
.unwrap();
249+
sandbox.restore(&snapshot).unwrap();
250+
});
251+
});
252+
253+
// Benchmark guest function call with 50MB heap
254+
group.bench_function("guest_call_restore_50mb_heap", |b| {
255+
let mut sandbox = create_sandbox_with_heap_size(Some(50));
256+
let snapshot = sandbox.snapshot().unwrap();
257+
258+
b.iter(|| {
259+
sandbox
260+
.call_guest_function_by_name::<String>("Echo", "hello\n".to_string())
261+
.unwrap();
262+
sandbox.restore(&snapshot).unwrap();
263+
});
264+
});
265+
266+
// Benchmark guest function call with 100MB heap
267+
group.bench_function("guest_call_restore_100mb_heap", |b| {
268+
let mut sandbox = create_sandbox_with_heap_size(Some(100));
269+
let snapshot = sandbox.snapshot().unwrap();
270+
271+
b.iter(|| {
272+
sandbox
273+
.call_guest_function_by_name::<String>("Echo", "hello\n".to_string())
274+
.unwrap();
275+
sandbox.restore(&snapshot).unwrap();
276+
});
277+
});
278+
279+
// Benchmark guest function call with 250MB heap
280+
group.bench_function("guest_call_restore_250mb_heap", |b| {
281+
let mut sandbox = create_sandbox_with_heap_size(Some(250));
282+
let snapshot = sandbox.snapshot().unwrap();
283+
b.iter(|| {
284+
sandbox
285+
.call_guest_function_by_name::<String>("Echo", "hello\n".to_string())
286+
.unwrap();
287+
sandbox.restore(&snapshot).unwrap();
288+
});
289+
});
290+
291+
// Benchmark guest function call with 500MB heap
292+
group.bench_function("guest_call_restore_500mb_heap", |b| {
293+
let mut sandbox = create_sandbox_with_heap_size(Some(500));
294+
let snapshot = sandbox.snapshot().unwrap();
295+
b.iter(|| {
296+
sandbox
297+
.call_guest_function_by_name::<String>("Echo", "hello\n".to_string())
298+
.unwrap();
299+
sandbox.restore(&snapshot).unwrap();
300+
});
301+
});
302+
303+
// Benchmark guest function call with 995MB heap
304+
group.bench_function("guest_call_restore_995mb_heap", |b| {
305+
let mut sandbox = create_sandbox_with_heap_size(Some(995));
306+
let snapshot = sandbox.snapshot().unwrap();
307+
b.iter(|| {
308+
sandbox
309+
.call_guest_function_by_name::<String>("Echo", "hello\n".to_string())
310+
.unwrap();
311+
sandbox.restore(&snapshot).unwrap();
312+
});
313+
});
314+
315+
group.finish();
316+
}
317+
141318
criterion_group! {
142319
name = benches;
143320
config = Criterion::default();
144-
targets = guest_call_benchmark, sandbox_benchmark, guest_call_benchmark_large_param
321+
targets = guest_call_benchmark, sandbox_benchmark, sandbox_heap_size_benchmark, guest_call_benchmark_large_params, guest_call_heap_size_benchmark
145322
}
146323
criterion_main!(benches);

0 commit comments

Comments
 (0)