Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
will be extended in the future.
* MSHV: vCPU creation reads the partition's XSAVE format once. This removes
one hypercall from every restore.
* On KVM, restore zeroes the scratch pages the guest wrote since the last
restore and keeps them mapped, so its next run takes no faults on them.
Other scratch is dropped, a few runs of it per restore when it is
fragmented, so what stays resident follows what recent runs wrote. On Linux
6.7 or newer, a restore costs time in how much of scratch is in use rather
than in its size.
* On WHP, and on MSHV on x86_64, restore zeroes only the scratch pages written
since the last restore, from the hypervisor's dirty-page log and a log of host
writes. WHP no longer replaces the scratch mapping on each restore, so the
pages a guest writes stay committed between restores. MSHV tracks scratch of
2 MiB or more, and stops tracking a scratch region after a run writes more
than a tenth of it (a quarter from 32 MiB), where zeroing all of it costs
less.
* When Windows cannot tell which scratch pages were written, restore zeroes
scratch of up to 16 MiB in place, which is faster than replacing it below
that size, and replaces larger scratch.

### Removed
* `RunPool` and the run-specific `AllocError::InvalidAlign` variant.
Expand Down
5 changes: 5 additions & 0 deletions bench_report.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
# nothing fails the report.
allowlist = [
"^function_call_codec/decode_vec_bytes_copy$",
"^guest_calls/call_with_restore/default$",
"^guest_calls/call_with_restore/scratch_64mib$",
"^guest_calls/call_with_restore/scratch_64mib_write_1mib$",
"^guest_calls/call_with_restore/scratch_256mib$",
"^guest_calls/call_with_restore/scratch_256mib_write_1mib$",
"^function_call_codec/encode_control/byte_chunks$",
"^function_call_codec/encode_control/vec_bytes$",
"^payload_allocation/slot_pool_segmented/262144$",
Expand Down
34 changes: 34 additions & 0 deletions src/hyperlight_host/benches/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,30 @@ fn bench_guest_call_with_restore(b: &mut criterion::Bencher, size: SandboxSize)
});
}

/// A call and a restore with `mib` MiB of scratch, where resetting scratch
/// dominates a restore. The guest writes `write` bytes of heap a call, or
/// only a few pages (an Echo).
fn bench_large_scratch_call_with_restore(
b: &mut criterion::Bencher,
mib: usize,
write: Option<u64>,
) {
let mut sbox = SandboxBuilder::from_file(simple_guest_as_pathbuf())
.heap_size(4 << 20)
.scratch_size(mib << 20)
.build()
.unwrap();
let snapshot = sbox.snapshot().unwrap();

b.iter(|| {
match write {
Some(len) => sbox.call::<()>("AllocAndWritePattern", len).unwrap(),
None => drop(sbox.call::<String>("Echo", "hello\n".to_string()).unwrap()),
}
sbox.restore(snapshot.clone()).unwrap();
});
}

fn bench_guest_call_with_host_function(b: &mut criterion::Bencher, size: SandboxSize) {
let mut multiuse_sandbox = size
.builder()
Expand Down Expand Up @@ -237,6 +261,16 @@ fn guest_calls_benchmark(c: &mut Criterion) {
});
}

for mib in [64, 256] {
group.bench_function(format!("call_with_restore/scratch_{mib}mib"), |b| {
bench_large_scratch_call_with_restore(b, mib, None)
});
group.bench_function(
format!("call_with_restore/scratch_{mib}mib_write_1mib"),
|b| bench_large_scratch_call_with_restore(b, mib, Some(1 << 20)),
);
}

for size in SandboxSize::all() {
group.bench_function(format!("call_with_host_function/{}", size.name()), |b| {
bench_guest_call_with_host_function(b, size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::sync::Arc;

use super::{
AccessPageTableError, CreateHyperlightVmError, DispatchGuestCallError, HyperlightVm,
InitializeError,
InitializeError, ScratchDirtyLog,
};
#[cfg(hvf)]
use crate::hypervisor::HvfInterruptHandle;
Expand Down Expand Up @@ -100,6 +100,7 @@ impl HyperlightVm {
snapshot_memory: None,
scratch_slot,
scratch_memory: None,
scratch_dirty: ScratchDirtyLog::default(),

mmap_regions: Vec::new(),

Expand Down
Loading
Loading