@@ -79,37 +79,65 @@ fn guest_call_benchmark(c: &mut Criterion) {
79
79
group. finish ( ) ;
80
80
}
81
81
82
- fn guest_call_benchmark_large_param ( c : & mut Criterion ) {
82
+ fn guest_call_benchmark_large_params ( c : & mut Criterion ) {
83
83
let mut group = c. benchmark_group ( "guest_functions_with_large_parameters" ) ;
84
84
#[ cfg( target_os = "windows" ) ]
85
85
group. sample_size ( 10 ) ; // This benchmark is very slow on Windows, so we reduce the sample size to avoid long test runs.
86
86
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
92
94
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 ) ) ;
96
97
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
+ }
103
103
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
+ } ) ;
111
132
} ) ;
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
113
141
114
142
group. finish ( ) ;
115
143
}
@@ -153,9 +181,143 @@ fn sandbox_benchmark(c: &mut Criterion) {
153
181
group. finish ( ) ;
154
182
}
155
183
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
+
156
318
criterion_group ! {
157
319
name = benches;
158
320
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
160
322
}
161
323
criterion_main ! ( benches) ;
0 commit comments