macpm 0.12__tar.gz → 0.14__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: macpm
3
- Version: 0.12
3
+ Version: 0.14
4
4
  Summary: Performance monitoring CLI tool for Apple Silicon
5
5
  Home-page: https://github.com/visualcjy/macpm
6
6
  Author: Jinyu Chen
@@ -1,6 +1,7 @@
1
1
  # macpm
2
2
 
3
- ![PyPI - Downloads](https://pypi.org/project/macpm/#files)
3
+ PyPI - Downloads (https://pypi.org/project/macpm/#files)
4
+ or: pip install macpm
4
5
 
5
6
  Performance monitoring CLI tool for Apple Silicon
6
7
 
@@ -15,6 +16,8 @@ pip install macpm
15
16
  forked form https://github.com/tlkh/asitop
16
17
  1. fixed the problem that "E-CPU Usage" and "P-CPU Usage" always 100%
17
18
  2. add "Disk IO" and "Network IO" info
19
+ 3. adjust the hard coded max power in CPU/GPU/ANE
20
+ 4. change the way to call powermetrics, no temp files in /tmp
18
21
 
19
22
  A Python-based `nvtop`-inspired command line tool for Apple Silicon (aka M1) Macs.
20
23
 
@@ -1,12 +1,17 @@
1
- import time
2
1
  import argparse
3
2
  import humanize
4
3
  from collections import deque
4
+ from blessed import Terminal
5
5
  from dashing import VSplit, HSplit, HGauge, HChart, VGauge, HBrailleChart, HBrailleFilledChart
6
- from .utils import *
6
+ import os, time
7
+ import subprocess
8
+ from subprocess import PIPE
9
+ import psutil
10
+ import plistlib
7
11
 
12
+ version = 'macpm v0.14'
8
13
  parser = argparse.ArgumentParser(
9
- description='macpm: Performance monitoring CLI tool for Apple Silicon')
14
+ description=f'{version}: Performance monitoring CLI tool for Apple Silicon')
10
15
  parser.add_argument('--interval', type=int, default=1,
11
16
  help='Display interval and sampling interval for powermetrics (seconds)')
12
17
  parser.add_argument('--color', type=int, default=2,
@@ -15,10 +20,314 @@ parser.add_argument('--avg', type=int, default=30,
15
20
  help='Interval for averaged values (seconds)')
16
21
  parser.add_argument('--show_cores', type=bool, default=False,
17
22
  help='Choose show cores mode')
18
- parser.add_argument('--max_count', type=int, default=0,
19
- help='Max show count to restart powermetrics')
23
+
20
24
  args = parser.parse_args()
21
25
 
26
+ powermetrics_process = None
27
+
28
+ def clear_console():
29
+ command = 'clear'
30
+ os.system(command)
31
+
32
+
33
+ def convert_to_GB(value):
34
+ return round(value/1024/1024/1024, 1)
35
+
36
+
37
+ def get_ram_metrics_dict():
38
+ ram_metrics = psutil.virtual_memory()
39
+ swap_metrics = psutil.swap_memory()
40
+ total_GB = convert_to_GB(ram_metrics.total)
41
+ free_GB = convert_to_GB(ram_metrics.available)
42
+ used_GB = convert_to_GB(ram_metrics.total-ram_metrics.available)
43
+ swap_total_GB = convert_to_GB(swap_metrics.total)
44
+ swap_used_GB = convert_to_GB(swap_metrics.used)
45
+ swap_free_GB = convert_to_GB(swap_metrics.total-swap_metrics.used)
46
+ if swap_total_GB > 0:
47
+ swap_free_percent = int(100-(swap_free_GB/swap_total_GB*100))
48
+ else:
49
+ swap_free_percent = None
50
+ ram_metrics_dict = {
51
+ "total_GB": round(total_GB, 1),
52
+ "free_GB": round(free_GB, 1),
53
+ "used_GB": round(used_GB, 1),
54
+ "free_percent": int(100-(ram_metrics.available/ram_metrics.total*100)),
55
+ "swap_total_GB": swap_total_GB,
56
+ "swap_used_GB": swap_used_GB,
57
+ "swap_free_GB": swap_free_GB,
58
+ "swap_free_percent": swap_free_percent,
59
+ }
60
+ return ram_metrics_dict
61
+
62
+
63
+ def get_cpu_info():
64
+ cpu_info = os.popen('sysctl -a | grep machdep.cpu').read()
65
+ cpu_info_lines = cpu_info.split("\n")
66
+ data_fields = ["machdep.cpu.brand_string", "machdep.cpu.core_count"]
67
+ cpu_info_dict = {}
68
+ for l in cpu_info_lines:
69
+ for h in data_fields:
70
+ if h in l:
71
+ value = l.split(":")[1].strip()
72
+ cpu_info_dict[h] = value
73
+ return cpu_info_dict
74
+
75
+
76
+ def get_core_counts():
77
+ cores_info = os.popen('sysctl -a | grep hw.perflevel').read()
78
+ cores_info_lines = cores_info.split("\n")
79
+ data_fields = ["hw.perflevel0.logicalcpu", "hw.perflevel1.logicalcpu"]
80
+ cores_info_dict = {}
81
+ for l in cores_info_lines:
82
+ for h in data_fields:
83
+ if h in l:
84
+ value = int(l.split(":")[1].strip())
85
+ cores_info_dict[h] = value
86
+ return cores_info_dict
87
+
88
+
89
+ def get_gpu_cores():
90
+ try:
91
+ cores = os.popen(
92
+ "system_profiler -detailLevel basic SPDisplaysDataType | grep 'Total Number of Cores'").read()
93
+ cores = int(cores.split(": ")[-1])
94
+ except:
95
+ cores = "?"
96
+ return cores
97
+
98
+
99
+ def get_soc_info():
100
+ cpu_info_dict = get_cpu_info()
101
+ core_counts_dict = get_core_counts()
102
+ try:
103
+ e_core_count = core_counts_dict["hw.perflevel1.logicalcpu"]
104
+ p_core_count = core_counts_dict["hw.perflevel0.logicalcpu"]
105
+ except:
106
+ e_core_count = "?"
107
+ p_core_count = "?"
108
+ soc_info = {
109
+ "name": cpu_info_dict["machdep.cpu.brand_string"],
110
+ "core_count": int(cpu_info_dict["machdep.cpu.core_count"]),
111
+ "cpu_max_power": None,
112
+ "gpu_max_power": None,
113
+ "cpu_max_bw": None,
114
+ "gpu_max_bw": None,
115
+ "e_core_count": e_core_count,
116
+ "p_core_count": p_core_count,
117
+ "gpu_core_count": get_gpu_cores()
118
+ }
119
+ # TDP (power)
120
+ if soc_info["name"] == "Apple M1 Max":
121
+ soc_info["cpu_max_power"] = 30
122
+ soc_info["gpu_max_power"] = 60
123
+ elif soc_info["name"] == "Apple M1 Pro":
124
+ soc_info["cpu_max_power"] = 30
125
+ soc_info["gpu_max_power"] = 30
126
+ elif soc_info["name"] == "Apple M1":
127
+ soc_info["cpu_max_power"] = 20
128
+ soc_info["gpu_max_power"] = 20
129
+ elif soc_info["name"] == "Apple M1 Ultra":
130
+ soc_info["cpu_max_power"] = 60
131
+ soc_info["gpu_max_power"] = 120
132
+ elif soc_info["name"] == "Apple M2":
133
+ soc_info["cpu_max_power"] = 25
134
+ soc_info["gpu_max_power"] = 15
135
+ else:
136
+ soc_info["cpu_max_power"] = 20
137
+ soc_info["gpu_max_power"] = 20
138
+ # bandwidth
139
+ if soc_info["name"] == "Apple M1 Max":
140
+ soc_info["cpu_max_bw"] = 250
141
+ soc_info["gpu_max_bw"] = 400
142
+ elif soc_info["name"] == "Apple M1 Pro":
143
+ soc_info["cpu_max_bw"] = 200
144
+ soc_info["gpu_max_bw"] = 200
145
+ elif soc_info["name"] == "Apple M1":
146
+ soc_info["cpu_max_bw"] = 70
147
+ soc_info["gpu_max_bw"] = 70
148
+ elif soc_info["name"] == "Apple M1 Ultra":
149
+ soc_info["cpu_max_bw"] = 500
150
+ soc_info["gpu_max_bw"] = 800
151
+ elif soc_info["name"] == "Apple M2":
152
+ soc_info["cpu_max_bw"] = 100
153
+ soc_info["gpu_max_bw"] = 100
154
+ else:
155
+ soc_info["cpu_max_bw"] = 70
156
+ soc_info["gpu_max_bw"] = 70
157
+ return soc_info
158
+
159
+ def parse_thermal_pressure(powermetrics_parse):
160
+ return powermetrics_parse["thermal_pressure"]
161
+
162
+
163
+ def parse_bandwidth_metrics(powermetrics_parse):
164
+ bandwidth_metrics = powermetrics_parse["bandwidth_counters"]
165
+ bandwidth_metrics_dict = {}
166
+ data_fields = ["PCPU0 DCS RD", "PCPU0 DCS WR",
167
+ "PCPU1 DCS RD", "PCPU1 DCS WR",
168
+ "PCPU2 DCS RD", "PCPU2 DCS WR",
169
+ "PCPU3 DCS RD", "PCPU3 DCS WR",
170
+ "PCPU DCS RD", "PCPU DCS WR",
171
+ "ECPU0 DCS RD", "ECPU0 DCS WR",
172
+ "ECPU1 DCS RD", "ECPU1 DCS WR",
173
+ "ECPU DCS RD", "ECPU DCS WR",
174
+ "GFX DCS RD", "GFX DCS WR",
175
+ "ISP DCS RD", "ISP DCS WR",
176
+ "STRM CODEC DCS RD", "STRM CODEC DCS WR",
177
+ "PRORES DCS RD", "PRORES DCS WR",
178
+ "VDEC DCS RD", "VDEC DCS WR",
179
+ "VENC0 DCS RD", "VENC0 DCS WR",
180
+ "VENC1 DCS RD", "VENC1 DCS WR",
181
+ "VENC2 DCS RD", "VENC2 DCS WR",
182
+ "VENC3 DCS RD", "VENC3 DCS WR",
183
+ "VENC DCS RD", "VENC DCS WR",
184
+ "JPG0 DCS RD", "JPG0 DCS WR",
185
+ "JPG1 DCS RD", "JPG1 DCS WR",
186
+ "JPG2 DCS RD", "JPG2 DCS WR",
187
+ "JPG3 DCS RD", "JPG3 DCS WR",
188
+ "JPG DCS RD", "JPG DCS WR",
189
+ "DCS RD", "DCS WR"]
190
+ for h in data_fields:
191
+ bandwidth_metrics_dict[h] = 0
192
+ for l in bandwidth_metrics:
193
+ if l["name"] in data_fields:
194
+ bandwidth_metrics_dict[l["name"]] = l["value"]/(1e9)
195
+ bandwidth_metrics_dict["PCPU DCS RD"] = bandwidth_metrics_dict["PCPU DCS RD"] + \
196
+ bandwidth_metrics_dict["PCPU0 DCS RD"] + \
197
+ bandwidth_metrics_dict["PCPU1 DCS RD"] + \
198
+ bandwidth_metrics_dict["PCPU2 DCS RD"] + \
199
+ bandwidth_metrics_dict["PCPU3 DCS RD"]
200
+ bandwidth_metrics_dict["PCPU DCS WR"] = bandwidth_metrics_dict["PCPU DCS WR"] + \
201
+ bandwidth_metrics_dict["PCPU0 DCS WR"] + \
202
+ bandwidth_metrics_dict["PCPU1 DCS WR"] + \
203
+ bandwidth_metrics_dict["PCPU2 DCS WR"] + \
204
+ bandwidth_metrics_dict["PCPU3 DCS WR"]
205
+ bandwidth_metrics_dict["JPG DCS RD"] = bandwidth_metrics_dict["JPG DCS RD"] + \
206
+ bandwidth_metrics_dict["JPG0 DCS RD"] + \
207
+ bandwidth_metrics_dict["JPG1 DCS RD"] + \
208
+ bandwidth_metrics_dict["JPG2 DCS RD"] + \
209
+ bandwidth_metrics_dict["JPG3 DCS RD"]
210
+ bandwidth_metrics_dict["JPG DCS WR"] = bandwidth_metrics_dict["JPG DCS WR"] + \
211
+ bandwidth_metrics_dict["JPG0 DCS WR"] + \
212
+ bandwidth_metrics_dict["JPG1 DCS WR"] + \
213
+ bandwidth_metrics_dict["JPG2 DCS WR"] + \
214
+ bandwidth_metrics_dict["JPG3 DCS WR"]
215
+ bandwidth_metrics_dict["VENC DCS RD"] = bandwidth_metrics_dict["VENC DCS RD"] + \
216
+ bandwidth_metrics_dict["VENC0 DCS RD"] + \
217
+ bandwidth_metrics_dict["VENC1 DCS RD"] + \
218
+ bandwidth_metrics_dict["VENC2 DCS RD"] + \
219
+ bandwidth_metrics_dict["VENC3 DCS RD"]
220
+ bandwidth_metrics_dict["VENC DCS WR"] = bandwidth_metrics_dict["VENC DCS WR"] + \
221
+ bandwidth_metrics_dict["VENC0 DCS WR"] + \
222
+ bandwidth_metrics_dict["VENC1 DCS WR"] + \
223
+ bandwidth_metrics_dict["VENC2 DCS WR"] + \
224
+ bandwidth_metrics_dict["VENC3 DCS WR"]
225
+ bandwidth_metrics_dict["MEDIA DCS"] = sum([
226
+ bandwidth_metrics_dict["ISP DCS RD"], bandwidth_metrics_dict["ISP DCS WR"],
227
+ bandwidth_metrics_dict["STRM CODEC DCS RD"], bandwidth_metrics_dict["STRM CODEC DCS WR"],
228
+ bandwidth_metrics_dict["PRORES DCS RD"], bandwidth_metrics_dict["PRORES DCS WR"],
229
+ bandwidth_metrics_dict["VDEC DCS RD"], bandwidth_metrics_dict["VDEC DCS WR"],
230
+ bandwidth_metrics_dict["VENC DCS RD"], bandwidth_metrics_dict["VENC DCS WR"],
231
+ bandwidth_metrics_dict["JPG DCS RD"], bandwidth_metrics_dict["JPG DCS WR"],
232
+ ])
233
+ return bandwidth_metrics_dict
234
+
235
+
236
+ def parse_cpu_metrics(powermetrics_parse):
237
+ e_core = []
238
+ p_core = []
239
+ cpu_metrics = powermetrics_parse["processor"]
240
+ cpu_metric_dict = {}
241
+ # cpu_clusters
242
+ cpu_clusters = cpu_metrics["clusters"]
243
+ e_total_idle_ratio = 0
244
+ e_core_count = 0
245
+ p_total_idle_ratio = 0
246
+ p_core_count = 0
247
+ for cluster in cpu_clusters:
248
+ name = cluster["name"]
249
+ cpu_metric_dict[name+"_freq_Mhz"] = int(cluster["freq_hz"]/(1e6))
250
+ cpu_metric_dict[name+"_active"] = int((1 - cluster["idle_ratio"])*100)
251
+ for cpu in cluster["cpus"]:
252
+ name = 'E-Cluster' if name[0] == 'E' else 'P-Cluster'
253
+ core = e_core if name[0] == 'E' else p_core
254
+ core.append(cpu["cpu"])
255
+ cpu_metric_dict[name + str(cpu["cpu"]) + "_freq_Mhz"] = int(cpu["freq_hz"] / (1e6))
256
+ cpu_metric_dict[name + str(cpu["cpu"]) + "_active"] = int((1 - cpu["idle_ratio"]) * 100)
257
+ if name[0] == 'E':
258
+ e_total_idle_ratio += cluster["down_ratio"] + (1 - cluster["down_ratio"]) * (cpu["idle_ratio"] + cpu["down_ratio"])
259
+ e_core_count += 1
260
+ else:
261
+ p_total_idle_ratio += cluster["down_ratio"] + (1 - cluster["down_ratio"]) * (cpu["idle_ratio"] + cpu["down_ratio"])
262
+ p_core_count += 1
263
+
264
+ cpu_metric_dict["E-Cluster_active"] = int((1 - e_total_idle_ratio/e_core_count)*100)
265
+ cpu_metric_dict["P-Cluster_active"] = int((1 - p_total_idle_ratio/p_core_count)*100)
266
+ cpu_metric_dict["e_core"] = e_core
267
+ cpu_metric_dict["p_core"] = p_core
268
+ if "E-Cluster_active" not in cpu_metric_dict:
269
+ # M1 Ultra
270
+ cpu_metric_dict["E-Cluster_active"] = int(
271
+ (cpu_metric_dict["E0-Cluster_active"] + cpu_metric_dict["E1-Cluster_active"])/2)
272
+ if "E-Cluster_freq_Mhz" not in cpu_metric_dict:
273
+ # M1 Ultra
274
+ cpu_metric_dict["E-Cluster_freq_Mhz"] = max(
275
+ cpu_metric_dict["E0-Cluster_freq_Mhz"], cpu_metric_dict["E1-Cluster_freq_Mhz"])
276
+ if "P-Cluster_active" not in cpu_metric_dict:
277
+ if "P2-Cluster_active" in cpu_metric_dict:
278
+ # M1 Ultra
279
+ cpu_metric_dict["P-Cluster_active"] = int((cpu_metric_dict["P0-Cluster_active"] + cpu_metric_dict["P1-Cluster_active"] +
280
+ cpu_metric_dict["P2-Cluster_active"] + cpu_metric_dict["P3-Cluster_active"]) / 4)
281
+ else:
282
+ cpu_metric_dict["P-Cluster_active"] = int(
283
+ (cpu_metric_dict["P0-Cluster_active"] + cpu_metric_dict["P1-Cluster_active"])/2)
284
+ if "P-Cluster_freq_Mhz" not in cpu_metric_dict:
285
+ if "P2-Cluster_freq_Mhz" in cpu_metric_dict:
286
+ # M1 Ultra
287
+ freqs = [
288
+ cpu_metric_dict["P0-Cluster_freq_Mhz"],
289
+ cpu_metric_dict["P1-Cluster_freq_Mhz"],
290
+ cpu_metric_dict["P2-Cluster_freq_Mhz"],
291
+ cpu_metric_dict["P3-Cluster_freq_Mhz"]]
292
+ cpu_metric_dict["P-Cluster_freq_Mhz"] = max(freqs)
293
+ else:
294
+ cpu_metric_dict["P-Cluster_freq_Mhz"] = max(
295
+ cpu_metric_dict["P0-Cluster_freq_Mhz"], cpu_metric_dict["P1-Cluster_freq_Mhz"])
296
+ # power
297
+ cpu_metric_dict["ane_W"] = cpu_metrics["ane_energy"]/1000
298
+ #cpu_metric_dict["dram_W"] = cpu_metrics["dram_energy"]/1000
299
+ cpu_metric_dict["cpu_W"] = cpu_metrics["cpu_energy"]/1000
300
+ cpu_metric_dict["gpu_W"] = cpu_metrics["gpu_energy"]/1000
301
+ cpu_metric_dict["package_W"] = cpu_metrics["combined_power"]/1000
302
+ return cpu_metric_dict
303
+
304
+
305
+ def parse_gpu_metrics(powermetrics_parse):
306
+ gpu_metrics = powermetrics_parse["gpu"]
307
+ gpu_metrics_dict = {
308
+ "freq_MHz": int(gpu_metrics["freq_hz"]),
309
+ "active": int((1 - gpu_metrics["idle_ratio"])*100),
310
+ }
311
+ return gpu_metrics_dict
312
+
313
+ def parse_disk_metrics(powermetrics_parse):
314
+ disk_metrics = powermetrics_parse["disk"]
315
+ disk_metrics_dict = {
316
+ "read_iops": int(disk_metrics["rops_per_s"]),
317
+ "write_iops": int(disk_metrics["wops_per_s"]),
318
+ "read_Bps": int(disk_metrics["rbytes_per_s"]),
319
+ "write_Bps": int(disk_metrics["wbytes_per_s"]),
320
+ }
321
+ return disk_metrics_dict
322
+
323
+ def parse_network_metrics(powermetrics_parse):
324
+ network_metrics = powermetrics_parse["network"]
325
+ network_metrics_dict = {
326
+ "out_Bps": int(network_metrics["obyte_rate"]),
327
+ "in_Bps": int(network_metrics["ibyte_rate"]),
328
+ }
329
+ return network_metrics_dict
330
+
22
331
 
23
332
  def main():
24
333
  print("\nmacpm - Performance monitoring CLI tool for Apple Silicon")
@@ -27,7 +336,7 @@ def main():
27
336
  print("P.S. You are recommended to run macpm with `sudo macpm`\n")
28
337
  print("\n[1/3] Loading macpm\n")
29
338
  print("\033[?25l")
30
-
339
+ global powermetrics_process
31
340
  cpu1_gauge = HGauge(title="E-CPU Usage", val=0, color=args.color)
32
341
  cpu2_gauge = HGauge(title="P-CPU Usage", val=0, color=args.color)
33
342
  gpu_gauge = HGauge(title="GPU Usage", val=0, color=args.color)
@@ -105,16 +414,16 @@ def main():
105
414
  )
106
415
 
107
416
  disk_read_iops_charts = HChart(title="read iops", color=args.color)
108
- disk_write_iops_charts = HBrailleFilledChart(title="write iops", color=args.color)
417
+ disk_write_iops_charts = HChart(title="write iops", color=args.color)
109
418
  disk_read_bps_charts = HChart(title="read Bps", color=args.color)
110
- disk_write_bps_charts = HBrailleFilledChart(title="write Bps", color=args.color)
419
+ disk_write_bps_charts = HChart(title="write Bps", color=args.color)
111
420
  network_in_bps_charts = HChart(title="in Bps", color=args.color)
112
- network_out_bps_charts = HBrailleFilledChart(title="out Bps", color=args.color)
421
+ network_out_bps_charts = HChart(title="out Bps", color=args.color)
113
422
  disk_io_charts = HSplit(
114
- disk_read_iops_charts,
115
- disk_write_iops_charts,
116
- disk_read_bps_charts,
117
- disk_write_bps_charts,
423
+ VSplit(disk_read_iops_charts,
424
+ disk_write_iops_charts,),
425
+ VSplit(disk_read_bps_charts,
426
+ disk_write_bps_charts,),
118
427
  title="Disk IO",
119
428
  color=args.color,
120
429
  border_color=args.color)
@@ -141,7 +450,13 @@ def main():
141
450
  disk_io_charts,
142
451
  network_io_charts,
143
452
  )
