Skip to content

Commit c2e6cdd

Browse files
committed
Add FunctionCall serialization benchmarks
and a c+rust sample workload benchmark Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 158df62 commit c2e6cdd

File tree

3 files changed

+112
-2
lines changed

3 files changed

+112
-2
lines changed

src/hyperlight_host/benches/benchmarks.rs

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ limitations under the License.
1515
*/
1616

1717
use criterion::{Criterion, criterion_group, criterion_main};
18+
use hyperlight_common::flatbuffer_wrappers::function_call::{FunctionCall, FunctionCallType};
19+
use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
1820
use hyperlight_host::GuestBinary;
1921
use hyperlight_host::sandbox::{MultiUseSandbox, SandboxConfiguration, UninitializedSandbox};
20-
use hyperlight_testing::simple_guest_as_string;
22+
use hyperlight_testing::{c_simple_guest_as_string, simple_guest_as_string};
2123

2224
fn create_uninit_sandbox() -> UninitializedSandbox {
2325
let path = simple_guest_as_string().unwrap();
@@ -133,9 +135,85 @@ fn sandbox_benchmark(c: &mut Criterion) {
133135
group.finish();
134136
}
135137

138+
fn function_call_serialization_benchmark(c: &mut Criterion) {
139+
let mut group = c.benchmark_group("function_call_serialization");
140+
141+
let function_call = FunctionCall::new(
142+
"TestFunction".to_string(),
143+
Some(vec![
144+
ParameterValue::VecBytes(vec![1; 10 * 1024 * 1024]),
145+
ParameterValue::String(String::from_utf8(vec![2; 10 * 1024 * 1024]).unwrap()),
146+
ParameterValue::Int(42),
147+
ParameterValue::UInt(100),
148+
ParameterValue::Long(1000),
149+
ParameterValue::ULong(2000),
150+
ParameterValue::Float(521521.53),
151+
ParameterValue::Double(432.53),
152+
ParameterValue::Bool(true),
153+
ParameterValue::VecBytes(vec![1; 10 * 1024 * 1024]),
154+
ParameterValue::String(String::from_utf8(vec![2; 10 * 1024 * 1024]).unwrap()),
155+
]),
156+
FunctionCallType::Guest,
157+
ReturnType::Int,
158+
);
159+
160+
let serialized_bytes: Vec<u8> = function_call.clone().try_into().unwrap();
161+
162+
group.bench_function("serialize_function_call", |b| {
163+
b.iter_with_setup(
164+
|| function_call.clone(),
165+
|fc| {
166+
let _serialized: Vec<u8> = fc.try_into().unwrap();
167+
},
168+
);
169+
});
170+
171+
group.bench_function("deserialize_function_call", |b| {
172+
b.iter(|| {
173+
let _deserialized: FunctionCall = serialized_bytes.as_slice().try_into().unwrap();
174+
});
175+
});
176+
177+
group.finish();
178+
}
179+
180+
#[allow(clippy::disallowed_macros)]
181+
fn sample_workloads_benchmark(c: &mut Criterion) {
182+
let mut group = c.benchmark_group("sample_workloads");
183+
184+
fn bench_24k_in_8k_out(b: &mut criterion::Bencher, guest_path: String) {
185+
let mut cfg = SandboxConfiguration::default();
186+
cfg.set_input_data_size(25 * 1024);
187+
188+
let mut sandbox = UninitializedSandbox::new(GuestBinary::FilePath(guest_path), Some(cfg))
189+
.unwrap()
190+
.evolve()
191+
.unwrap();
192+
193+
b.iter_with_setup(
194+
|| vec![1; 24 * 1024],
195+
|input| {
196+
let ret: Vec<u8> = sandbox.call("24K_in_8K_out", (input,)).unwrap();
197+
assert_eq!(ret.len(), 8 * 1024, "Expected output length to be 8K");
198+
std::hint::black_box(ret);
199+
},
200+
);
201+
}
202+
203+
group.bench_function("24K_in_8K_out_c", |b| {
204+
bench_24k_in_8k_out(b, c_simple_guest_as_string().unwrap());
205+
});
206+
207+
group.bench_function("24K_in_8K_out_rust", |b| {
208+
bench_24k_in_8k_out(b, simple_guest_as_string().unwrap());
209+
});
210+
211+
group.finish();
212+
}
213+
136214
criterion_group! {
137215
name = benches;
138216
config = Criterion::default();
139-
targets = guest_call_benchmark, sandbox_benchmark, guest_call_benchmark_large_param
217+
targets = guest_call_benchmark, sandbox_benchmark, guest_call_benchmark_large_param, function_call_serialization_benchmark, sample_workloads_benchmark
140218
}
141219
criterion_main!(benches);

src/tests/c_guests/c_simpleguest/main.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "stdint.h"
55
#include "string.h"
66
#include "stdlib.h"
7+
#include "assert.h"
78
// Included from hyperlight_guest_bin/third_party/printf
89
#include "printf.h"
910

@@ -232,6 +233,12 @@ int log_message(const char *message, int64_t level) {
232233
return -1;
233234
}
234235

236+
hl_Vec *twenty_four_k_in_eight_k_out(const hl_FunctionCall* params) {
237+
hl_Vec input = params->parameters[0].value.VecBytes;
238+
assert(input.len == 24 * 1024);
239+
return hl_flatbuffer_result_from_Bytes(input.data, 8 * 1024);
240+
}
241+
235242
HYPERLIGHT_WRAP_FUNCTION(echo, String, 1, String)
236243
// HYPERLIGHT_WRAP_FUNCTION(set_byte_array_to_zero, 1, VecBytes) is not valid for functions that return VecBytes
237244
HYPERLIGHT_WRAP_FUNCTION(print_output, Int, 1, String)
@@ -260,6 +267,7 @@ HYPERLIGHT_WRAP_FUNCTION(guest_abort_with_msg, Int, 2, Int, String)
260267
HYPERLIGHT_WRAP_FUNCTION(guest_abort_with_code, Int, 1, Int)
261268
HYPERLIGHT_WRAP_FUNCTION(execute_on_stack, Int, 0)
262269
HYPERLIGHT_WRAP_FUNCTION(log_message, Int, 2, String, Long)
270+
// HYPERLIGHT_WRAP_FUNCTION(twenty_four_k_in_eight_k_out, VecBytes, 1, VecBytes) is not valid for functions that return VecBytes
263271

264272
void hyperlight_main(void)
265273
{
@@ -295,6 +303,9 @@ void hyperlight_main(void)
295303
HYPERLIGHT_REGISTER_FUNCTION("GuestAbortWithMessage", guest_abort_with_msg);
296304
HYPERLIGHT_REGISTER_FUNCTION("ExecuteOnStack", execute_on_stack);
297305
HYPERLIGHT_REGISTER_FUNCTION("LogMessage", log_message);
306+
// HYPERLIGHT_REGISTER_FUNCTION macro does not work for functions that return VecBytes,
307+
// so we use hl_register_function_definition directly
308+
hl_register_function_definition("24K_in_8K_out", twenty_four_k_in_eight_k_out, 1, (hl_ParameterType[]){hl_ParameterType_VecBytes}, hl_ReturnType_VecBytes);
298309
}
299310

300311
// This dispatch function is only used when the host dispatches a guest function

src/tests/rust_guests/simpleguest/src/main.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,19 @@ fn add_to_static_and_fail(_: &FunctionCall) -> Result<Vec<u8>> {
725725
))
726726
}
727727

