@@ -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+
141318criterion_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}
146323criterion_main ! ( benches) ;
0 commit comments