144
-
453
+ """
454
+ ui.title = "".join([
455
+ version,
456
+ " (Press q or ESC to stop)"
457
+ ])
458
+ ui.border_color = args.color
459
+ """
145
460
  usage_gauges = ui.items[0]
146
461
  #bw_gauges = memory_gauges.items[1]
147
462
 
@@ -158,7 +473,7 @@ def main():
158
473
  usage_gauges.title = cpu_title
159
474
  cpu_max_power = soc_info_dict["cpu_max_power"]
160
475
  gpu_max_power = soc_info_dict["gpu_max_power"]
161
- ane_max_power = 8.0
476
+ ane_max_power = 16.0
162
477
  """max_cpu_bw = soc_info_dict["cpu_max_bw"]
163
478
  max_gpu_bw = soc_info_dict["gpu_max_bw"]
164
479
  max_media_bw = 7.0"""
@@ -175,13 +490,21 @@ def main():
175
490
 
176
491
  print("\n[2/3] Starting powermetrics process\n")
177
492
 
178
- timecode = str(int(time.time()))
179
-
180
- powermetrics_process = run_powermetrics_process(timecode,
181
- interval=args.interval * 1000)
493
+ command = " ".join([
494
+ "sudo nice -n",
495
+ str(10),
496
+ "powermetrics",
497
+ "--samplers cpu_power,gpu_power,thermal,network,disk",
498
+ "-f plist",
499
+ "-i",
500
+ str(args.interval * 1000)
501
+ ])
502
+ process = subprocess.Popen(command.split(" "), stdin=PIPE, stdout=PIPE)
503
+
504
+ powermetrics_process = process
182
505
 
