pmonitor 1.4.9__tar.gz → 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {pmonitor-1.4.9 → pmonitor-1.5.0}/PKG-INFO +1 -1
  2. pmonitor-1.5.0/monitor/monitor_mac_vmmap.py +116 -0
  3. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/monitor_pids.py +11 -4
  4. {pmonitor-1.4.9 → pmonitor-1.5.0}/pmonitor.egg-info/PKG-INFO +1 -1
  5. {pmonitor-1.4.9 → pmonitor-1.5.0}/setup.py +1 -1
  6. pmonitor-1.4.9/monitor/monitor_mac_vmmap.py +0 -51
  7. {pmonitor-1.4.9 → pmonitor-1.5.0}/README.md +0 -0
  8. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/GpuMonitorLib.dll +0 -0
  9. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/KernelBase.dll +0 -0
  10. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/__init__.py +0 -0
  11. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/advapi32.dll +0 -0
  12. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/bcrypt.dll +0 -0
  13. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/kernel.appcore.dll +0 -0
  14. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/kernel32.dll +0 -0
  15. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/msvcirt.dll +0 -0
  16. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/msvcp140.dll +0 -0
  17. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/ntdll.dll +0 -0
  18. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/pdh.dll +0 -0
  19. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/rpcrt4.dll +0 -0
  20. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/sechost.dll +0 -0
  21. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/ucrtbased.dll +0 -0
  22. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/vcruntime140.dll +0 -0
  23. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/DLL/vcruntime140_1.dll +0 -0
  24. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/WinPidUtil.py +0 -0
  25. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/__init__.py +0 -0
  26. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/get_process_name.py +0 -0
  27. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/mac_gpu.py +0 -0
  28. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/monitor_mac.py +0 -0
  29. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/monitor_win.py +0 -0
  30. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/run_monitor.py +0 -0
  31. {pmonitor-1.4.9 → pmonitor-1.5.0}/monitor/sys_info.py +0 -0
  32. {pmonitor-1.4.9 → pmonitor-1.5.0}/pmonitor.egg-info/SOURCES.txt +0 -0
  33. {pmonitor-1.4.9 → pmonitor-1.5.0}/pmonitor.egg-info/dependency_links.txt +0 -0
  34. {pmonitor-1.4.9 → pmonitor-1.5.0}/pmonitor.egg-info/entry_points.txt +0 -0
  35. {pmonitor-1.4.9 → pmonitor-1.5.0}/pmonitor.egg-info/requires.txt +0 -0
  36. {pmonitor-1.4.9 → pmonitor-1.5.0}/pmonitor.egg-info/top_level.txt +0 -0
  37. {pmonitor-1.4.9 → pmonitor-1.5.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.2
2
2
  Name: pmonitor
3
- Version: 1.4.9
3
+ Version: 1.5.0
4
4
  Summary: pc monitor
5
5
  Home-page: UNKNOWN
6
6
  Author: cfr
@@ -0,0 +1,116 @@
1
+ import subprocess
2
+ import threading
3
+ import time
4
+ import json
5
+ import re
6
+ import os
7
+
8
+
9
+ class VmMapMemory:
10
+ def __init__(self):
11
+ """
12
+ 初始化实时内存监控器
13
+ """
14
+ self.pids = set() # 当前监控的 PID
15
+ self.current_data = {} # 存储最新的内存数据 {pid: memory_mb}
16
+ self.lock = threading.Lock() # 线程锁
17
+ self.running = True # 控制线程运行状态
18
+ self.thread = None # 监控线程
19
+ # 启动监控线程
20
+ self.start_monitoring()
21
+
22
+ def start_monitoring(self):
23
+ """启动监控线程"""
24
+ self.thread = threading.Thread(target=self._monitor_memory)
25
+ self.thread.daemon = True # 设置为守护线程
26
+ self.thread.start()
27
+
28
+ def update_pids(self, new_pids):
29
+ """更新要监控的 PID 列表"""
30
+ with self.lock:
31
+ # 转换为字符串并更新集合
32
+ self.pids = set(map(str, new_pids))
33
+
34
+ def _convert_to_mb(self, mem_str):
35
+ """
36
+ 将内存字符串转换为 MB
37
+ 支持格式: 123, 123K, 123M, 123G
38
+ """
39
+ # 移除逗号(如果存在)
40
+ mem_str = mem_str.replace(',', '')
41
+
42
+ # 检查单位并转换
43
+ if 'G' in mem_str:
44
+ return float(mem_str.replace('G', '')) * 1024
45
+ elif 'M' in mem_str:
46
+ return float(mem_str.replace('M', ''))
47
+ elif 'K' in mem_str:
48
+ return float(mem_str.replace('K', '')) / 1024
49
+ else:
50
+ # 假设为字节
51
+ return float(mem_str) / (1024 * 1024)
52
+
53
+ def _monitor_memory(self):
54
+ """线程函数:实时监控内存使用"""
55
+ # macOS 专用 top 命令
56
+ cmd = ["top", "-stats", "pid,mem"]
57
+
58
+ # 启动 top 进程
59
+ process = subprocess.Popen(
60
+ cmd,
61
+ stdout=subprocess.PIPE,
62
+ stderr=subprocess.PIPE,
63
+ text=True,
64
+ bufsize=1, # 行缓冲
65
+ universal_newlines=True # 确保文本模式
66
+ )
67
+
68
+ try:
69
+ while self.running:
70
+ line = process.stdout.readline() # 逐行读取
71
+
72
+ if not line: # 进程结束或无输出时退出
73
+ break
74
+
75
+ # 匹配 PID 和内存行 (例如: "12345 123.4M")
76
+ match = re.match(r'^\s*(\d+)\s+([\d,.]+[KMG]?)\s*$', line.strip())
77
+ if match:
78
+ pid = match.group(1)
79
+ mem_str = match.group(2)
80
+
81
+ # 检查是否在监控列表中
82
+ with self.lock:
83
+ if pid in self.pids:
84
+ mem_mb = self._convert_to_mb(mem_str)
85
+ # 直接更新当前数据,不保存历史
86
+ self.current_data[pid] = round(mem_mb, 2)
87
+
88
+ except Exception as e:
89
+ print(f"Monitoring error: {e}")
90
+ finally:
91
+ if process.poll() is None: # 确保进程终止
92
+ process.terminate()
93
+
94
+ def get_current_data(self):
95
+ """
96
+ 获取当前内存数据(线程安全)
97
+ 只返回当前监控的 PID 的最新内存值
98
+ """
99
+ with self.lock:
100
+ # 只返回当前监控列表中的 PID 数据
101
+ return {
102
+ pid: self.current_data.get(pid, 0.0)
103
+ for pid in self.pids
104
+ }
105
+
106
+ def get_current_json(self):
107
+ """获取 JSON 格式的当前内存数据"""
108
+ data = self.get_current_data()
109
+ return json.dumps(data, indent=2)
110
+
111
+ def stop(self):
112
+ """停止监控"""
113
+ self.running = False
114
+ if self.thread and self.thread.is_alive():
115
+ self.thread.join(timeout=1)
116
+ print("Memory monitor stopped")
@@ -26,6 +26,7 @@ class PidsPerf:
26
26
  current_pid = self.processUtil.find_main_process_pid(self.process_name)
27
27
  vm = VmMapMemory()
28
28
  next_time = time.time() # 初始化下一次执行的时间点
29
+ first_iteration = True # 标志变量,用于跳过第一次循环
29
30
  while True:
30
31
  start_time = time.time() # 记录循环开始时间
31
32
  minor_cpu_sum = 0
@@ -45,13 +46,19 @@ class PidsPerf:
45
46
 
46
47
  gpu_memory_usage, gpu_memory_total, gpu_memory_free = get_gpu_memory()
47
48
  # 使用 asyncio.gather 并发获取内存数据
48
- memory_tasks = [vm.get_process_memory(process.pid) for process in pids_process]
49
- memory_results = await asyncio.gather(*memory_tasks, return_exceptions=True)
50
- for idx, process in enumerate(pids_process):
49
+ vm.update_pids(current_pids)
50
+
51
+ if first_iteration:
52
+ first_iteration = False # 第一次循环后将标志置为 False
53
+ await asyncio.sleep(self.interval / 1000) # 等待一段时间以确保数据稳定
54
+ continue # 跳过第一次循环
55
+
56
+ for process in pids_process:
51
57
  try:
52
58
  cpu_percent = process.cpu_percent()
53
59
  mem_percent = u'%.2f' % (process.memory_percent()) # 内存利用率
54
- real_mem = memory_results[idx] # 实际内存
60
+ vm_memory_data = json.loads(vm.get_current_json())
61
+ real_mem = vm_memory_data.get(str(process.pid), 0) # 默认值为 0(如果未找到对应 PID)
55
62
  thread_count = process.num_threads() # 线程总数
56
63
  except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
57
64
  cpu_percent = 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.2
2
2
  Name: pmonitor
3
- Version: 1.4.9
3
+ Version: 1.5.0
4
4
  Summary: pc monitor
5
5
  Home-page: UNKNOWN
6
6
  Author: cfr
@@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
5
5
  long_description = f.read()
6
6
 
7
7
  setup(name='pmonitor',
8
- version='1.4.9',
8
+ version='1.5.0',
9
9
  description='pc monitor',
10
10
  long_description=long_description,
11
11
  author='cfr',
@@ -1,51 +0,0 @@
1
- import re
2
- import asyncio
3
-
4
-
5
- class VmMapMemory:
6
- def __init__(self):
7
- self.last_nonzero_memory = None
8
-
9
- async def get_process_memory(self, pid):
10
- cmd = ["top", "-l", "1", "-stats", "mem", "-pid", str(pid)]
11
- try:
12
- # 创建子进程并设置超时
13
- proc = await asyncio.create_subprocess_exec(
14
- *cmd,
15
- stdout=asyncio.subprocess.PIPE,
16
- stderr=asyncio.subprocess.DEVNULL
17
- )
18
-
19
- try:
20
- stdout, _ = await asyncio.wait_for(proc.communicate(), timeout=1)
21
- except asyncio.TimeoutError:
22
- # 超时后确保子进程被终止
23
- proc.kill()
24
- await proc.wait()
25
- raise
26
-
27
- if proc.returncode == 0:
28
- # 解析 top 输出中的内存信息
29
- lines = stdout.decode().strip().split('\n')
30
- if lines:
31
- last_line = lines[-1].strip() # 获取最后一行
32
- match = re.match(r'^([\d.]+)([GMK]?)$', last_line)
33
-
34
- if match:
35
- val, unit = float(match.group(1)), match.group(2)
36
- memory_value = val * {
37
- 'G': 1024, 'M': 1, 'K': 1 / 1024, '': 1 / (1024 * 1024)
38
- }.get(unit, 1)
39
-
40
- if memory_value > 0:
41
- self.last_nonzero_memory = memory_value
42
- # 返回当前值或上一次非零值
43
- return memory_value if memory_value != 0 else self.last_nonzero_memory
44
- except Exception as e:
45
- print(e)
46
- finally:
47
- if proc and proc.returncode is None:
48
- proc.kill()
49
- await proc.wait()
50
- # 如果未能获取到有效值,返回上一次非零值或默认值 0.0
51
- return self.last_nonzero_memory if self.last_nonzero_memory is not None else 0.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes