Repository navigation
Revert sparse snapshot blob writes (#1788) - #1898
Conversation
This reverts commit 3ef1a36. On Windows, a snapshot blob marked with FSCTL_SET_SPARSE is slow to map under WHP. The first guest function call after restoring from it takes about 35 ms longer than from a dense blob. Having the flag set is enough: a blob with no holes and a single extent is just as slow, and clearing the flag afterwards does not help. Only a fresh dense write does. Signed-off-by: danbugs <danilochiarlone@gmail.com>
There was a problem hiding this comment.
🟡 Changes recommended
Existing valid sparse blobs are reused without the dense rewrite needed to remove the Windows penalty.
1 open finding
What changed in this PR
Restores dense snapshot blob writes to avoid WHP restore latency.
Changes:
- Removes sparse file writing and related tests.
- Reduces Windows API features.
- Removes the sparse writing changelog entry.
| File | Description |
|---|---|
fsutil.rs |
Restores dense blob writes. |
Cargo.toml |
Removes sparse file API features. |
CHANGELOG.md |
Removes the reverted feature entry. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Benchmark ResultsMeasured commit: kvm / amd (Linux) (➖ stable)No benchmark improved or regressed. Benchmark Resultsfunction_call_codec
payload_allocation
sandboxes
slot_pool
snapshot_files
virtq_readonly
virtq_readwrite
kvm / intel (Linux) (➖ stable)No benchmark improved or regressed. Benchmark Resultsfunction_call_codec
payload_allocation
sandboxes
slot_pool
snapshot_files
virtq_readonly
virtq_readwrite
mshv3 / amd (Linux) (
|
encode_control |
decode_vec_bytes_copy |
|
|---|---|---|
byte_chunks |
922.04 ns (➖ 1.02x faster) |
|
vec_bytes |
703.20 ns ( |
|
373.28 µs (➖ 1.30x slower) |
payload_allocation
slot_pool_segmented |
|
|---|---|
262144 |
730.38 ns (➖ 1.01x faster) |
65536 |
254.31 ns (➖ 1.30x slower) |
sandboxes
create_initialized_and_drop |
|
|---|---|
medium |
59.28 ms (➖ 1.03x slower) |
slot_pool
alloc_dealloc_1500 |
alloc_dealloc_4096 |
alloc_dealloc_128 |
|
|---|---|---|---|
9.73 ns (➖ 1.00x slower) |
9.71 ns (➖ 1.00x faster) |
9.67 ns (➖ 1.01x faster) |
snapshot_files
load_snapshot_unverified |
|
|---|---|
small |
84.69 µs (➖ 1.00x slower) |
virtq_readonly
slot_pool_segmented_fragmented |
slot_pool_segmented |
|
|---|---|---|
262144 |
9.84 µs (➖ 1.09x faster) |
8.78 µs (➖ 1.04x faster) |
65536 |
2.28 µs (➖ 1.02x slower) |
2.22 µs (➖ 1.10x faster) |
virtq_readwrite
slot_pool_segmented_fragmented |
slot_pool_segmented |
|
|---|---|---|
65536 |
8.14 µs (➖ 1.00x faster) |
8.10 µs (➖ 1.03x faster) |
8192 |
1.29 µs (➖ 1.00x faster) |
1.39 µs (➖ 1.04x slower) |
262144 |
36.96 µs (➖ 1.01x slower) |
mshv3 / intel (Linux) (➖ stable)
No benchmark improved or regressed.
Benchmark Results
function_call_codec
encode_control |
decode_vec_bytes_copy |
|
|---|---|---|
byte_chunks |
929.64 ns (➖ 1.01x faster) |
|
vec_bytes |
663.85 ns (➖ 1.01x faster) |
|
701.44 µs (➖ 1.05x slower) |
payload_allocation
slot_pool_segmented |
|
|---|---|
262144 |
672.68 ns (➖ 1.13x slower) |
65536 |
170.80 ns (➖ 1.02x slower) |
sandboxes
create_initialized_and_drop |
|
|---|---|
medium |
83.40 ms (➖ 1.31x slower) |
slot_pool
alloc_dealloc_1500 |
alloc_dealloc_4096 |
alloc_dealloc_128 |
|
|---|---|---|---|
9.61 ns (➖ 1.01x slower) |
8.82 ns (➖ 1.13x faster) |
8.81 ns (➖ 1.00x slower) |
snapshot_files
load_snapshot_unverified |
|
|---|---|
small |
48.48 µs (➖ 1.06x slower) |
virtq_readonly
slot_pool_segmented_fragmented |
slot_pool_segmented |
|
|---|---|---|
262144 |
7.78 µs (➖ 1.00x faster) |
7.78 µs (➖ 1.03x faster) |
65536 |
2.27 µs (➖ 1.01x slower) |
2.27 µs (➖ 1.00x faster) |
virtq_readwrite
slot_pool_segmented_fragmented |
slot_pool_segmented |
|
|---|---|---|
65536 |
7.57 µs (➖ 1.01x slower) |
7.54 µs (➖ 1.01x faster) |
8192 |
881.98 ns (➖ 1.01x slower) |
880.92 ns (➖ 1.01x slower) |
262144 |
35.81 µs (➖ 1.12x faster) |
hyperv-ws2025 / amd (Windows) (➖ stable)
No benchmark improved or regressed.
Benchmark Results
function_call_codec
encode_control |
decode_vec_bytes_copy |
|
|---|---|---|
byte_chunks |
1.15 µs (➖ 1.01x faster) |
|
vec_bytes |
760.35 ns (➖ 1.04x faster) |
|
2.18 ms (➖ 1.03x slower) |
payload_allocation
slot_pool_segmented |
|
|---|---|
262144 |
793.69 ns (➖ 1.05x faster) |
65536 |
227.86 ns (➖ 1.04x faster) |
sandboxes
create_initialized_and_drop |
|
|---|---|
medium |
102.45 ms (➖ 1.10x slower) |
slot_pool
alloc_dealloc_1500 |
alloc_dealloc_4096 |
alloc_dealloc_128 |
|
|---|---|---|---|
11.22 ns (➖ 1.11x slower) |
10.57 ns (➖ 1.01x slower) |
10.75 ns (➖ 1.06x slower) |
snapshot_files
load_snapshot_unverified |
|
|---|---|
small |
732.70 µs (➖ 1.10x faster) |
virtq_readonly
slot_pool_segmented_fragmented |
slot_pool_segmented |
|
|---|---|---|
262144 |
8.68 µs (➖ 1.11x faster) |
8.60 µs (➖ 1.24x faster) |
65536 |
2.54 µs (➖ 1.06x slower) |
2.55 µs (➖ 1.08x slower) |
virtq_readwrite
slot_pool_segmented_fragmented |
slot_pool_segmented |
|
|---|---|---|
65536 |
9.07 µs (➖ 1.02x slower) |
8.96 µs (➖ 1.06x faster) |
8192 |
1.41 µs (➖ 1.05x slower) |
1.37 µs (➖ 1.03x slower) |
262144 |
48.40 µs (➖ 1.25x slower) |
hyperv-ws2025 / intel (Windows) (➖ stable)
No benchmark improved or regressed.
Benchmark Results
function_call_codec
encode_control |
decode_vec_bytes_copy |
|
|---|---|---|
byte_chunks |
1.24 µs (➖ 1.24x slower) |
|
vec_bytes |
816.77 ns (➖ 1.26x slower) |
|
3.07 ms (➖ 1.17x faster) |
payload_allocation
slot_pool_segmented |
|
|---|---|
262144 |
742.03 ns (➖ 1.10x slower) |
65536 |
218.37 ns (➖ 1.14x slower) |
sandboxes
create_initialized_and_drop |
|
|---|---|
medium |
112.59 ms (➖ 1.10x faster) |
slot_pool
alloc_dealloc_1500 |
alloc_dealloc_4096 |
alloc_dealloc_128 |
|
|---|---|---|---|
10.29 ns (➖ 1.20x slower) |
10.11 ns (➖ 1.20x slower) |
10.63 ns (➖ 1.31x slower) |
snapshot_files
load_snapshot_unverified |
|
|---|---|
small |
476.54 µs (➖ 1.11x faster) |
virtq_readonly
slot_pool_segmented_fragmented |
slot_pool_segmented |
|
|---|---|---|
262144 |
7.62 µs (➖ 1.14x faster) |
7.72 µs (➖ 1.13x faster) |
65536 |
2.33 µs (➖ 1.09x faster) |
2.31 µs (➖ 1.09x faster) |
virtq_readwrite
slot_pool_segmented_fragmented |
slot_pool_segmented |
|
|---|---|---|
65536 |
8.54 µs (➖ 1.08x faster) |
8.60 µs (➖ 1.15x faster) |
8192 |
1.11 µs (➖ 1.01x faster) |
1.18 µs (➖ 1.02x slower) |
262144 |
42.27 µs (➖ 1.18x slower) |
Reported by cargo ci bench-report --candidate run:37670356285 --baseline run:37551535479 --config-file bench_report.toml.
|
Why doesn't bot comment show an improvement on windows? |
We don't have a benchmark in hyperlight-core that catches the regression. It was observed in hyperlight-unikraft. |
also, it currently only shows the results for a subset of the benchmarks, due to the high variance of some benches (#1894 is trying to fix that) |

This reverts #1788 because sparse snapshot blobs slow down the first guest function call after a restore on Windows (WHP). Any blob written with
FSCTL_SET_SPARSEcosts about 35 ms extra on that first guest function call, even when the blob has no holes. Clearing the flag later doesn't fix it; only a dense rewrite does.Replaces #1895, which was opened from a fork and hit the shorter CI timeouts.