Skip to content

Commit 6de0d2f

Browse files
committed
Add new benchmarks for varying sizes of sandboxes and guest function parameters
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
1 parent 3b398bc commit 6de0d2f

File tree

1 file changed

+186
-24
lines changed

1 file changed

+186
-24
lines changed

src/hyperlight_host/benches/benchmarks.rs

Lines changed: 186 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -79,37 +79,65 @@ fn guest_call_benchmark(c: &mut Criterion) {
7979
group.finish();
8080
}
8181

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

87-
// 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
88-
group.bench_function("guest_call_with_large_parameters", |b| {
89-
const SIZE: usize = 50 * 1024 * 1024; // 50 MB
90-
let large_vec = vec![0u8; SIZE];
91-
let large_string = unsafe { String::from_utf8_unchecked(large_vec.clone()) }; // Safety: indeed above vec is valid utf8
87+
// Helper function to create a benchmark for a specific size
88+
let create_benchmark = |group: &mut criterion::BenchmarkGroup<_>, size_mb: usize| {
89+
let benchmark_name = format!("guest_call_with_2_large_parameters_{}mb each", size_mb);
90+
group.bench_function(&benchmark_name, |b| {
91+
let size = size_mb * 1024 * 1024; // Convert MB to bytes
92+
let large_vec = vec![0u8; size];
93+
let large_string = unsafe { String::from_utf8_unchecked(large_vec.clone()) }; // Safety: indeed above vec is valid utf8
9294

93-
let mut config = SandboxConfiguration::default();
94-
config.set_input_data_size(2 * SIZE + (1024 * 1024)); // 2 * SIZE + 1 MB, to allow 1MB for the rest of the serialized function call
95-
config.set_heap_size(SIZE as u64 * 15);
95+
let mut config = SandboxConfiguration::default();
96+
config.set_input_data_size(2 * size + (1024 * 1024));
9697

97-
let sandbox = UninitializedSandbox::new(
98-
GuestBinary::FilePath(simple_guest_as_string().unwrap()),
99-
Some(config),
100-
)
101-
.unwrap();
102-
let mut sandbox = sandbox.evolve(Noop::default()).unwrap();
98+
if size < 50 * 1024 * 1024 {
99+
config.set_heap_size(size as u64 * 16);
100+
} else {
101+
config.set_heap_size(size as u64 * 11); // Set to 1GB for larger sizes
102+
}
103103

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

114142
group.finish();
115143
}
@@ -153,9 +181,143 @@ fn sandbox_benchmark(c: &mut Criterion) {
153181
group.finish();
154182
}
155183

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

0 commit comments

Comments
 (0)