86 lines
2.7 KiB
Python
86 lines
2.7 KiB
Python
from dataclasses import dataclass
|
|
import dataclasses
|
|
from decimal import Decimal
|
|
from functools import reduce
|
|
from typing import NamedTuple, Optional
|
|
from line_profiler import profile
|
|
import psutil
|
|
|
|
@dataclass
|
|
class ProcessSwapInfo:
|
|
pid: int
|
|
name: str
|
|
swap: int
|
|
|
|
@dataclass
|
|
class ProcessSwapGroup:
|
|
name: str
|
|
processes: list[ProcessSwapInfo] = dataclasses.field(default_factory=list)
|
|
|
|
@property
|
|
def total_swap(self) -> int:
|
|
return sum(map(lambda x: x.swap, self.processes))
|
|
|
|
type ProcessName = str
|
|
|
|
def convert_bytes_to_mb(value: int) -> Decimal:
|
|
return Decimal(value) / (1024 * 1024)
|
|
|
|
@profile
|
|
def get_process_swap_usage() -> None:
|
|
print(f"{'PID':>6} {'Name':<25} {'Swap (MB)':>10}")
|
|
print("-" * 45)
|
|
|
|
total_swap_used = 0
|
|
|
|
swap_used: list[ProcessSwapInfo] = []
|
|
|
|
for proc in psutil.process_iter(['pid', 'name', 'memory_full_info']):
|
|
try:
|
|
with proc.oneshot():
|
|
memory_info: Optional[NamedTuple] = proc.info['memory_full_info']
|
|
swap: int = getattr(memory_info, "swap", 0)
|
|
if swap > 0:
|
|
swap_used.append(ProcessSwapInfo(proc.pid, proc.name(), swap))
|
|
total_swap_used += swap
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
continue
|
|
|
|
swap_used.sort(key=lambda x: x.swap)
|
|
|
|
def _add_to_group(groups: dict[ProcessName, ProcessSwapGroup], process: ProcessSwapInfo) -> dict[ProcessName, ProcessSwapGroup]:
|
|
if process.name not in groups:
|
|
groups[process.name] = ProcessSwapGroup(process.name)
|
|
groups[process.name].processes.append(process)
|
|
return groups
|
|
|
|
swap_used_groups: list[ProcessSwapGroup] = sorted(
|
|
(item for item in reduce(_add_to_group, swap_used, dict()).values()),
|
|
key=lambda x: x.total_swap
|
|
)
|
|
|
|
for group in swap_used_groups:
|
|
print(f"{group.name:<32} {convert_bytes_to_mb(group.total_swap):10.2f}")
|
|
for item in group.processes:
|
|
print(f"{item.pid:>32} {convert_bytes_to_mb(item.swap):10.2f}")
|
|
print()
|
|
|
|
print("-" * 45)
|
|
print(f"{'Total swap used by processes:':<32} {convert_bytes_to_mb(total_swap_used):10.2f} MB")
|
|
|
|
def show_swap_summary() -> None:
|
|
swap = psutil.swap_memory()
|
|
print("\n=== Swap Summary ===")
|
|
print(f"Total: {convert_bytes_to_mb(swap.total):.2f} MB")
|
|
print(f"Used: {convert_bytes_to_mb(swap.used):.2f} MB")
|
|
print(f"Free: {convert_bytes_to_mb(swap.free):.2f} MB")
|
|
print(f"Percent Used: {swap.percent:.1f}%")
|
|
|
|
def main() -> None:
|
|
print("=== Process Swap Usage ===")
|
|
get_process_swap_usage()
|
|
show_swap_summary()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|