183
506
  print("\n[3/3] Waiting for first reading...\n")
184
-
507
+ """
185
508
  def get_reading(wait=0.1):
186
509
  ready = parse_powermetrics(timecode=timecode)
187
510
  while not ready:
@@ -191,7 +514,7 @@ def main():
191
514
 
192
515
  ready = get_reading()
193
516
  last_timestamp = ready[-1]
194
-
517
+ """
195
518
  def get_avg(inlist):
196
519
  avg = sum(inlist) / len(inlist)
197
520
  return avg
@@ -201,25 +524,29 @@ def main():
201
524
  avg_gpu_power_list = deque([], maxlen=int(args.avg / args.interval))
202
525
 
203
526
  clear_console()
204
-
205
- count=0
527
+ term = Terminal()
206
528
  try:
529
+ data = b''
207
530
  while True:
208
- if args.max_count > 0:
209
- if count >= args.max_count:
210
- count = 0
211
- powermetrics_process.terminate()
212
- timecode = str(int(time.time()))
213
- powermetrics_process = run_powermetrics_process(
214
- timecode, interval=args.interval * 1000)
215
- count += 1
216
- ready = parse_powermetrics(timecode=timecode)
217
- if ready:
218
- cpu_metrics_dict, gpu_metrics_dict, thermal_pressure, bandwidth_metrics, disk_metrics_dict, network_metrics_dict, timestamp = ready
219
-
220
- if timestamp > last_timestamp:
221
- last_timestamp = timestamp
222
-
531
+ output = process.stdout.readline()
532
+ #output, stderr = process.communicate()
533
+ if process.poll() is not None:
534
+ break
535
+ data = data + output
536
+ str_output = output.decode()
537
+ if str_output.startswith('</plist>'):
538
+ data = data.replace(b'\x00',b'')
539
+ powermetrics_parse = plistlib.loads(data)
540
+ thermal_pressure = parse_thermal_pressure(powermetrics_parse)
541
+ cpu_metrics_dict = parse_cpu_metrics(powermetrics_parse)
542
+ gpu_metrics_dict = parse_gpu_metrics(powermetrics_parse)
543
+ disk_metrics_dict = parse_disk_metrics(powermetrics_parse)
544
+ network_metrics_dict = parse_network_metrics(powermetrics_parse)
545
+ #bandwidth_metrics = parse_bandwidth_metrics(powermetrics_parse)
546
+ bandwidth_metrics = None
547
+ timestamp = powermetrics_parse["timestamp"]
548
+ data = b''
549
+ if timestamp :
223
550
  if thermal_pressure == "Nominal":