728+
#[hyperlight_guest_tracing::trace_function]
729+
fn twenty_four_k_in_eight_k_out(function_call: &FunctionCall) -> Result<Vec<u8>> {
730+
if let ParameterValue::VecBytes(input) = &function_call.parameters.as_ref().unwrap()[0] {
731+
assert!(input.len() == 24 * 1024, "Input must be 24K bytes");
732+
Ok(get_flatbuffer_result(&input[..8 * 1024]))
733+
} else {
734+
Err(HyperlightGuestError::new(
735+
ErrorCode::GuestFunctionParameterTypeMismatch,
736+
"Invalid parameters passed to 24K_in_8K_out".to_string(),
737+
))
738+
}
739+
}
740+
728741
#[hyperlight_guest_tracing::trace_function]
729742
fn violate_seccomp_filters(function_call: &FunctionCall) -> Result<Vec<u8>> {
730743
if function_call.parameters.is_none() {
@@ -901,6 +914,14 @@ fn exec_mapped_buffer(function_call: &FunctionCall) -> Result<Vec<u8>> {
901914
#[no_mangle]
902915
#[hyperlight_guest_tracing::trace_function]
903916
pub extern "C" fn hyperlight_main() {
917+
let twenty_four_k_in_def = GuestFunctionDefinition::new(
918+
"24K_in_8K_out".to_string(),
919+
Vec::from(&[ParameterType::VecBytes]),
920+
ReturnType::VecBytes,
921+
twenty_four_k_in_eight_k_out as usize,
922+
);
923+
register_function(twenty_four_k_in_def);
924+
904925
let read_from_user_memory_def = GuestFunctionDefinition::new(
905926
"ReadFromUserMemory".to_string(),
906927
Vec::from(&[ParameterType::ULong, ParameterType::VecBytes]),

0 commit comments

Comments
 (0)