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