224
551
  thermal_throttle = "no"
225
552
  else:
@@ -285,14 +612,16 @@ def main():
285
612
  ])
286
613
  gpu_gauge.value = gpu_metrics_dict["active"]
287
614
 
615
+ ane_power_W = cpu_metrics_dict["ane_W"] / args.interval
616
+ if ane_power_W > ane_max_power:
617
+ ane_max_power = ane_power_W
288
618
  ane_util_percent = int(
289
- cpu_metrics_dict["ane_W"] / args.interval / ane_max_power * 100)
619
+ ane_power_W / ane_max_power * 100)
290
620
  ane_gauge.title = "".join([
291
621
  "ANE Usage: ",
292
622
  str(ane_util_percent),
293
623
  "% @ ",
294
- '{0:.1f}'.format(
295
- cpu_metrics_dict["ane_W"] / args.interval),
624
+ '{0:.1f}'.format(ane_power_W),
296
625
  " W"
297
626
  ])
298
627
  ane_gauge.value = ane_util_percent
@@ -408,11 +737,13 @@ def main():
408
737
  thermal_throttle,
409
738
  ])
410
739
 
411
- cpu_power_percent = int(
412
- cpu_metrics_dict["cpu_W"] / args.interval / cpu_max_power * 100)
413
740
  cpu_power_W = cpu_metrics_dict["cpu_W"] / args.interval
414
741
  if cpu_power_W > cpu_peak_power:
415
742
  cpu_peak_power = cpu_power_W
