|
14 | 14 | import typing |
15 | 15 | from collections import defaultdict, namedtuple |
16 | 16 | from contextlib import contextmanager |
| 17 | +from pathlib import Path |
17 | 18 | from typing import Dict |
18 | 19 |
|
19 | 20 | import psutil |
20 | 21 | import semver |
| 22 | +from packaging import version |
21 | 23 | from tenacity import ( |
22 | 24 | Retrying, |
23 | 25 | retry, |
@@ -259,6 +261,48 @@ def get_free_mem_ssh(ssh_connection): |
259 | 261 | raise Exception("Available memory not found in `/proc/meminfo") |
260 | 262 |
|
261 | 263 |
|
| 264 | +def get_stable_rss_mem_by_pid(process, percentage_delta=1): |
| 265 | + """ |
| 266 | + Get the RSS memory that a guest uses, given the pid of the guest. |
| 267 | +
|
| 268 | + Wait till the fluctuations in RSS drop below percentage_delta. |
| 269 | + Or print a warning if this does not happen. |
| 270 | + """ |
| 271 | + |
| 272 | + # All values are reported as KiB |
| 273 | + |
| 274 | + def get_rss_from_pmap(): |
| 275 | + """Returns current memory utilization in KiB, including used HugeTLBFS""" |
| 276 | + |
| 277 | + proc_status = Path("/proc", str(process.pid), "status").read_text("utf-8") |
| 278 | + for line in proc_status.splitlines(): |
| 279 | + if line.startswith("HugetlbPages:"): # entry is in KiB |
| 280 | + hugetlbfs_usage = int(line.split()[1]) |
| 281 | + break |
| 282 | + else: |
| 283 | + assert False, f"HugetlbPages not found in {str(proc_status)}" |
| 284 | + return hugetlbfs_usage + process.memory_info().rss // 1024 |
| 285 | + |
| 286 | + first_rss = 0 |
| 287 | + second_rss = 0 |
| 288 | + for _ in range(5): |
| 289 | + first_rss = get_rss_from_pmap() |
| 290 | + time.sleep(1) |
| 291 | + second_rss = get_rss_from_pmap() |
| 292 | + abs_diff = abs(first_rss - second_rss) |
| 293 | + abs_delta = abs_diff / first_rss * 100 |
| 294 | + print( |
| 295 | + f"RSS readings: old: {first_rss} new: {second_rss} abs_diff: {abs_diff} abs_delta: {abs_delta}" |
| 296 | + ) |
| 297 | + if abs_delta < percentage_delta: |
| 298 | + return second_rss |
| 299 | + |
| 300 | + time.sleep(1) |
| 301 | + |
| 302 | + print("WARNING: RSS readings did not stabilize") |
| 303 | + return second_rss |
| 304 | + |
| 305 | + |
262 | 306 | def _format_output_message(proc, stdout, stderr): |
263 | 307 | output_message = f"\n[{proc.pid}] Command:\n{proc.args}" |
264 | 308 | # Append stdout/stderr to the output message |
@@ -417,6 +461,11 @@ def get_kernel_version(level=2): |
417 | 461 | return linux_version |
418 | 462 |
|
419 | 463 |
|
| 464 | +def supports_hugetlbfs_discard(): |
| 465 | + """Returns True if the kernel supports hugetlbfs discard""" |
| 466 | + return version.parse(get_kernel_version()) >= version.parse("5.18.0") |
| 467 | + |
| 468 | + |
420 | 469 | def generate_mmds_session_token( |
421 | 470 | ssh_connection, ipv4_address, token_ttl, imds_compat=False |
422 | 471 | ): |
|
0 commit comments