|
|
@@ -8,31 +8,16 @@ from numba import cuda
|
|
|
import numpy as np
|
|
|
import pynvml
|
|
|
class Monitor:
|
|
|
- def __init__(self, pid:int, alias:str=''):
|
|
|
+ def __init__(self, pid:int, interval=2, alias:str=''):
|
|
|
self.cuda_tensor = cuda.to_device(np.arange(10000).astype(np.float32))
|
|
|
self.pid = pid
|
|
|
+ self.interval = interval # 相邻两次采样间隔,默认2秒
|
|
|
self.process = None
|
|
|
self.curr_disk_io_counter = None # 磁盘读写计数器
|
|
|
- self.curr_system_net_io_counter = psutil.net_io_counters() # 系统网络读写计数器
|
|
|
+ self.curr_system_net_io_counter = None # 系统网络读写计数器
|
|
|
self.data_points=[] # 数据点
|
|
|
self.max_count = 1
|
|
|
- self.usage = {
|
|
|
- "pid":'', # 进程名称
|
|
|
- "now_time":'', # 当前时间
|
|
|
- "cpu_pct": '', # cpu使用率
|
|
|
- "rss":'', # 物理内存
|
|
|
- "vms":'', # 虚拟内存
|
|
|
- "mem_pct":'', # 内存使用率
|
|
|
- "disk_read": '', # 磁盘读速率
|
|
|
- "disk_write": '', # 磁盘写速率
|
|
|
- "sys_net_recv": '', # 系统网络下载速率
|
|
|
- "sys_net_send": '', # 系统网络上传速率
|
|
|
- "name": '', # 进程名称
|
|
|
- "status": '', # 进程状态
|
|
|
- "pwd":'', # 当前工作目录
|
|
|
- "exe":'', # 可执行文件路径
|
|
|
- "start_time": '', # 进程启动时间
|
|
|
- }
|
|
|
+ self.usage = self.__init_usage
|
|
|
self.usage_map = {
|
|
|
"pid": '进程名称',
|
|
|
"now_time": '当前时间',
|
|
|
@@ -53,19 +38,44 @@ class Monitor:
|
|
|
|
|
|
try:
|
|
|
self.process = psutil.Process(pid)
|
|
|
- self.curr_disk_io_counter = self.process.io_counters()
|
|
|
-
|
|
|
+ self.curr_disk_io_counter = self.process.io_counters() # 磁盘读写计数器
|
|
|
+ self.curr_system_net_io_counter = psutil.net_io_counters() # 系统网络读写计数器
|
|
|
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
|
+ print(f"未找到PID为 {pid} 的进程或无权限访问该进程。")
|
|
|
+ self.process = None
|
|
|
+ except Exception as e:
|
|
|
+ print(f"初始化{pid}Monitor时发生错误: {e}")
|
|
|
+ self.process = None
|
|
|
+ if self.process:
|
|
|
print(f"成功附加到进程: {self.process.name()} (PID: {pid})")
|
|
|
self.usage["name"] = self.process.name()
|
|
|
self.usage["pid"] = f'{self.process.pid}'
|
|
|
self.usage["pwd"] = self.process.cwd()
|
|
|
self.usage["exe"] = self.process.exe()
|
|
|
self.usage["start_time"] = datetime.fromtimestamp(self.process.create_time()).strftime('%Y-%m-%d %H:%M:%S')
|
|
|
- except psutil.NoSuchProcess:
|
|
|
- print(f"未找到PID为 {pid} 的进程。")
|
|
|
- self.process = None
|
|
|
|
|
|
- def get_memory_usage_info(self):
|
|
|
+
|
|
|
+ @property
|
|
|
+ def __init_usage(self):
|
|
|
+ return {
|
|
|
+ "pid":'', # 进程名称
|
|
|
+ "now_time":'', # 当前时间
|
|
|
+ "cpu_pct": '', # cpu使用率
|
|
|
+ "rss":'', # 物理内存
|
|
|
+ "vms":'', # 虚拟内存
|
|
|
+ "mem_pct":'', # 内存使用率
|
|
|
+ "disk_read": '', # 磁盘读速率
|
|
|
+ "disk_write": '', # 磁盘写速率
|
|
|
+ "sys_net_recv": '', # 系统网络下载速率
|
|
|
+ "sys_net_send": '', # 系统网络上传速率
|
|
|
+ "name": '', # 进程名称
|
|
|
+ "status": '', # 进程状态
|
|
|
+ "pwd":'', # 当前工作目录
|
|
|
+ "exe":'', # 可执行文件路径
|
|
|
+ "start_time": '', # 进程启动时间
|
|
|
+ }
|
|
|
+
|
|
|
+ def __get_memory_usage_info(self):
|
|
|
"""内存使用信息"""
|
|
|
if not self.process:
|
|
|
raise RuntimeError(f'监控程序未能找到进程:{self.pid}')
|
|
|
@@ -77,12 +87,12 @@ class Monitor:
|
|
|
self.usage["vms"] = f'{vms_mb:.2f}MB' # 虚拟内存
|
|
|
self.usage["mem_pct"] = f'{memory_usage_percent:.2f}%' # 占用百分比
|
|
|
|
|
|
- def get_cpu_usage_info(self):
|
|
|
+ def __get_cpu_usage_info(self):
|
|
|
# 获取CPU使用率,设置采样间隔为1秒
|
|
|
cpu_usage = self.process.cpu_percent(interval=1.0)
|
|
|
self.usage["cpu_pct"] = f'{cpu_usage:.2f}%'
|
|
|
|
|
|
- def get_disk_io_info(self):
|
|
|
+ def __get_disk_io_info(self):
|
|
|
"""统计磁盘读写速度"""
|
|
|
new_io_counter = self.process.io_counters()
|
|
|
read_bytes_diff = (new_io_counter.read_bytes - self.curr_disk_io_counter.read_bytes) / (1024 ** 2)
|
|
|
@@ -97,7 +107,7 @@ class Monitor:
|
|
|
self.usage['disk_write'] = f'{write_speed_mB:.2f} MB/s'
|
|
|
self.curr_disk_io_counter = new_io_counter
|
|
|
|
|
|
- def get_net_io_info(self):
|
|
|
+ def __get_net_io_info(self):
|
|
|
"""统计网络上下行速度"""
|
|
|
new_net_io_counter = psutil.net_io_counters()
|
|
|
sent_bytes_mB = (new_net_io_counter.bytes_sent - self.curr_system_net_io_counter.bytes_sent) / (1024 ** 2)
|
|
|
@@ -111,7 +121,7 @@ class Monitor:
|
|
|
self.usage['sys_net_recv'] = f'{sys_net_recv_speed:.2f} MB/s'
|
|
|
self.curr_system_net_io_counter = new_net_io_counter
|
|
|
|
|
|
- def get_gpu_usage_info(self):
|
|
|
+ def __get_gpu_usage_info(self):
|
|
|
try:
|
|
|
# 验证进程是否存在
|
|
|
if not psutil.pid_exists(self.pid):
|
|
|
@@ -147,7 +157,7 @@ class Monitor:
|
|
|
# self.usage[device_id+'rate_mem'] = gpu_util.memory if gpu_util else 0
|
|
|
self.usage[device_id+'temperature'] = temperature
|
|
|
self.usage[device_id+'power'] = power_watts
|
|
|
- # print(f"GPU {i}:")
|
|
|
+ print(f"GPU {i}:")
|
|
|
# print(f" 内存使用: {memory_mb:.2f} MB")
|
|
|
# print(f" GPU 利用率: {gpu_util.gpu if gpu_util else 0}%")
|
|
|
# print(f" 内存利用率: {gpu_util.memory if gpu_util else 0}%")
|
|
|
@@ -162,18 +172,25 @@ class Monitor:
|
|
|
import traceback
|
|
|
traceback.print_exc()
|
|
|
def update(self, output_file=None):
|
|
|
+ """更新进程信息"""
|
|
|
+ # 时间间隔
|
|
|
+ time.sleep(self.interval)
|
|
|
+ # 初始化记录
|
|
|
+ self.usage = self.__init_usage
|
|
|
+ # 刷新时间
|
|
|
self.usage['now_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
|
self.usage['status'] = self.process.status()
|
|
|
# 刷新内存使用情况
|
|
|
- self.get_memory_usage_info()
|
|
|
+ self.__get_memory_usage_info()
|
|
|
# 刷新cpu使用情况
|
|
|
- self.get_cpu_usage_info()
|
|
|
+ self.__get_cpu_usage_info()
|
|
|
# 刷新硬盘读取情况
|
|
|
- self.get_disk_io_info()
|
|
|
+ self.__get_disk_io_info()
|
|
|
# 刷新网络上下行情况
|
|
|
- self.get_net_io_info()
|
|
|
+ self.__get_net_io_info()
|
|
|
# 获取GPU使用情况
|
|
|
- self.get_gpu_usage_info()
|
|
|
+ self.__get_gpu_usage_info()
|
|
|
+ print(self.usage)
|
|
|
if output_file:
|
|
|
self.data_points.append(self.usage.copy())
|
|
|
if len(self.data_points) >= self.max_count: # 如果达到100个数据点,则保存到CSV文件中,并清空数据点
|
|
|
@@ -197,7 +214,6 @@ class Monitor:
|
|
|
with self.process.oneshot():
|
|
|
self.update(output_file=output_file)
|
|
|
print(self.usage)
|
|
|
- time.sleep(interval)
|
|
|
except Exception as e:
|
|
|
break
|
|
|
def main():
|