Skip to content

Commit 7803c42

Browse files
committed
bench: add benchmark for page fault latencies
Add a benchmark that attempts to capture the latency of a single page fault in a guest memory configuration that we also use in production. This should catch regressions such as the 1.6 memfd/vhost post snapshot-restore latency regression, and does indeed do so: MAP_ANONYMOUS: Running benches/memory_access.rs page_fault time: [2.8611 µs 2.9327 µs 3.0170 µs] Found 9 outliers among 100 measurements (9.00%) 4 (4.00%) high mild 5 (5.00%) high severe memfd_create: Running benches/memory_access.rs page_fault time: [5.7449 µs 5.8779 µs 6.0450 µs] change: [+85.649% +92.231% +98.074%] (p = 0.00 < 0.05) Performance has regressed. Found 8 outliers among 100 measurements (8.00%) 5 (5.00%) low mild 2 (2.00%) high mild 1 (1.00%) high severe Add the same benchmark for huge pages, just in case. Funnily enough, there is no vhost-tax to be paid for huge pages. Signed-off-by: Patrick Roy <[email protected]>
1 parent c852830 commit 7803c42

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

src/vmm/Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,9 @@ harness = false
7070
name = "block_request"
7171
harness = false
7272

73+
[[bench]]
74+
name = "memory_access"
75+
harness = false
76+
7377
[lints]
7478
workspace = true

src/vmm/benches/memory_access.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
5+
use vm_memory::{GuestAddress, GuestMemory};
6+
use vmm::resources::VmResources;
7+
use vmm::vmm_config::machine_config::{HugePageConfig, VmConfig};
8+
9+
fn bench_single_page_fault(c: &mut Criterion, configuration: VmResources) {
10+
c.bench_function("page_fault", |b| {
11+
b.iter_batched(
12+
|| {
13+
let memory = configuration.allocate_guest_memory().unwrap();
14+
let ptr = memory
15+
.get_slice(GuestAddress(0), 1)
16+
.unwrap()
17+
.ptr_guard_mut()
18+
.as_ptr();
19+
20+
// fine to return both here, because ptr is not a reference into `memory` (e.g. no
21+
// self-referential structs are happening here)
22+
(memory, ptr)
23+
},
24+
|(_, ptr)| unsafe {
25+
// Cause a single page fault
26+
ptr.write_volatile(1);
27+
},
28+
BatchSize::SmallInput,
29+
)
30+
});
31+
}
32+
33+
pub fn bench_4k_page_fault(c: &mut Criterion) {
34+
bench_single_page_fault(
35+
c,
36+
VmResources {
37+
vm_config: VmConfig {
38+
vcpu_count: 1,
39+
mem_size_mib: 2,
40+
..Default::default()
41+
},
42+
..Default::default()
43+
},
44+
)
45+
}
46+
47+
pub fn bench_2m_page_fault(c: &mut Criterion) {
48+
bench_single_page_fault(
49+
c,
50+
VmResources {
51+
vm_config: VmConfig {
52+
vcpu_count: 1,
53+
mem_size_mib: 2,
54+
huge_pages: HugePageConfig::Hugetlbfs2M,
55+
..Default::default()
56+
},
57+
..Default::default()
58+
},
59+
)
60+
}
61+
62+
criterion_group! {
63+
name = memory_access_benches;
64+
config = Criterion::default().noise_threshold(0.05);
65+
targets = bench_4k_page_fault, bench_2m_page_fault
66+
}
67+
68+
criterion_main! {
69+
memory_access_benches
70+
}

0 commit comments

Comments
 (0)