|
6 | 6 | import os |
7 | 7 |
|
8 | 8 | import host_tools.drive as drive_tools |
| 9 | +from framework import utils |
9 | 10 |
|
10 | 11 | ALIGNMENT = 2 << 20 |
11 | 12 |
|
@@ -140,3 +141,66 @@ def test_pmem_add_as_root_ro(uvm_plain_any, rootfs, microvm_factory): |
140 | 141 | snapshot = vm.snapshot_full() |
141 | 142 | restored_vm = microvm_factory.build_from_snapshot(snapshot) |
142 | 143 | check_pmem_exist(restored_vm, 0, True, True, align(rootfs_size), "squashfs") |
| 144 | + |
| 145 | + |
| 146 | +def inside_buff_cache(vm) -> int: |
| 147 | + """Get buffer/cache usage from inside the vm""" |
| 148 | + _, stdout, _ = vm.ssh.check_output("free") |
| 149 | + # Get the `buffer/cache` of the `free` command which represents |
| 150 | + # kernel page cache size |
| 151 | + return int(stdout.splitlines()[1].split()[5]) |
| 152 | + |
| 153 | + |
| 154 | +def outside_rssanon(vm) -> int: |
| 155 | + """Get RssAnon usage from outside the vm""" |
| 156 | + cmd = f"cat /proc/{vm.firecracker_pid}/status | grep RssAnon" |
| 157 | + _, stdout, _ = utils.check_output(cmd) |
| 158 | + return int(stdout.split()[1]) |
| 159 | + |
| 160 | + |
| 161 | +def test_pmem_dax_memory_saving( |
| 162 | + microvm_factory, |
| 163 | + guest_kernel_acpi, |
| 164 | + rootfs_rw, |
| 165 | +): |
| 166 | + """ |
| 167 | + Test that booting from pmem with DAX enabled indeed saves memory in the |
| 168 | + guest by not needing guest to use its page cache |
| 169 | + """ |
| 170 | + |
| 171 | + # Boot from a block device |
| 172 | + vm = microvm_factory.build( |
| 173 | + guest_kernel_acpi, rootfs_rw, pci=True, monitor_memory=False |
| 174 | + ) |
| 175 | + vm.spawn() |
| 176 | + vm.basic_config() |
| 177 | + vm.add_net_iface() |
| 178 | + vm.start() |
| 179 | + block_cache_usage = inside_buff_cache(vm) |
| 180 | + block_rss_usage = outside_rssanon(vm) |
| 181 | + |
| 182 | + # Boot from pmem with DAX enabled for root device |
| 183 | + vm_pmem = microvm_factory.build( |
| 184 | + guest_kernel_acpi, rootfs_rw, pci=True, monitor_memory=False |
| 185 | + ) |
| 186 | + vm_pmem.spawn() |
| 187 | + vm_pmem.basic_config( |
| 188 | + add_root_device=False, |
| 189 | + boot_args="reboot=k panic=1 nomodule swiotlb=noforce console=ttyS0 rootflags=dax", |
| 190 | + ) |
| 191 | + vm_pmem.add_net_iface() |
| 192 | + vm_pmem.add_pmem("pmem", rootfs_rw, True, False) |
| 193 | + vm_pmem.start() |
| 194 | + pmem_cache_usage = inside_buff_cache(vm_pmem) |
| 195 | + pmem_rss_usage = outside_rssanon(vm_pmem) |
| 196 | + |
| 197 | + # The pmem cache usage should be much lower than drive cache usage. |
| 198 | + # The 50% is an arbitrary number, but does provide a good guarantee |
| 199 | + # that DAX is working |
| 200 | + assert ( |
| 201 | + pmem_cache_usage < block_cache_usage * 0.5 |
| 202 | + ), f"{block_cache_usage} <= {pmem_cache_usage}" |
| 203 | + # RssAnon difference will be smaller, so no multipliers |
| 204 | + assert ( |
| 205 | + pmem_rss_usage < block_rss_usage |
| 206 | + ), f"{block_cache_usage} <= {pmem_cache_usage}" |
0 commit comments