743
+ if cpu_power_W > cpu_max_power:
744
+ cpu_max_power = cpu_power_W
745
+ cpu_power_percent = int(
746
+ cpu_power_W / cpu_max_power * 100)
416
747
  avg_cpu_power_list.append(cpu_power_W)
417
748
  avg_cpu_power = get_avg(avg_cpu_power_list)
418
749
  cpu_power_chart.title = "".join([
@@ -426,11 +757,13 @@ def main():
426
757
  ])
427
758
  cpu_power_chart.append(cpu_power_percent)
428
759
 
429
- gpu_power_percent = int(
430
- cpu_metrics_dict["gpu_W"] / args.interval / gpu_max_power * 100)
431
760
  gpu_power_W = cpu_metrics_dict["gpu_W"] / args.interval
432
761
  if gpu_power_W > gpu_peak_power:
433
762
  gpu_peak_power = gpu_power_W
763
+ if gpu_power_W > gpu_max_power:
764
+ gpu_max_power = gpu_power_W
765
+ gpu_power_percent = int(
766
+ gpu_power_W / gpu_max_power * 100)
434
767
  avg_gpu_power_list.append(gpu_power_W)
435
768
  avg_gpu_power = get_avg(avg_gpu_power_list)
436
769
  gpu_power_chart.title = "".join([
@@ -452,7 +785,7 @@ def main():
452
785
  disk_read_iops_peak = disk_read_iops
453
786
  disk_read_iops_charts.title = "Read iops: "+ f'{disk_read_iops} (peak: {disk_read_iops_peak})'
454
787
  if disk_read_iops_charts.datapoints:
455
- disk_read_iops_rate = int(disk_read_iops / disk_read_iops_peak * 100)
788
+ disk_read_iops_rate = int(disk_read_iops / disk_read_iops_peak * 100) if disk_read_iops_peak > 0 else 0
456
789
  else:
457
790
  disk_read_iops_rate = 100
458
791
  disk_read_iops_charts.append(disk_read_iops_rate)
@@ -462,7 +795,7 @@ def main():
462
795
  disk_write_iops_peak = disk_write_iops
463
796
  disk_write_iops_charts.title = "Write iops: "+ f'{disk_write_iops} (peak: {disk_write_iops_peak})'
464
797
  if disk_write_iops_charts.datapoints:
465
- disk_write_iops_rate = int(disk_read_iops / disk_write_iops_peak * 100)
798
+ disk_write_iops_rate = int(disk_read_iops / disk_write_iops_peak * 100) if disk_write_iops_peak > 0 else 0
466
799
  else:
467
800
  disk_write_iops_rate = 100
468
801
  disk_write_iops_charts.append(disk_write_iops_rate)
@@ -472,7 +805,7 @@ def main():
472
805
  disk_read_bps_peak = disk_read_bps
473
806
  disk_read_bps_charts.title = "Read : "+ f'{format_number(disk_read_bps)}/s (peak: {format_number(disk_read_bps_peak)}/s)'
474
807
  if disk_read_bps_charts.datapoints:
475
- disk_read_bps_rate = int(disk_read_bps / disk_read_bps_peak * 100)
808
+ disk_read_bps_rate = int(disk_read_bps / disk_read_bps_peak * 100) if disk_read_bps_peak > 0 else 0
476
809
  else:
477
810
  disk_read_bps_rate = 100
478
811
  disk_read_bps_charts.append(disk_read_bps_rate)
@@ -482,7 +815,7 @@ def main():
482
815
  disk_write_bps_peak = disk_write_bps
483
816
  disk_write_bps_charts.title = "Write : "+ f'{format_number(disk_write_bps)}/s (peak: {format_number(disk_write_bps_peak)}/s)'
484
817
  if disk_write_bps_charts.datapoints:
485
- disk_write_bps_rate = int(disk_write_bps / disk_write_bps_peak * 100)
818
+ disk_write_bps_rate = int(disk_write_bps / disk_write_bps_peak * 100) if disk_write_bps_peak > 0 else 0
486
819
  else:
487
820
  disk_write_bps_rate = 100
488
821
  disk_write_bps_charts.append(disk_write_bps_rate)
@@ -492,7 +825,7 @@ def main():
492
825
  network_in_bps_peak = network_in_bps
493
826
  network_in_bps_charts.title = "in : "+ f'{format_number(network_in_bps)}/s (peak: {format_number(network_in_bps_peak)}/s)'
494
827
  if network_in_bps_charts.datapoints:
495
- network_in_bps_rate = int(network_in_bps / network_in_bps_peak * 100)
828
+ network_in_bps_rate = int(network_in_bps / network_in_bps_peak * 100) if network_in_bps_peak > 0 else 0
496
829
  else:
497
830
  network_in_bps_rate = 100
498
831
  network_in_bps_charts.append(network_in_bps_rate)
@@ -502,24 +835,37 @@ def main():
502
835
  network_out_bps_peak = network_out_bps
503
836
  network_out_bps_charts.title = "out : "+ f'{format_number(network_out_bps)}/s (peak: {format_number(network_out_bps_peak)}/s)'
504
837
  if network_out_bps_charts.datapoints:
505
- network_out_bps_rate = int(network_out_bps / network_out_bps_peak * 100)
838
+ network_out_bps_rate = int(network_out_bps / network_out_bps_peak * 100) if network_out_bps_peak > 0 else 0
506
839
  else:
507
840
  network_out_bps_rate = 100
508
841
  network_out_bps_charts.append(network_out_bps_rate)
509
842
 
510
843
  ui.display()
511
-
512
- time.sleep(args.interval)
844
+ key_cmd = ''
845
+ with term.cbreak():
846
+ key = term.inkey(timeout=1)
847
+ if key:
848
+ if key.is_sequence:
849
+ if key.name == 'KEY_ESCAPE':
850
+ key_cmd = "quit"
851
+ elif key.lower() == 'q':
852
+ key_cmd = "quit"
853
+ if key_cmd == "quit":
854
+ print("\nStopping...")
855
+ break
856
+
857
+ if str_output == '':
858
+ time.sleep(0.1)
513
859
 
514
860
  except KeyboardInterrupt:
515
861
  print("Stopping...")
516
862
  print("\033[?25h")
517
863
 
518
- return powermetrics_process
864
+ return
519
865
 
520
866
 
521
867
  if __name__ == "__main__":
522
- powermetrics_process = main()
868
+ main()
523
869
  try:
524
870
  powermetrics_process.terminate()
525
871
  print("Successfully terminated powermetrics process")
@@ -527,3 +873,4 @@ if __name__ == "__main__":
527
873
  print(e)
528
874
  powermetrics_process.terminate()
529
875
  print("Successfully terminated powermetrics process")
876
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: macpm
3
- Version: 0.12
3
+ Version: 0.14
4
4
  Summary: Performance monitoring CLI tool for Apple Silicon
5
5
  Home-page: https://github.com/visualcjy/macpm
6
6
  Author: Jinyu Chen
@@ -3,8 +3,6 @@ README.md
3
3
  setup.py
4
4
  macpm/__init__.py
5
5
  macpm/macpm.py
6
- macpm/parsers.py
7
- macpm/utils.py
8
6
  macpm.egg-info/PKG-INFO
9
7
  macpm.egg-info/SOURCES.txt
10
8
  macpm.egg-info/dependency_links.txt
@@ -4,7 +4,7 @@ long_description = 'Performance monitoring CLI tool for Apple Silicon'
4
4
 
5
5
  setup(
6
6
  name='macpm',
7
- version='0.12',
7
+ version='0.14',
8
8
  author='Jinyu Chen',
9
9
  author_email='visualcjy@mail.com',
10
10
  url='https://github.com/visualcjy/macpm',
@@ -13,7 +13,6 @@ setup(
13
13
  long_description_content_type="text/markdown",
14
14
  license='MIT',
15
15
  packages=find_packages(),
16
- package_dir={'macpm':'macpm'},
17
16
  entry_points={
18
17
  'console_scripts': [
19
18
  'macpm = macpm.macpm:main'
@@ -1,171 +0,0 @@
1
- def parse_thermal_pressure(powermetrics_parse):
2
- return powermetrics_parse["thermal_pressure"]
3
-
4
-
5
- def parse_bandwidth_metrics(powermetrics_parse):
6
- bandwidth_metrics = powermetrics_parse["bandwidth_counters"]
7
- bandwidth_metrics_dict = {}
8
- data_fields = ["PCPU0 DCS RD", "PCPU0 DCS WR",
9
- "PCPU1 DCS RD", "PCPU1 DCS WR",
10
- "PCPU2 DCS RD", "PCPU2 DCS WR",
11
- "PCPU3 DCS RD", "PCPU3 DCS WR",
12
- "PCPU DCS RD", "PCPU DCS WR",
13
- "ECPU0 DCS RD", "ECPU0 DCS WR",
14
- "ECPU1 DCS RD", "ECPU1 DCS WR",
15
- "ECPU DCS RD", "ECPU DCS WR",
16
- "GFX DCS RD", "GFX DCS WR",
17
- "ISP DCS RD", "ISP DCS WR",
18
- "STRM CODEC DCS RD", "STRM CODEC DCS WR",
19
- "PRORES DCS RD", "PRORES DCS WR",
20
- "VDEC DCS RD", "VDEC DCS WR",
21
- "VENC0 DCS RD", "VENC0 DCS WR",
22
- "VENC1 DCS RD", "VENC1 DCS WR",
23
- "VENC2 DCS RD", "VENC2 DCS WR",
24
- "VENC3 DCS RD", "VENC3 DCS WR",
25
- "VENC DCS RD", "VENC DCS WR",
26
- "JPG0 DCS RD", "JPG0 DCS WR",
27
- "JPG1 DCS RD", "JPG1 DCS WR",
28
- "JPG2 DCS RD", "JPG2 DCS WR",
29
- "JPG3 DCS RD", "JPG3 DCS WR",
30
- "JPG DCS RD", "JPG DCS WR",
31
- "DCS RD", "DCS WR"]
32
- for h in data_fields:
33
- bandwidth_metrics_dict[h] = 0
34
- for l in bandwidth_metrics:
35
- if l["name"] in data_fields:
36
- bandwidth_metrics_dict[l["name"]] = l["value"]/(1e9)
37
- bandwidth_metrics_dict["PCPU DCS RD"] = bandwidth_metrics_dict["PCPU DCS RD"] + \
38
- bandwidth_metrics_dict["PCPU0 DCS RD"] + \
39
- bandwidth_metrics_dict["PCPU1 DCS RD"] + \
40
- bandwidth_metrics_dict["PCPU2 DCS RD"] + \
41
- bandwidth_metrics_dict["PCPU3 DCS RD"]
42
- bandwidth_metrics_dict["PCPU DCS WR"] = bandwidth_metrics_dict["PCPU DCS WR"] + \
43
- bandwidth_metrics_dict["PCPU0 DCS WR"] + \
44
- bandwidth_metrics_dict["PCPU1 DCS WR"] + \
45
- bandwidth_metrics_dict["PCPU2 DCS WR"] + \
46
- bandwidth_metrics_dict["PCPU3 DCS WR"]
47
- bandwidth_metrics_dict["JPG DCS RD"] = bandwidth_metrics_dict["JPG DCS RD"] + \
48
- bandwidth_metrics_dict["JPG0 DCS RD"] + \
49
- bandwidth_metrics_dict["JPG1 DCS RD"] + \
50
- bandwidth_metrics_dict["JPG2 DCS RD"] + \
51
- bandwidth_metrics_dict["JPG3 DCS RD"]
52
- bandwidth_metrics_dict["JPG DCS WR"] = bandwidth_metrics_dict["JPG DCS WR"] + \
53
- bandwidth_metrics_dict["JPG0 DCS WR"] + \
54
- bandwidth_metrics_dict["JPG1 DCS WR"] + \
55
- bandwidth_metrics_dict["JPG2 DCS WR"] + \
56
- bandwidth_metrics_dict["JPG3 DCS WR"]
57
- bandwidth_metrics_dict["VENC DCS RD"] = bandwidth_metrics_dict["VENC DCS RD"] + \
58
- bandwidth_metrics_dict["VENC0 DCS RD"] + \
59
- bandwidth_metrics_dict["VENC1 DCS RD"] + \
60
- bandwidth_metrics_dict["VENC2 DCS RD"] + \
61
- bandwidth_metrics_dict["VENC3 DCS RD"]
62
- bandwidth_metrics_dict["VENC DCS WR"] = bandwidth_metrics_dict["VENC DCS WR"] + \
63
- bandwidth_metrics_dict["VENC0 DCS WR"] + \
64
- bandwidth_metrics_dict["VENC1 DCS WR"] + \
65
- bandwidth_metrics_dict["VENC2 DCS WR"] + \
66
- bandwidth_metrics_dict["VENC3 DCS WR"]
67
- bandwidth_metrics_dict["MEDIA DCS"] = sum([
68
- bandwidth_metrics_dict["ISP DCS RD"], bandwidth_metrics_dict["ISP DCS WR"],
69
- bandwidth_metrics_dict["STRM CODEC DCS RD"], bandwidth_metrics_dict["STRM CODEC DCS WR"],
70
- bandwidth_metrics_dict["PRORES DCS RD"], bandwidth_metrics_dict["PRORES DCS WR"],
71
- bandwidth_metrics_dict["VDEC DCS RD"], bandwidth_metrics_dict["VDEC DCS WR"],
72
- bandwidth_metrics_dict["VENC DCS RD"], bandwidth_metrics_dict["VENC DCS WR"],
73
- bandwidth_metrics_dict["JPG DCS RD"], bandwidth_metrics_dict["JPG DCS WR"],
74
- ])
75
- return bandwidth_metrics_dict
76
-
77
-
78
- def parse_cpu_metrics(powermetrics_parse):
79
- e_core = []
80
- p_core = []
81
- cpu_metrics = powermetrics_parse["processor"]
82
- cpu_metric_dict = {}
83
- # cpu_clusters
84
- cpu_clusters = cpu_metrics["clusters"]
85
- e_total_idle_ratio = 0
86
- e_core_count = 0
87
- p_total_idle_ratio = 0
88
- p_core_count = 0
89
- for cluster in cpu_clusters:
90
- name = cluster["name"]
91
- cpu_metric_dict[name+"_freq_Mhz"] = int(cluster["freq_hz"]/(1e6))
92
- cpu_metric_dict[name+"_active"] = int((1 - cluster["idle_ratio"])*100)
93
- for cpu in cluster["cpus"]:
94
- name = 'E-Cluster' if name[0] == 'E' else 'P-Cluster'
95
- core = e_core if name[0] == 'E' else p_core
96
- core.append(cpu["cpu"])
97
- cpu_metric_dict[name + str(cpu["cpu"]) + "_freq_Mhz"] = int(cpu["freq_hz"] / (1e6))
98
- cpu_metric_dict[name + str(cpu["cpu"]) + "_active"] = int((1 - cpu["idle_ratio"]) * 100)
99
- if name[0] == 'E':
100
- e_total_idle_ratio += cluster["down_ratio"] + (1 - cluster["down_ratio"]) * (cpu["idle_ratio"] + cpu["down_ratio"])
101
- e_core_count += 1
102
- else:
103
- p_total_idle_ratio += cluster["down_ratio"] + (1 - cluster["down_ratio"]) * (cpu["idle_ratio"] + cpu["down_ratio"])
104
- p_core_count += 1
105
-
106
- cpu_metric_dict["E-Cluster_active"] = int((1 - e_total_idle_ratio/e_core_count)*100)
107
- cpu_metric_dict["P-Cluster_active"] = int((1 - p_total_idle_ratio/p_core_count)*100)
108
- cpu_metric_dict["e_core"] = e_core
109
- cpu_metric_dict["p_core"] = p_core
110
- if "E-Cluster_active" not in cpu_metric_dict:
111
- # M1 Ultra
112
- cpu_metric_dict["E-Cluster_active"] = int(
113
- (cpu_metric_dict["E0-Cluster_active"] + cpu_metric_dict["E1-Cluster_active"])/2)
114
- if "E-Cluster_freq_Mhz" not in cpu_metric_dict:
115
- # M1 Ultra
116
- cpu_metric_dict["E-Cluster_freq_Mhz"] = max(
117
- cpu_metric_dict["E0-Cluster_freq_Mhz"], cpu_metric_dict["E1-Cluster_freq_Mhz"])
118
- if "P-Cluster_active" not in cpu_metric_dict:
119
- if "P2-Cluster_active" in cpu_metric_dict:
120
- # M1 Ultra
121
- cpu_metric_dict["P-Cluster_active"] = int((cpu_metric_dict["P0-Cluster_active"] + cpu_metric_dict["P1-Cluster_active"] +
122
- cpu_metric_dict["P2-Cluster_active"] + cpu_metric_dict["P3-Cluster_active"]) / 4)
123
- else:
124
- cpu_metric_dict["P-Cluster_active"] = int(
125
- (cpu_metric_dict["P0-Cluster_active"] + cpu_metric_dict["P1-Cluster_active"])/2)
126
- if "P-Cluster_freq_Mhz" not in cpu_metric_dict:
127
- if "P2-Cluster_freq_Mhz" in cpu_metric_dict:
128
- # M1 Ultra
129
- freqs = [
130
- cpu_metric_dict["P0-Cluster_freq_Mhz"],
131
- cpu_metric_dict["P1-Cluster_freq_Mhz"],
132
- cpu_metric_dict["P2-Cluster_freq_Mhz"],
133
- cpu_metric_dict["P3-Cluster_freq_Mhz"]]
134
- cpu_metric_dict["P-Cluster_freq_Mhz"] = max(freqs)
135
- else:
136
- cpu_metric_dict["P-Cluster_freq_Mhz"] = max(
137
- cpu_metric_dict["P0-Cluster_freq_Mhz"], cpu_metric_dict["P1-Cluster_freq_Mhz"])
138
- # power
139
- cpu_metric_dict["ane_W"] = cpu_metrics["ane_energy"]/1000
140
- #cpu_metric_dict["dram_W"] = cpu_metrics["dram_energy"]/1000
141
- cpu_metric_dict["cpu_W"] = cpu_metrics["cpu_energy"]/1000
142
- cpu_metric_dict["gpu_W"] = cpu_metrics["gpu_energy"]/1000
143
- cpu_metric_dict["package_W"] = cpu_metrics["combined_power"]/1000
144
- return cpu_metric_dict
145
-
146
-
147
- def parse_gpu_metrics(powermetrics_parse):
148
- gpu_metrics = powermetrics_parse["gpu"]
149
- gpu_metrics_dict = {
150
- "freq_MHz": int(gpu_metrics["freq_hz"]),
151
- "active": int((1 - gpu_metrics["idle_ratio"])*100),
152
- }
153
- return gpu_metrics_dict
154
-
155
- def parse_disk_metrics(powermetrics_parse):
156
- disk_metrics = powermetrics_parse["disk"]
157
- disk_metrics_dict = {
158
- "read_iops": int(disk_metrics["rops_per_s"]),
159
- "write_iops": int(disk_metrics["wops_per_s"]),
160
- "read_Bps": int(disk_metrics["rbytes_per_s"]),
161
- "write_Bps": int(disk_metrics["wbytes_per_s"]),
162
- }
163
- return disk_metrics_dict
164
-
165
- def parse_network_metrics(powermetrics_parse):
166
- network_metrics = powermetrics_parse["network"]
167
- network_metrics_dict = {
168
- "out_Bps": int(network_metrics["obyte_rate"]),
169
- "in_Bps": int(network_metrics["ibyte_rate"]),
170
- }
171
- return network_metrics_dict
macpm-0.12/macpm/utils.py DELETED
@@ -1,192 +0,0 @@
1
- import os
2
- import glob
3
- import subprocess
4
- from subprocess import PIPE
5
- import psutil
6
- from .parsers import *
7
- import plistlib
8
-
9
-
10
- def parse_powermetrics(path='/tmp/asitop_powermetrics', timecode="0"):
11
- data = None
12
- try:
13
- with open(path+timecode, 'rb') as fp:
14
- data = fp.read()
15
- data = data.split(b'\x00')
16
- powermetrics_parse = plistlib.loads(data[-1])
17
- thermal_pressure = parse_thermal_pressure(powermetrics_parse)
18
- cpu_metrics_dict = parse_cpu_metrics(powermetrics_parse)
19
- gpu_metrics_dict = parse_gpu_metrics(powermetrics_parse)
20
- disk_metrics_dict = parse_disk_metrics(powermetrics_parse)
21
- network_metrics_dict = parse_network_metrics(powermetrics_parse)
22
- #bandwidth_metrics = parse_bandwidth_metrics(powermetrics_parse)
23
- bandwidth_metrics = None
24
- timestamp = powermetrics_parse["timestamp"]
25
- return cpu_metrics_dict, gpu_metrics_dict, thermal_pressure, bandwidth_metrics, disk_metrics_dict, network_metrics_dict, timestamp
26
- except Exception as e:
27
- if data:
28
- if len(data) > 1:
29
- powermetrics_parse = plistlib.loads(data[-2])
30
- thermal_pressure = parse_thermal_pressure(powermetrics_parse)
31
- cpu_metrics_dict = parse_cpu_metrics(powermetrics_parse)
32
- gpu_metrics_dict = parse_gpu_metrics(powermetrics_parse)
33
- disk_metrics_dict = parse_disk_metrics(powermetrics_parse)
34
- network_metrics_dict = parse_network_metrics(powermetrics_parse)
35
- #bandwidth_metrics = parse_bandwidth_metrics(powermetrics_parse)
36
- bandwidth_metrics = None
37
- timestamp = powermetrics_parse["timestamp"]
38
- return cpu_metrics_dict, gpu_metrics_dict, thermal_pressure, bandwidth_metrics, disk_metrics_dict, network_metrics_dict, timestamp
39
- return False
40
-
41
-
42
- def clear_console():
43
- command = 'clear'
44
- os.system(command)
45
-
46
-
47
- def convert_to_GB(value):
48
- return round(value/1024/1024/1024, 1)
49
-
50
-
51
- def run_powermetrics_process(timecode, nice=10, interval=1000):
52
- #ver, *_ = platform.mac_ver()
53
- #major_ver = int(ver.split(".")[0])
54
- #for tmpf in glob.glob("/tmp/asitop_powermetrics*"):
55
- # os.remove(tmpf)
56
- output_file_flag = "-o"
57
- command = " ".join([
58
- "sudo nice -n",
59
- str(nice),
60
- "powermetrics",
61
- "--samplers cpu_power,gpu_power,thermal,network,disk",
62
- output_file_flag,
63
- "/tmp/asitop_powermetrics"+timecode,
64
- "-f plist",
65
- "-i",
66
- str(interval)
67
- ])
68
- process = subprocess.Popen(command.split(" "), stdin=PIPE, stdout=PIPE)
69
- return process
70
-
71
-
72
- def get_ram_metrics_dict():
73
- ram_metrics = psutil.virtual_memory()
74
- swap_metrics = psutil.swap_memory()
75
- total_GB = convert_to_GB(ram_metrics.total)
76
- free_GB = convert_to_GB(ram_metrics.available)
77
- used_GB = convert_to_GB(ram_metrics.total-ram_metrics.available)
78
- swap_total_GB = convert_to_GB(swap_metrics.total)
79
- swap_used_GB = convert_to_GB(swap_metrics.used)
80
- swap_free_GB = convert_to_GB(swap_metrics.total-swap_metrics.used)
81
- if swap_total_GB > 0:
82
- swap_free_percent = int(100-(swap_free_GB/swap_total_GB*100))
83
- else:
84
- swap_free_percent = None
85
- ram_metrics_dict = {
86
- "total_GB": round(total_GB, 1),
87
- "free_GB": round(free_GB, 1),
88
- "used_GB": round(used_GB, 1),
89
- "free_percent": int(100-(ram_metrics.available/ram_metrics.total*100)),
90
- "swap_total_GB": swap_total_GB,
91
- "swap_used_GB": swap_used_GB,
92
- "swap_free_GB": swap_free_GB,
93
- "swap_free_percent": swap_free_percent,
94
- }
95
- return ram_metrics_dict
96
-
97
-
98
- def get_cpu_info():
99
- cpu_info = os.popen('sysctl -a | grep machdep.cpu').read()
100
- cpu_info_lines = cpu_info.split("\n")
101
- data_fields = ["machdep.cpu.brand_string", "machdep.cpu.core_count"]
102
- cpu_info_dict = {}
103
- for l in cpu_info_lines:
104
- for h in data_fields:
105
- if h in l:
106
- value = l.split(":")[1].strip()
107
- cpu_info_dict[h] = value
108
- return cpu_info_dict
109
-
110
-
111
- def get_core_counts():
112
- cores_info = os.popen('sysctl -a | grep hw.perflevel').read()
113
- cores_info_lines = cores_info.split("\n")
114
- data_fields = ["hw.perflevel0.logicalcpu", "hw.perflevel1.logicalcpu"]
115
- cores_info_dict = {}
116
- for l in cores_info_lines:
117
- for h in data_fields:
118
- if h in l:
119
- value = int(l.split(":")[1].strip())
120
- cores_info_dict[h] = value
121
- return cores_info_dict
122
-
123
-
124
- def get_gpu_cores():
125
- try:
126
- cores = os.popen(
127
- "system_profiler -detailLevel basic SPDisplaysDataType | grep 'Total Number of Cores'").read()
128
- cores = int(cores.split(": ")[-1])
129
- except:
130
- cores = "?"
131
- return cores
132
-
133
-
134
- def get_soc_info():
135
- cpu_info_dict = get_cpu_info()
136
- core_counts_dict = get_core_counts()
137
- try:
138
- e_core_count = core_counts_dict["hw.perflevel1.logicalcpu"]
139
- p_core_count = core_counts_dict["hw.perflevel0.logicalcpu"]
140
- except:
141
- e_core_count = "?"
142
- p_core_count = "?"
143
- soc_info = {
144
- "name": cpu_info_dict["machdep.cpu.brand_string"],
145
- "core_count": int(cpu_info_dict["machdep.cpu.core_count"]),
146
- "cpu_max_power": None,
147
- "gpu_max_power": None,
148
- "cpu_max_bw": None,
149
- "gpu_max_bw": None,
150
- "e_core_count": e_core_count,
151
- "p_core_count": p_core_count,
152
- "gpu_core_count": get_gpu_cores()
153
- }
154
- # TDP (power)
155
- if soc_info["name"] == "Apple M1 Max":
156
- soc_info["cpu_max_power"] = 30
157
- soc_info["gpu_max_power"] = 60
158
- elif soc_info["name"] == "Apple M1 Pro":
159
- soc_info["cpu_max_power"] = 30
160
- soc_info["gpu_max_power"] = 30
161
- elif soc_info["name"] == "Apple M1":
162
- soc_info["cpu_max_power"] = 20
163
- soc_info["gpu_max_power"] = 20
164
- elif soc_info["name"] == "Apple M1 Ultra":
165
- soc_info["cpu_max_power"] = 60
166
- soc_info["gpu_max_power"] = 120
167
- elif soc_info["name"] == "Apple M2":
168
- soc_info["cpu_max_power"] = 25
169
- soc_info["gpu_max_power"] = 15
170
- else:
171
- soc_info["cpu_max_power"] = 20
172
- soc_info["gpu_max_power"] = 20
173
- # bandwidth
174
- if soc_info["name"] == "Apple M1 Max":
175
- soc_info["cpu_max_bw"] = 250
176
- soc_info["gpu_max_bw"] = 400
177
- elif soc_info["name"] == "Apple M1 Pro":
178
- soc_info["cpu_max_bw"] = 200
179
- soc_info["gpu_max_bw"] = 200
180
- elif soc_info["name"] == "Apple M1":
181
- soc_info["cpu_max_bw"] = 70
182
- soc_info["gpu_max_bw"] = 70
183
- elif soc_info["name"] == "Apple M1 Ultra":
184
- soc_info["cpu_max_bw"] = 500
185
- soc_info["gpu_max_bw"] = 800
186
- elif soc_info["name"] == "Apple M2":
187
- soc_info["cpu_max_bw"] = 100
188
- soc_info["gpu_max_bw"] = 100
189
- else:
190
- soc_info["cpu_max_bw"] = 70
191
- soc_info["gpu_max_bw"] = 70
192
- return soc_info
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes