|
| 1 | +# Author: Elin |
| 2 | +# Date: 2024-04-25 10:31:02 |
| 3 | +# Last Modified by: Elin |
| 4 | +# Last Modified time: 2024-04-25 10:31:02 |
| 5 | + |
| 6 | +import psutil as pt |
| 7 | +from typing import List |
| 8 | +from pynvml import * |
| 9 | +import asciichartpy |
| 10 | +import time |
| 11 | +from rich.console import Console |
| 12 | +from rich.table import Table |
| 13 | +from datetime import datetime |
| 14 | + |
| 15 | +class Moni: |
| 16 | + def __init__(self): |
| 17 | + nvmlInit() |
| 18 | + self.console = Console() |
| 19 | + self.cpu_name: str = open("/proc/cpuinfo").readlines()[4].split(":")[1].strip() |
| 20 | + self.threads: int = pt.cpu_count() |
| 21 | + self.mem_size: int = pt.virtual_memory().total // (1024 ** 3) + 1 |
| 22 | + self.gpus: int = nvmlDeviceGetCount() |
| 23 | + self.gpus_names: List[str] = [nvmlDeviceGetName(nvmlDeviceGetHandleByIndex(i)) for i in range(self.gpus)] |
| 24 | + self.gpus_mem_size: List[int] = [ |
| 25 | + nvmlDeviceGetMemoryInfo(nvmlDeviceGetHandleByIndex(i)).total // (1024 ** 3) for i in range(self.gpus) |
| 26 | + ] |
| 27 | + |
| 28 | + def __call__(self): |
| 29 | + while True: |
| 30 | + self._flush_data() |
| 31 | + self.console.clear() |
| 32 | + self._render() |
| 33 | + time.sleep(1) |
| 34 | + |
| 35 | + def _render(self): |
| 36 | + self.console.print(f"Moni v{self.__version__()} by {self.__author__()}" + " " * 10 + datetime.now().strftime("%Y-%m-%d %H:%M:%S")) |
| 37 | + self.console.print(f"CPU: {self.cpu_name}, {self.threads} THREADS") |
| 38 | + self.console.print(f"MEM: {self.mem_size} GB, {self.used_mem} GB has been used now") |
| 39 | + self.console.print("CPU Usage:") |
| 40 | + self.console.print(asciichartpy.plot(self.cpu_percent, {'height': 5})) |
| 41 | + for i in range(self.gpus): |
| 42 | + self.console.print(f"GPU {i}: {self.gpus_names[i]} ({self.gpus_mem_size[i]} GB), {self.gpus_mem_usage[i]} GB VRAM been used, CORE Temp {self.gpus_temperature[i]} °C") |
| 43 | + self.console.print(asciichartpy.plot(self.gpus_volatile_usage[i], {'height': 5})) |
| 44 | + self._plot_process_table() |
| 45 | + |
| 46 | + def _plot_process_table(self): |
| 47 | + process_table = Table() |
| 48 | + fields = ["PID", "USER", "NAME", "STATUS", "CPU_USAGE", "MEM_USAGE", "COMMAND"] |
| 49 | + process_table.add_column("PID") |
| 50 | + process_table.add_column("USER") |
| 51 | + process_table.add_column("NAME") |
| 52 | + process_table.add_column("STATUS") |
| 53 | + process_table.add_column("CPU_USAGE") |
| 54 | + process_table.add_column("MEM_USAGE") |
| 55 | + process_table.add_column("COMMAND") |
| 56 | + running_process_count:int = 0 |
| 57 | + sleeping_process_count:int = 0 |
| 58 | + stopped_process_count:int = 0 |
| 59 | + zombie_process_count:int = 0 |
| 60 | + self.process_list = sorted(self.process_list, key=lambda x: (x.cpu_percent(),x.memory_percent()), reverse=True) |
| 61 | + for p in self.process_list: |
| 62 | + status = p.status() |
| 63 | + if status == "running": |
| 64 | + running_process_count += 1 |
| 65 | + elif status == "sleeping": |
| 66 | + sleeping_process_count += 1 |
| 67 | + elif status == "stopped": |
| 68 | + stopped_process_count += 1 |
| 69 | + elif status == "zombie": |
| 70 | + zombie_process_count += 1 |
| 71 | + for p in self.process_list[:10]: |
| 72 | + try: |
| 73 | + process_table.add_row(str(p.pid), p.username(), p.name(), p.status(), str(round(p.cpu_percent(), 2)) + "%", str(round(p.memory_percent(), 2)) + "%", p.cmdline()[0] if p.cmdline() else "") |
| 74 | + except pt.NoSuchProcess or pt.AccessDenied or pt.ZombieProcess: |
| 75 | + continue |
| 76 | + self.console.print(f"Total Process: {len(self.process_list)}, Running: {running_process_count}, Sleeping: {sleeping_process_count}, Stopped: {stopped_process_count}, Zombie: {zombie_process_count}") |
| 77 | + self.console.print(f"Shows TOP10 high utilized process:") |
| 78 | + self.console.print(process_table) |
| 79 | + |
| 80 | + def _flush_data(self): |
| 81 | + self.used_mem: int = pt.virtual_memory().used // (1024 ** 3) + 1 |
| 82 | + self.cpu_percent: List[float] = [pt.cpu_percent(interval=1e-1) for _ in range(self.threads)] |
| 83 | + self.gpus_mem_usage: List[float] = [ |
| 84 | + round(nvmlDeviceGetMemoryInfo(nvmlDeviceGetHandleByIndex(i)).used // (1024 ** 3),2) for i in range(self.gpus) |
| 85 | + ] |
| 86 | + self.gpus_temperature: List[int] = [ |
| 87 | + nvmlDeviceGetTemperature(nvmlDeviceGetHandleByIndex(i), NVML_TEMPERATURE_GPU) for i in range(self.gpus) |
| 88 | + ] |
| 89 | + self.gpus_volatile_usage: List[List[int]] = [ |
| 90 | + [int(nvmlDeviceGetUtilizationRates(nvmlDeviceGetHandleByIndex(i)).gpu) for _ in range(50)] for i in range(self.gpus) |
| 91 | + ] |
| 92 | + try: |
| 93 | + self.process_list: List[pt.Process] = list(pt.process_iter()) |
| 94 | + except: |
| 95 | + self.process_list: List[pt.Process] = [] |
| 96 | + |
| 97 | + def __version__(self): |
| 98 | + return "0.0.1" |
| 99 | + def __author__(self): |
| 100 | + return "Elin" |
| 101 | +if __name__ == "__main__": |
| 102 | + moni = Moni() |
| 103 | + moni() |
0 commit comments