From 05058c30c85edd9876514465d0536529f66d89f1 Mon Sep 17 00:00:00 2001 From: Shahzad Malik Muzaffar Date: Fri, 12 Dec 2025 20:18:37 +0100 Subject: [PATCH 1/3] improve cpu utilization monitoring --- monitor_build.py | 76 ++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 42 deletions(-) diff --git a/monitor_build.py b/monitor_build.py index c5b36c6..01f89bc 100644 --- a/monitor_build.py +++ b/monitor_build.py @@ -2,59 +2,51 @@ from threading import Thread import psutil from json import dump as json_dump -from time import time, sleep +from time import time, sleep, monotonic # Sampling interval in seconds SAMPLE_INTERVAL = 1.0 -cpu_initialized = set() +cpu_times = {} def update_monitor_stats(proc): - global cpu_initialized - children = [] - try: children = proc.children(recursive=True) + global cpu_times + try:children = proc.children(recursive=True) except: return {} stats = {"rss": 0, "vms": 0, "shared": 0, "data": 0, "uss": 0, "pss": 0, "num_fds": 0, "num_threads": 0, "processes": 0, "cpu": 0} - clds = len(children) - if clds==0: return stats - stats['processes'] = clds - - # Step 1: Initialize CPU counters for new PIDs - current_pids = set() - for p in children: - pid = p.pid - current_pids.add(pid) - if pid not in cpu_initialized: - try: - p.cpu_percent(interval=None) - cpu_initialized.add(pid) - except: - continue - - # Step 2: Sleep once to allow CPU measurement + stats['processes'] = len(children) sleep(SAMPLE_INTERVAL) - - # Step 3: Collect CPU%, memory, threads, FDs - for p in children: + new_cpu_times = {} + for p in [proc] + children: + pid = p.pid try: - stats["cpu"] += int(p.cpu_percent(interval=None)) - try: - mem = p.memory_full_info() - stats["uss"] += getattr(mem, "uss", 0) - stats["pss"] += getattr(mem, "pss", 0) - except: - mem = p.memory_info() - for a in ["rss", "vms", "shared", "data"]: - stats[a] += getattr(mem, a) - stats["num_threads"] += p.num_threads() - try: - stats["num_fds"] += p.num_fds() - except: - pass + current_time = monotonic() + new_cpu = p.cpu_times() + old_cpu, last_time = cpu_times.get(pid, (None, None)) + cpu_delta = 0 + elapsed = 0 + if old_cpu: + delta = (new_cpu.user - old_cpu.user) + (new_cpu.system - old_cpu.system) + elapsed = current_time - last_time + else: + delta = new_cpu.user + new_cpu.system + elapsed = time() - p.create_time() + if elapsed>=0.1: + stats["cpu"] += int((delta / elapsed) * 100.0) + new_cpu_times[pid] = (new_cpu, current_time) except: continue - - # Step 4: Cleanup exited PIDs - cpu_initialized.intersection_update(current_pids) + try: + mem = p.memory_full_info() + stats["uss"] += getattr(mem, "uss", 0) + stats["pss"] += getattr(mem, "pss", 0) + except: + mem = p.memory_info() + for a in ["rss", "vms", "shared", "data"]: + stats[a] += getattr(mem, a, 0) + stats["num_threads"] += p.num_threads() + try: stats["num_fds"] += p.num_fds() + except: pass + cpu_times = new_cpu_times return stats def monitor_stats(p_id, stats_file_name): From 5d758d7cb64408f948e75b7dff6dfeb5ec9309f0 Mon Sep 17 00:00:00 2001 From: Shahzad Malik Muzaffar Date: Sat, 13 Dec 2025 00:18:27 +0100 Subject: [PATCH 2/3] do not fail if process finished before we process its resources --- monitor_build.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/monitor_build.py b/monitor_build.py index 01f89bc..4d568d6 100644 --- a/monitor_build.py +++ b/monitor_build.py @@ -36,15 +36,15 @@ def update_monitor_stats(proc): except: continue try: - mem = p.memory_full_info() - stats["uss"] += getattr(mem, "uss", 0) - stats["pss"] += getattr(mem, "pss", 0) - except: - mem = p.memory_info() - for a in ["rss", "vms", "shared", "data"]: - stats[a] += getattr(mem, a, 0) - stats["num_threads"] += p.num_threads() - try: stats["num_fds"] += p.num_fds() + stats['num_fds'] += p.num_fds() + stats['num_threads'] += p.num_threads() + mem = {} + try: + mem = p.memory_full_info() + for a in ["uss", "pss"]: stats[a]+=getattr(mem,a) + except: + mem = p.memory_info() + for a in ["rss", "vms", "shared", "data"]: stats[a]+=getattr(mem,a) except: pass cpu_times = new_cpu_times return stats From da910f2e59327d5860c5027454ba7f272afd9cc3 Mon Sep 17 00:00:00 2001 From: Shahzad Malik Muzaffar Date: Sat, 13 Dec 2025 11:36:59 +0100 Subject: [PATCH 3/3] improve memory monitoring --- monitor_build.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/monitor_build.py b/monitor_build.py index 4d568d6..c4960f8 100644 --- a/monitor_build.py +++ b/monitor_build.py @@ -38,13 +38,14 @@ def update_monitor_stats(proc): try: stats['num_fds'] += p.num_fds() stats['num_threads'] += p.num_threads() - mem = {} + mem = None try: - mem = p.memory_full_info() - for a in ["uss", "pss"]: stats[a]+=getattr(mem,a) + mem = p.memory_full_info() + for a in ["uss", "pss"]: stats[a] += getattr(mem, a) except: - mem = p.memory_info() - for a in ["rss", "vms", "shared", "data"]: stats[a]+=getattr(mem,a) + try: mem = p.memory_info() + except: mem = p.memory_info_ex() + for a in ["rss", "vms", "shared", "data"]: stats[a] += getattr(mem, a) except: pass cpu_times = new_cpu_times return stats