New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

macpm

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

macpm - pypi Package Compare versions

Comparing version
0.14
to
0.15
+1
-1
macpm.egg-info/PKG-INFO
Metadata-Version: 2.1
Name: macpm
Version: 0.14
Version: 0.15
Summary: Performance monitoring CLI tool for Apple Silicon

@@ -5,0 +5,0 @@ Home-page: https://github.com/visualcjy/macpm

import argparse
import humanize
from collections import deque
from blessed import Terminal
from dashing import VSplit, HSplit, HGauge, HChart, VGauge, HBrailleChart, HBrailleFilledChart

@@ -11,4 +10,5 @@ import os, time

import plistlib
import curses
version = 'macpm v0.14'
version = 'macpm v0.15'
parser = argparse.ArgumentParser(

@@ -333,527 +333,547 @@ description=f'{version}: Performance monitoring CLI tool for Apple Silicon')

def main():
print("\nmacpm - Performance monitoring CLI tool for Apple Silicon")
print("You can update macpm by running `pip install macpm --upgrade`")
print("Get help at `https://github.com/visualcjy/macpm`")
print("P.S. You are recommended to run macpm with `sudo macpm`\n")
print("\n[1/3] Loading macpm\n")
print("\033[?25l")
global powermetrics_process
cpu1_gauge = HGauge(title="E-CPU Usage", val=0, color=args.color)
cpu2_gauge = HGauge(title="P-CPU Usage", val=0, color=args.color)
gpu_gauge = HGauge(title="GPU Usage", val=0, color=args.color)
ane_gauge = HGauge(title="ANE", val=0, color=args.color)
gpu_ane_gauges = [gpu_gauge, ane_gauge]
class DefaultView():
def __init__(self,soc_info_dict,args):
self.cpu_peak_power = 0
self.gpu_peak_power = 0
self.package_peak_power = 0
self.disk_read_iops_peak = 0
self.disk_write_iops_peak = 0
self.disk_read_bps_peak = 0
self.disk_write_bps_peak = 0
self.network_in_bps_peak = 0
self.network_out_bps_peak = 0
self.construct(soc_info_dict,args)
def construct(self,soc_info_dict,args):
self.cpu1_gauge = HGauge(title="E-CPU Usage", val=0, color=args.color)
self.cpu2_gauge = HGauge(title="P-CPU Usage", val=0, color=args.color)
self.gpu_gauge = HGauge(title="GPU Usage", val=0, color=args.color)
self.ane_gauge = HGauge(title="ANE", val=0, color=args.color)
self.gpu_ane_gauges = [self.gpu_gauge, self.ane_gauge]
self.e_core_count = soc_info_dict["e_core_count"]
self.e_core_gauges = [VGauge(val=0, color=args.color, border_color=args.color) for _ in range(self.e_core_count)]
self.p_core_count = soc_info_dict["p_core_count"]
self.p_core_gauges = [VGauge(val=0, color=args.color, border_color=args.color) for _ in range(min(self.p_core_count, 8))]
self.p_core_split = [HSplit(
*self.p_core_gauges,
)]
if self.p_core_count > 8:
self.p_core_gauges_ext = [VGauge(val=0, color=args.color, border_color=args.color) for _ in range(self.p_core_count - 8)]
self.p_core_split.append(HSplit(
*self.p_core_gauges_ext,
))
self.processor_gauges = [self.cpu1_gauge,
HSplit(*self.e_core_gauges),
self.cpu2_gauge,
*self.p_core_split,
*self.gpu_ane_gauges
] if args.show_cores else [
HSplit(self.cpu1_gauge, self.cpu2_gauge),
HSplit(*self.gpu_ane_gauges)
]
self.processor_split = VSplit(
*self.processor_gauges,
title="Processor Utilization",
border_color=args.color,
)
soc_info_dict = get_soc_info()
e_core_count = soc_info_dict["e_core_count"]
e_core_gauges = [VGauge(val=0, color=args.color, border_color=args.color) for _ in range(e_core_count)]
p_core_count = soc_info_dict["p_core_count"]
p_core_gauges = [VGauge(val=0, color=args.color, border_color=args.color) for _ in range(min(p_core_count, 8))]
p_core_split = [HSplit(
*p_core_gauges,
)]
if p_core_count > 8:
p_core_gauges_ext = [VGauge(val=0, color=args.color, border_color=args.color) for _ in range(p_core_count - 8)]
p_core_split.append(HSplit(
*p_core_gauges_ext,
))
processor_gauges = [cpu1_gauge,
HSplit(*e_core_gauges),
cpu2_gauge,
*p_core_split,
*gpu_ane_gauges
] if args.show_cores else [
HSplit(cpu1_gauge, cpu2_gauge),
HSplit(*gpu_ane_gauges)
]
processor_split = VSplit(
*processor_gauges,
title="Processor Utilization",
border_color=args.color,
)
ram_gauge = HGauge(title="RAM Usage", val=0, color=args.color)
"""
ecpu_bw_gauge = HGauge(title="E-CPU B/W", val=50, color=args.color)
pcpu_bw_gauge = HGauge(title="P-CPU B/W", val=50, color=args.color)
gpu_bw_gauge = HGauge(title="GPU B/W", val=50, color=args.color)
media_bw_gauge = HGauge(title="Media B/W", val=50, color=args.color)
bw_gauges = [HSplit(
ecpu_bw_gauge,
pcpu_bw_gauge,
),
HSplit(
gpu_bw_gauge,
media_bw_gauge,
)] if args.show_cores else [
HSplit(
self.ram_gauge = HGauge(title="RAM Usage", val=0, color=args.color)
"""
ecpu_bw_gauge = HGauge(title="E-CPU B/W", val=50, color=args.color)
pcpu_bw_gauge = HGauge(title="P-CPU B/W", val=50, color=args.color)
gpu_bw_gauge = HGauge(title="GPU B/W", val=50, color=args.color)
media_bw_gauge = HGauge(title="Media B/W", val=50, color=args.color)
bw_gauges = [HSplit(
ecpu_bw_gauge,
pcpu_bw_gauge,
gpu_bw_gauge,
media_bw_gauge,
)]
"""
memory_gauges = VSplit(
ram_gauge,
#*bw_gauges,
border_color=args.color,
title="Memory"
)
),
HSplit(
gpu_bw_gauge,
media_bw_gauge,
)] if args.show_cores else [
HSplit(
ecpu_bw_gauge,
pcpu_bw_gauge,
gpu_bw_gauge,
media_bw_gauge,
)]
"""
self.memory_gauges = VSplit(
self.ram_gauge,
#*bw_gauges,
border_color=args.color,
title="Memory"
)
cpu_power_chart = HChart(title="CPU Power", color=args.color)
gpu_power_chart = HChart(title="GPU Power", color=args.color)
power_charts = VSplit(
cpu_power_chart,
gpu_power_chart,
title="Power Chart",
border_color=args.color,
) if args.show_cores else HSplit(
cpu_power_chart,
gpu_power_chart,
title="Power Chart",
border_color=args.color,
)
self.cpu_power_chart = HChart(title="CPU Power", color=args.color)
self.gpu_power_chart = HChart(title="GPU Power", color=args.color)
self.power_charts = VSplit(
self.cpu_power_chart,
self.gpu_power_chart,
title="Power Chart",
border_color=args.color,
) if args.show_cores else HSplit(
self.cpu_power_chart,
self.gpu_power_chart,
title="Power Chart",
border_color=args.color,
)
disk_read_iops_charts = HChart(title="read iops", color=args.color)
disk_write_iops_charts = HChart(title="write iops", color=args.color)
disk_read_bps_charts = HChart(title="read Bps", color=args.color)
disk_write_bps_charts = HChart(title="write Bps", color=args.color)
network_in_bps_charts = HChart(title="in Bps", color=args.color)
network_out_bps_charts = HChart(title="out Bps", color=args.color)
disk_io_charts = HSplit(
VSplit(disk_read_iops_charts,
disk_write_iops_charts,),
VSplit(disk_read_bps_charts,
disk_write_bps_charts,),
title="Disk IO",
color=args.color,
border_color=args.color)
network_io_charts = HSplit(
network_in_bps_charts,
network_out_bps_charts,
title="Network IO",
color=args.color,
border_color=args.color)
ui = HSplit(
processor_split,
VSplit(
memory_gauges,
power_charts,
disk_io_charts,
network_io_charts,
self.disk_read_iops_charts = HChart(title="read iops", color=args.color)
self.disk_write_iops_charts = HChart(title="write iops", color=args.color)
self.disk_read_bps_charts = HChart(title="read Bps", color=args.color)
self.disk_write_bps_charts = HChart(title="write Bps", color=args.color)
self.network_in_bps_charts = HChart(title="in Bps", color=args.color)
self.network_out_bps_charts = HChart(title="out Bps", color=args.color)
self.disk_io_charts = HSplit(
VSplit(self.disk_read_iops_charts,
self.disk_write_iops_charts,),
VSplit(self.disk_read_bps_charts,
self.disk_write_bps_charts,),
title="Disk IO",
color=args.color,
border_color=args.color)
self.network_io_charts = HSplit(
self.network_in_bps_charts,
self.network_out_bps_charts,
title="Network IO",
color=args.color,
border_color=args.color)
self.ui = HSplit(
self.processor_split,
VSplit(
self.memory_gauges,
self.power_charts,
self.disk_io_charts,
self.network_io_charts,
)
) if args.show_cores else VSplit(
self.processor_split,
self.memory_gauges,
self.power_charts,
self.disk_io_charts,
self.network_io_charts,
)
) if args.show_cores else VSplit(
processor_split,
memory_gauges,
power_charts,
disk_io_charts,
network_io_charts,
)
"""
ui.title = "".join([
version,
" (Press q or ESC to stop)"
])
ui.border_color = args.color
"""
usage_gauges = ui.items[0]
#bw_gauges = memory_gauges.items[1]
"""
ui.title = "".join([
version,
" (Press q or ESC to stop)"
])
ui.border_color = args.color
"""
self.usage_gauges = self.ui.items[0]
#bw_gauges = memory_gauges.items[1]
cpu_title = "".join([
soc_info_dict["name"],
" (cores: ",
str(soc_info_dict["e_core_count"]),
"E+",
str(soc_info_dict["p_core_count"]),
"P+",
str(soc_info_dict["gpu_core_count"]),
"GPU)"
])
usage_gauges.title = cpu_title
cpu_max_power = soc_info_dict["cpu_max_power"]
gpu_max_power = soc_info_dict["gpu_max_power"]
ane_max_power = 16.0
"""max_cpu_bw = soc_info_dict["cpu_max_bw"]
max_gpu_bw = soc_info_dict["gpu_max_bw"]
max_media_bw = 7.0"""
cpu_title = "".join([
soc_info_dict["name"],
" (cores: ",
str(soc_info_dict["e_core_count"]),
"E+",
str(soc_info_dict["p_core_count"]),
"P+",
str(soc_info_dict["gpu_core_count"]),
"GPU)"
])
self.usage_gauges.title = cpu_title
self.cpu_max_power = soc_info_dict["cpu_max_power"]
self.gpu_max_power = soc_info_dict["gpu_max_power"]
self.ane_max_power = 16.0
"""max_cpu_bw = soc_info_dict["cpu_max_bw"]
max_gpu_bw = soc_info_dict["gpu_max_bw"]
max_media_bw = 7.0"""
cpu_peak_power = 0
gpu_peak_power = 0
package_peak_power = 0
disk_read_iops_peak = 0
disk_write_iops_peak = 0
disk_read_bps_peak = 0
disk_write_bps_peak = 0
network_in_bps_peak = 0
network_out_bps_peak = 0
self.avg_package_power_list = deque([], maxlen=int(args.avg / args.interval))
self.avg_cpu_power_list = deque([], maxlen=int(args.avg / args.interval))
self.avg_gpu_power_list = deque([], maxlen=int(args.avg / args.interval))
print("\n[2/3] Starting powermetrics process\n")
def display(self,powermetrics_parse,args):
if args.color != self.gpu_gauge.color:
clear_console()
self.gpu_gauge.color = args.color
self.ane_gauge.color = args.color
self.cpu1_gauge.color = args.color
self.cpu2_gauge.color = args.color
self.power_charts.color = args.color
self.power_charts.border_color = args.color
self.processor_split.border_color = args.color
self.ram_gauge.color = args.color
self.memory_gauges.border_color = args.color
self.cpu_power_chart.color = args.color
self.gpu_power_chart.color = args.color
#self.cpu_power_chart.border_color = args.color
self.disk_io_charts.color = args.color
self.disk_io_charts.border_color = args.color
self.network_io_charts.color = args.color
self.network_io_charts.border_color = args.color
self.disk_read_iops_charts.color = args.color
self.disk_write_iops_charts.color = args.color
self.disk_read_bps_charts.color = args.color
self.disk_write_bps_charts.color = args.color
self.network_in_bps_charts.color = args.color
self.network_out_bps_charts.color = args.color
for i in range(len(self.e_core_gauges)):
self.e_core_gauges[i].color = args.color
self.e_core_gauges[i].border_color = args.color
for i in range(len(self.p_core_gauges)):
self.p_core_gauges[i].color = args.color
self.p_core_gauges[i].border_color = args.color
for i in range(len(self.p_core_gauges_ext)):
self.p_core_gauges_ext[i].color = args.color
self.p_core_gauges_ext[i].border_color = args.color
thermal_pressure = parse_thermal_pressure(powermetrics_parse)
cpu_metrics_dict = parse_cpu_metrics(powermetrics_parse)
gpu_metrics_dict = parse_gpu_metrics(powermetrics_parse)
disk_metrics_dict = parse_disk_metrics(powermetrics_parse)
network_metrics_dict = parse_network_metrics(powermetrics_parse)
#bandwidth_metrics = parse_bandwidth_metrics(powermetrics_parse)
bandwidth_metrics = None
timestamp = powermetrics_parse["timestamp"]
if timestamp :
if thermal_pressure == "Nominal":
thermal_throttle = "no"
else:
thermal_throttle = "yes"
command = " ".join([
"sudo nice -n",
str(10),
"powermetrics",
"--samplers cpu_power,gpu_power,thermal,network,disk",
"-f plist",
"-i",
str(args.interval * 1000)
])
process = subprocess.Popen(command.split(" "), stdin=PIPE, stdout=PIPE)
powermetrics_process = process
"""e_cpu_usage = 0
core_count = 0
for i in cpu_metrics_dict["e_core"]:
e_cpu_usage += cpu_metrics_dict["E-Cluster" + str(i) + "_active"]
core_count += 1
e_cpu_usage = (e_cpu_usage / core_count) if core_count > 0 else 0"""
self.cpu1_gauge.title = "".join([
"E-CPU Usage: ",
str(cpu_metrics_dict["E-Cluster_active"]),
"% @ ",
str(cpu_metrics_dict["E-Cluster_freq_Mhz"]),
" MHz"
])
self.cpu1_gauge.value = cpu_metrics_dict["E-Cluster_active"]
print("\n[3/3] Waiting for first reading...\n")
"""
def get_reading(wait=0.1):
ready = parse_powermetrics(timecode=timecode)
while not ready:
time.sleep(wait)
ready = parse_powermetrics(timecode=timecode)
return ready
"""p_cpu_usage = 0
core_count = 0
for i in cpu_metrics_dict["p_core"]:
p_cpu_usage += cpu_metrics_dict["P-Cluster" + str(i) + "_active"]
core_count += 1
p_cpu_usage = (p_cpu_usage / core_count) if core_count > 0 else 0"""
self.cpu2_gauge.title = "".join([
"P-CPU Usage: ",
str(cpu_metrics_dict["P-Cluster_active"]),
"% @ ",
str(cpu_metrics_dict["P-Cluster_freq_Mhz"]),
" MHz"
])
self.cpu2_gauge.value = cpu_metrics_dict["P-Cluster_active"]
ready = get_reading()
last_timestamp = ready[-1]
"""
def get_avg(inlist):
avg = sum(inlist) / len(inlist)
return avg
avg_package_power_list = deque([], maxlen=int(args.avg / args.interval))
avg_cpu_power_list = deque([], maxlen=int(args.avg / args.interval))
avg_gpu_power_list = deque([], maxlen=int(args.avg / args.interval))
clear_console()
term = Terminal()
try:
data = b''
while True:
output = process.stdout.readline()
#output, stderr = process.communicate()
if process.poll() is not None:
break
data = data + output
str_output = output.decode()
if str_output.startswith('</plist>'):
data = data.replace(b'\x00',b'')
powermetrics_parse = plistlib.loads(data)
thermal_pressure = parse_thermal_pressure(powermetrics_parse)
cpu_metrics_dict = parse_cpu_metrics(powermetrics_parse)
gpu_metrics_dict = parse_gpu_metrics(powermetrics_parse)
disk_metrics_dict = parse_disk_metrics(powermetrics_parse)
network_metrics_dict = parse_network_metrics(powermetrics_parse)
#bandwidth_metrics = parse_bandwidth_metrics(powermetrics_parse)
bandwidth_metrics = None
timestamp = powermetrics_parse["timestamp"]
data = b''
if timestamp :
if thermal_pressure == "Nominal":
thermal_throttle = "no"
else:
thermal_throttle = "yes"
"""e_cpu_usage = 0
core_count = 0
for i in cpu_metrics_dict["e_core"]:
e_cpu_usage += cpu_metrics_dict["E-Cluster" + str(i) + "_active"]
core_count += 1
e_cpu_usage = (e_cpu_usage / core_count) if core_count > 0 else 0"""
cpu1_gauge.title = "".join([
"E-CPU Usage: ",
str(cpu_metrics_dict["E-Cluster_active"]),
"% @ ",
str(cpu_metrics_dict["E-Cluster_freq_Mhz"]),
" MHz"
if args.show_cores:
core_count = 0
for i in cpu_metrics_dict["e_core"]:
self.e_core_gauges[core_count % 4].title = "".join([
"Core-" + str(i + 1) + " ",
str(cpu_metrics_dict["E-Cluster" + str(i) + "_active"]),
"%",
])
cpu1_gauge.value = cpu_metrics_dict["E-Cluster_active"]
"""p_cpu_usage = 0
core_count = 0
for i in cpu_metrics_dict["p_core"]:
p_cpu_usage += cpu_metrics_dict["P-Cluster" + str(i) + "_active"]
core_count += 1
p_cpu_usage = (p_cpu_usage / core_count) if core_count > 0 else 0"""
cpu2_gauge.title = "".join([
"P-CPU Usage: ",
str(cpu_metrics_dict["P-Cluster_active"]),
"% @ ",
str(cpu_metrics_dict["P-Cluster_freq_Mhz"]),
" MHz"
self.e_core_gauges[core_count % 4].value = cpu_metrics_dict["E-Cluster" + str(i) + "_active"]
core_count += 1
core_count = 0
for i in cpu_metrics_dict["p_core"]:
core_gauges =self.p_core_gauges if core_count < 8 else self.p_core_gauges_ext
core_gauges[core_count % 8].title = "".join([
("Core-" if self.p_core_count < 6 else 'C-') + str(i + 1) + " ",
str(cpu_metrics_dict["P-Cluster" + str(i) + "_active"]),
"%",
])
cpu2_gauge.value = cpu_metrics_dict["P-Cluster_active"]
core_gauges[core_count % 8].value = cpu_metrics_dict["P-Cluster" + str(i) + "_active"]
core_count += 1
if args.show_cores:
core_count = 0
for i in cpu_metrics_dict["e_core"]:
e_core_gauges[core_count % 4].title = "".join([
"Core-" + str(i + 1) + " ",
str(cpu_metrics_dict["E-Cluster" + str(i) + "_active"]),
"%",
])
e_core_gauges[core_count % 4].value = cpu_metrics_dict["E-Cluster" + str(i) + "_active"]
core_count += 1
core_count = 0
for i in cpu_metrics_dict["p_core"]:
core_gauges = p_core_gauges if core_count < 8 else p_core_gauges_ext
core_gauges[core_count % 8].title = "".join([
("Core-" if p_core_count < 6 else 'C-') + str(i + 1) + " ",
str(cpu_metrics_dict["P-Cluster" + str(i) + "_active"]),
"%",
])
core_gauges[core_count % 8].value = cpu_metrics_dict["P-Cluster" + str(i) + "_active"]
core_count += 1
self.gpu_gauge.title = "".join([
"GPU Usage: ",
str(gpu_metrics_dict["active"]),
"% @ ",
str(gpu_metrics_dict["freq_MHz"]),
" MHz"
])
self.gpu_gauge.value = gpu_metrics_dict["active"]
gpu_gauge.title = "".join([
"GPU Usage: ",
str(gpu_metrics_dict["active"]),
"% @ ",
str(gpu_metrics_dict["freq_MHz"]),
" MHz"
])
gpu_gauge.value = gpu_metrics_dict["active"]
ane_power_W = cpu_metrics_dict["ane_W"] / args.interval
if ane_power_W > self.ane_max_power:
self.ane_max_power = ane_power_W
ane_util_percent = int(
ane_power_W / self.ane_max_power * 100)
self.ane_gauge.title = "".join([
"ANE Usage: ",
str(ane_util_percent),
"% @ ",
'{0:.1f}'.format(ane_power_W),
" W"
])
self.ane_gauge.value = ane_util_percent
ane_power_W = cpu_metrics_dict["ane_W"] / args.interval
if ane_power_W > ane_max_power:
ane_max_power = ane_power_W
ane_util_percent = int(
ane_power_W / ane_max_power * 100)
ane_gauge.title = "".join([
"ANE Usage: ",
str(ane_util_percent),
"% @ ",
'{0:.1f}'.format(ane_power_W),
" W"
])
ane_gauge.value = ane_util_percent
ram_metrics_dict = get_ram_metrics_dict()
ram_metrics_dict = get_ram_metrics_dict()
if ram_metrics_dict["swap_total_GB"] < 0.1:
self.ram_gauge.title = "".join([
"RAM Usage: ",
str(ram_metrics_dict["used_GB"]),
"/",
str(ram_metrics_dict["total_GB"]),
"GB - swap inactive"
])
else:
self.ram_gauge.title = "".join([
"RAM Usage: ",
str(ram_metrics_dict["used_GB"]),
"/",
str(ram_metrics_dict["total_GB"]),
"GB",
" - swap:",
str(ram_metrics_dict["swap_used_GB"]),
"/",
str(ram_metrics_dict["swap_total_GB"]),
"GB"
])
self.ram_gauge.value = ram_metrics_dict["free_percent"]
if ram_metrics_dict["swap_total_GB"] < 0.1:
ram_gauge.title = "".join([
"RAM Usage: ",
str(ram_metrics_dict["used_GB"]),
"/",
str(ram_metrics_dict["total_GB"]),
"GB - swap inactive"
])
else:
ram_gauge.title = "".join([
"RAM Usage: ",
str(ram_metrics_dict["used_GB"]),
"/",
str(ram_metrics_dict["total_GB"]),
"GB",
" - swap:",
str(ram_metrics_dict["swap_used_GB"]),
"/",
str(ram_metrics_dict["swap_total_GB"]),
"GB"
])
ram_gauge.value = ram_metrics_dict["free_percent"]
"""
"""
ecpu_bw_percent = int(
(bandwidth_metrics["ECPU DCS RD"] + bandwidth_metrics[
"ECPU DCS WR"]) / args.interval / max_cpu_bw * 100)
ecpu_read_GB = bandwidth_metrics["ECPU DCS RD"] / \
args.interval
ecpu_write_GB = bandwidth_metrics["ECPU DCS WR"] / \
args.interval
ecpu_bw_gauge.title = "".join([
"E-CPU: ",
'{0:.1f}'.format(ecpu_read_GB + ecpu_write_GB),
"GB/s"
])
ecpu_bw_gauge.value = ecpu_bw_percent
ecpu_bw_percent = int(
(bandwidth_metrics["ECPU DCS RD"] + bandwidth_metrics[
"ECPU DCS WR"]) / args.interval / max_cpu_bw * 100)
ecpu_read_GB = bandwidth_metrics["ECPU DCS RD"] / \
args.interval
ecpu_write_GB = bandwidth_metrics["ECPU DCS WR"] / \
args.interval
ecpu_bw_gauge.title = "".join([
"E-CPU: ",
'{0:.1f}'.format(ecpu_read_GB + ecpu_write_GB),
"GB/s"
])
ecpu_bw_gauge.value = ecpu_bw_percent
pcpu_bw_percent = int(
(bandwidth_metrics["PCPU DCS RD"] + bandwidth_metrics[
"PCPU DCS WR"]) / args.interval / max_cpu_bw * 100)
pcpu_read_GB = bandwidth_metrics["PCPU DCS RD"] / \
args.interval
pcpu_write_GB = bandwidth_metrics["PCPU DCS WR"] / \
args.interval
pcpu_bw_gauge.title = "".join([
"P-CPU: ",
'{0:.1f}'.format(pcpu_read_GB + pcpu_write_GB),
"GB/s"
])
pcpu_bw_gauge.value = pcpu_bw_percent
pcpu_bw_percent = int(
(bandwidth_metrics["PCPU DCS RD"] + bandwidth_metrics[
"PCPU DCS WR"]) / args.interval / max_cpu_bw * 100)
pcpu_read_GB = bandwidth_metrics["PCPU DCS RD"] / \
args.interval
pcpu_write_GB = bandwidth_metrics["PCPU DCS WR"] / \
args.interval
pcpu_bw_gauge.title = "".join([
"P-CPU: ",
'{0:.1f}'.format(pcpu_read_GB + pcpu_write_GB),
"GB/s"
])
pcpu_bw_gauge.value = pcpu_bw_percent
gpu_bw_percent = int(
(bandwidth_metrics["GFX DCS RD"] + bandwidth_metrics["GFX DCS WR"]) / max_gpu_bw * 100)
gpu_read_GB = bandwidth_metrics["GFX DCS RD"]
gpu_write_GB = bandwidth_metrics["GFX DCS WR"]
gpu_bw_gauge.title = "".join([
"GPU: ",
'{0:.1f}'.format(gpu_read_GB + gpu_write_GB),
"GB/s"
])
gpu_bw_gauge.value = gpu_bw_percent
gpu_bw_percent = int(
(bandwidth_metrics["GFX DCS RD"] + bandwidth_metrics["GFX DCS WR"]) / max_gpu_bw * 100)
gpu_read_GB = bandwidth_metrics["GFX DCS RD"]
gpu_write_GB = bandwidth_metrics["GFX DCS WR"]
gpu_bw_gauge.title = "".join([
"GPU: ",
'{0:.1f}'.format(gpu_read_GB + gpu_write_GB),
"GB/s"
])
gpu_bw_gauge.value = gpu_bw_percent
media_bw_percent = int(
bandwidth_metrics["MEDIA DCS"] / args.interval / max_media_bw * 100)
media_bw_gauge.title = "".join([
"Media: ",
'{0:.1f}'.format(
bandwidth_metrics["MEDIA DCS"] / args.interval),
"GB/s"
])
media_bw_gauge.value = media_bw_percent
media_bw_percent = int(
bandwidth_metrics["MEDIA DCS"] / args.interval / max_media_bw * 100)
media_bw_gauge.title = "".join([
"Media: ",
'{0:.1f}'.format(
bandwidth_metrics["MEDIA DCS"] / args.interval),
"GB/s"
])
media_bw_gauge.value = media_bw_percent
total_bw_GB = (
bandwidth_metrics["DCS RD"] + bandwidth_metrics["DCS WR"]) / args.interval
bw_gauges.title = "".join([
"Memory Bandwidth: ",
'{0:.2f}'.format(total_bw_GB),
" GB/s (R:",
'{0:.2f}'.format(
bandwidth_metrics["DCS RD"] / args.interval),
"/W:",
'{0:.2f}'.format(
bandwidth_metrics["DCS WR"] / args.interval),
" GB/s)"
])
if args.show_cores:
bw_gauges_ext = memory_gauges.items[2]
bw_gauges_ext.title = "Memory Bandwidth:"
"""
total_bw_GB = (
bandwidth_metrics["DCS RD"] + bandwidth_metrics["DCS WR"]) / args.interval
bw_gauges.title = "".join([
"Memory Bandwidth: ",
'{0:.2f}'.format(total_bw_GB),
" GB/s (R:",
'{0:.2f}'.format(
bandwidth_metrics["DCS RD"] / args.interval),
"/W:",
'{0:.2f}'.format(
bandwidth_metrics["DCS WR"] / args.interval),
" GB/s)"
])
if args.show_cores:
bw_gauges_ext = memory_gauges.items[2]
bw_gauges_ext.title = "Memory Bandwidth:"
"""
package_power_W = cpu_metrics_dict["package_W"] / \
args.interval
if package_power_W > self.package_peak_power:
self.package_peak_power = package_power_W
self.avg_package_power_list.append(package_power_W)
avg_package_power = get_avg(self.avg_package_power_list)
self.power_charts.title = "".join([
"CPU+GPU+ANE Power: ",
'{0:.2f}'.format(package_power_W),
"W (avg: ",
'{0:.2f}'.format(avg_package_power),
"W peak: ",
'{0:.2f}'.format(self.package_peak_power),
"W) throttle: ",
thermal_throttle,
])
package_power_W = cpu_metrics_dict["package_W"] / \
args.interval
if package_power_W > package_peak_power:
package_peak_power = package_power_W
avg_package_power_list.append(package_power_W)
avg_package_power = get_avg(avg_package_power_list)
power_charts.title = "".join([
"CPU+GPU+ANE Power: ",
'{0:.2f}'.format(package_power_W),
"W (avg: ",
'{0:.2f}'.format(avg_package_power),
"W peak: ",
'{0:.2f}'.format(package_peak_power),
"W) throttle: ",
thermal_throttle,
])
cpu_power_W = cpu_metrics_dict["cpu_W"] / args.interval
if cpu_power_W > self.cpu_peak_power:
self.cpu_peak_power = cpu_power_W
if cpu_power_W > self.cpu_max_power:
self.cpu_max_power = cpu_power_W
cpu_power_percent = int(
cpu_power_W / self.cpu_max_power * 100)
self.avg_cpu_power_list.append(cpu_power_W)
avg_cpu_power = get_avg(self.avg_cpu_power_list)
self.cpu_power_chart.title = "".join([
"CPU: ",
'{0:.2f}'.format(cpu_power_W),
"W (avg: ",
'{0:.2f}'.format(avg_cpu_power),
"W peak: ",
'{0:.2f}'.format(self.cpu_peak_power),
"W)"
])
self.cpu_power_chart.append(cpu_power_percent)
cpu_power_W = cpu_metrics_dict["cpu_W"] / args.interval
if cpu_power_W > cpu_peak_power:
cpu_peak_power = cpu_power_W
if cpu_power_W > cpu_max_power:
cpu_max_power = cpu_power_W
cpu_power_percent = int(
cpu_power_W / cpu_max_power * 100)
avg_cpu_power_list.append(cpu_power_W)
avg_cpu_power = get_avg(avg_cpu_power_list)
cpu_power_chart.title = "".join([
"CPU: ",
'{0:.2f}'.format(cpu_power_W),
"W (avg: ",
'{0:.2f}'.format(avg_cpu_power),
"W peak: ",
'{0:.2f}'.format(cpu_peak_power),
"W)"
])
cpu_power_chart.append(cpu_power_percent)
gpu_power_W = cpu_metrics_dict["gpu_W"] / args.interval
if gpu_power_W > self.gpu_peak_power:
self.gpu_peak_power = gpu_power_W
if gpu_power_W > self.gpu_max_power:
self.gpu_max_power = gpu_power_W
gpu_power_percent = int(
gpu_power_W / self.gpu_max_power * 100)
self.avg_gpu_power_list.append(gpu_power_W)
avg_gpu_power = get_avg(self.avg_gpu_power_list)
self.gpu_power_chart.title = "".join([
"GPU: ",
'{0:.2f}'.format(gpu_power_W),
"W (avg: ",
'{0:.2f}'.format(avg_gpu_power),
"W peak: ",
'{0:.2f}'.format(self.gpu_peak_power),
"W)"
])
self.gpu_power_chart.append(gpu_power_percent)
gpu_power_W = cpu_metrics_dict["gpu_W"] / args.interval
if gpu_power_W > gpu_peak_power:
gpu_peak_power = gpu_power_W
if gpu_power_W > gpu_max_power:
gpu_max_power = gpu_power_W
gpu_power_percent = int(
gpu_power_W / gpu_max_power * 100)
avg_gpu_power_list.append(gpu_power_W)
avg_gpu_power = get_avg(avg_gpu_power_list)
gpu_power_chart.title = "".join([
"GPU: ",
'{0:.2f}'.format(gpu_power_W),
"W (avg: ",
'{0:.2f}'.format(avg_gpu_power),
"W peak: ",
'{0:.2f}'.format(gpu_peak_power),
"W)"
])
gpu_power_chart.append(gpu_power_percent)
def format_number(number):
return humanize.naturalsize(number)
def format_number(number):
return humanize.naturalsize(number)
disk_read_iops = disk_metrics_dict["read_iops"]
if disk_read_iops > self.disk_read_iops_peak:
self.disk_read_iops_peak = disk_read_iops
self.disk_read_iops_charts.title = "Read iops: "+ f'{disk_read_iops} (peak: {self.disk_read_iops_peak})'
if self.disk_read_iops_charts.datapoints:
disk_read_iops_rate = int(disk_read_iops / self.disk_read_iops_peak * 100) if self.disk_read_iops_peak > 0 else 0
else:
disk_read_iops_rate = 100
self.disk_read_iops_charts.append(disk_read_iops_rate)
disk_read_iops = disk_metrics_dict["read_iops"]
if disk_read_iops > disk_read_iops_peak:
disk_read_iops_peak = disk_read_iops
disk_read_iops_charts.title = "Read iops: "+ f'{disk_read_iops} (peak: {disk_read_iops_peak})'
if disk_read_iops_charts.datapoints:
disk_read_iops_rate = int(disk_read_iops / disk_read_iops_peak * 100) if disk_read_iops_peak > 0 else 0
else:
disk_read_iops_rate = 100
disk_read_iops_charts.append(disk_read_iops_rate)
disk_write_iops = disk_metrics_dict["write_iops"]
if disk_write_iops > self.disk_write_iops_peak:
self.disk_write_iops_peak = disk_write_iops
self.disk_write_iops_charts.title = "Write iops: "+ f'{disk_write_iops} (peak: {self.disk_write_iops_peak})'
if self.disk_write_iops_charts.datapoints:
disk_write_iops_rate = int(disk_read_iops / self.disk_write_iops_peak * 100) if self.disk_write_iops_peak > 0 else 0
else:
disk_write_iops_rate = 100
self.disk_write_iops_charts.append(disk_write_iops_rate)
disk_write_iops = disk_metrics_dict["write_iops"]
if disk_write_iops > disk_write_iops_peak:
disk_write_iops_peak = disk_write_iops
disk_write_iops_charts.title = "Write iops: "+ f'{disk_write_iops} (peak: {disk_write_iops_peak})'
if disk_write_iops_charts.datapoints:
disk_write_iops_rate = int(disk_read_iops / disk_write_iops_peak * 100) if disk_write_iops_peak > 0 else 0
else:
disk_write_iops_rate = 100
disk_write_iops_charts.append(disk_write_iops_rate)
disk_read_bps = disk_metrics_dict["read_Bps"]
if disk_read_bps > self.disk_read_bps_peak:
self.disk_read_bps_peak = disk_read_bps
self.disk_read_bps_charts.title = "Read : "+ f'{format_number(disk_read_bps)}/s (peak: {format_number(self.disk_read_bps_peak)}/s)'
if self.disk_read_bps_charts.datapoints:
disk_read_bps_rate = int(disk_read_bps / self.disk_read_bps_peak * 100) if self.disk_read_bps_peak > 0 else 0
else:
disk_read_bps_rate = 100
self.disk_read_bps_charts.append(disk_read_bps_rate)
disk_read_bps = disk_metrics_dict["read_Bps"]
if disk_read_bps > disk_read_bps_peak:
disk_read_bps_peak = disk_read_bps
disk_read_bps_charts.title = "Read : "+ f'{format_number(disk_read_bps)}/s (peak: {format_number(disk_read_bps_peak)}/s)'
if disk_read_bps_charts.datapoints:
disk_read_bps_rate = int(disk_read_bps / disk_read_bps_peak * 100) if disk_read_bps_peak > 0 else 0
else:
disk_read_bps_rate = 100
disk_read_bps_charts.append(disk_read_bps_rate)
disk_write_bps = disk_metrics_dict["write_Bps"]
if disk_write_bps > self.disk_write_bps_peak:
self.disk_write_bps_peak = disk_write_bps
self.disk_write_bps_charts.title = "Write : "+ f'{format_number(disk_write_bps)}/s (peak: {format_number(self.disk_write_bps_peak)}/s)'
if self.disk_write_bps_charts.datapoints:
disk_write_bps_rate = int(disk_write_bps / self.disk_write_bps_peak * 100) if self.disk_write_bps_peak > 0 else 0
else:
disk_write_bps_rate = 100
self.disk_write_bps_charts.append(disk_write_bps_rate)
disk_write_bps = disk_metrics_dict["write_Bps"]
if disk_write_bps > disk_write_bps_peak:
disk_write_bps_peak = disk_write_bps
disk_write_bps_charts.title = "Write : "+ f'{format_number(disk_write_bps)}/s (peak: {format_number(disk_write_bps_peak)}/s)'
if disk_write_bps_charts.datapoints:
disk_write_bps_rate = int(disk_write_bps / disk_write_bps_peak * 100) if disk_write_bps_peak > 0 else 0
else:
disk_write_bps_rate = 100
disk_write_bps_charts.append(disk_write_bps_rate)
network_in_bps = network_metrics_dict["in_Bps"]
if network_in_bps > self.network_in_bps_peak:
self.network_in_bps_peak = network_in_bps
self.network_in_bps_charts.title = "in : "+ f'{format_number(network_in_bps)}/s (peak: {format_number(self.network_in_bps_peak)}/s)'
if self.network_in_bps_charts.datapoints:
network_in_bps_rate = int(network_in_bps / self.network_in_bps_peak * 100) if self.network_in_bps_peak > 0 else 0
else:
network_in_bps_rate = 100
self.network_in_bps_charts.append(network_in_bps_rate)
network_in_bps = network_metrics_dict["in_Bps"]
if network_in_bps > network_in_bps_peak:
network_in_bps_peak = network_in_bps
network_in_bps_charts.title = "in : "+ f'{format_number(network_in_bps)}/s (peak: {format_number(network_in_bps_peak)}/s)'
if network_in_bps_charts.datapoints:
network_in_bps_rate = int(network_in_bps / network_in_bps_peak * 100) if network_in_bps_peak > 0 else 0
else:
network_in_bps_rate = 100
network_in_bps_charts.append(network_in_bps_rate)
network_out_bps = network_metrics_dict["out_Bps"]
if network_out_bps > self.network_out_bps_peak:
self.network_out_bps_peak = network_out_bps
self.network_out_bps_charts.title = "out : "+ f'{format_number(network_out_bps)}/s (peak: {format_number(self.network_out_bps_peak)}/s)'
if self.network_out_bps_charts.datapoints:
network_out_bps_rate = int(network_out_bps / self.network_out_bps_peak * 100) if self.network_out_bps_peak > 0 else 0
else:
network_out_bps_rate = 100
self.network_out_bps_charts.append(network_out_bps_rate)
network_out_bps = network_metrics_dict["out_Bps"]
if network_out_bps > network_out_bps_peak:
network_out_bps_peak = network_out_bps
network_out_bps_charts.title = "out : "+ f'{format_number(network_out_bps)}/s (peak: {format_number(network_out_bps_peak)}/s)'
if network_out_bps_charts.datapoints:
network_out_bps_rate = int(network_out_bps / network_out_bps_peak * 100) if network_out_bps_peak > 0 else 0
else:
network_out_bps_rate = 100
network_out_bps_charts.append(network_out_bps_rate)
self.ui.display()
ui.display()
key_cmd = ''
with term.cbreak():
key = term.inkey(timeout=1)
if key:
if key.is_sequence:
if key.name == 'KEY_ESCAPE':
key_cmd = "quit"
elif key.lower() == 'q':
key_cmd = "quit"
if key_cmd == "quit":
def get_avg(inlist):
avg = sum(inlist) / len(inlist)
return avg
def main(stdscr):
soc_info_dict = get_soc_info()
view1 = DefaultView(soc_info_dict=soc_info_dict,args=args)
clear_console()
stdscr.nodelay(True)
view = 1
try:
data = b''
while True:
output = powermetrics_process.stdout.readline()
if powermetrics_process.poll() is not None:
break
data = data + output
str_output = output.decode()
if str_output.startswith('</plist>'):
data = data.replace(b'\x00',b'')
powermetrics_parse = plistlib.loads(data)
key = stdscr.getch()
if key > 0:
if key == 27:
print("\nStopping...")
break
elif key == curses.KEY_LEFT:
args.color = (args.color - 1) if args.color > 1 else 8
elif key == curses.KEY_RIGHT:
args.color = (args.color + 1) if args.color < 8 else 1
elif chr(key).lower() == 'q':
print("\nStopping...")
break
elif chr(key) == '1':
args.show_cores = False
if view != 1:
view1.construct(soc_info_dict,args)
view = 1
clear_console()
elif chr(key) == '2':
args.show_cores = True
if view != 2:
view1.construct(soc_info_dict,args)
view = 2
clear_console()
if view == 1 or view == 2:
view1.display(powermetrics_parse,args)
data = b''
if str_output == '':

@@ -864,3 +884,2 @@ time.sleep(0.1)

print("Stopping...")
print("\033[?25h")

@@ -871,3 +890,27 @@ return

if __name__ == "__main__":
main()
print(f"\n{version} - enhanced MAC Performance monitoring CLI tool for Apple Silicon")
print("You can update macpm by running `pip install macpm --upgrade`")
print("Get help at `https://github.com/visualcjy/macpm`")
print("P.S. You are recommended to run macpm with `sudo macpm`\n")
print("\n[1/3] Loading macpm\n")
print("\033[?25l")
#global powermetrics_process
print("\n[2/3] Starting powermetrics process\n")
command = " ".join([
"sudo nice -n",
str(10),
"powermetrics",
"--samplers cpu_power,gpu_power,thermal,network,disk",
"-f plist",
"-i",
str(args.interval * 1000)
])
powermetrics_process = subprocess.Popen(command.split(" "), stdin=PIPE, stdout=PIPE)
print("\n[3/3] Waiting for first reading...\n")
curses.wrapper(main)
print("\033[?25h")
try:

@@ -874,0 +917,0 @@ powermetrics_process.terminate()

Metadata-Version: 2.1
Name: macpm
Version: 0.14
Version: 0.15
Summary: Performance monitoring CLI tool for Apple Silicon

@@ -5,0 +5,0 @@ Home-page: https://github.com/visualcjy/macpm

@@ -6,3 +6,3 @@ # macpm

Performance monitoring CLI tool for Apple Silicon
enhanced MAC Performance monitoring CLI tool for Apple Silicon

@@ -22,2 +22,3 @@ ![](images/macpm.png)

4. change the way to call powermetrics, no temp files in /tmp
5. press ESC or q to quit

@@ -24,0 +25,0 @@ A Python-based `nvtop`-inspired command line tool for Apple Silicon (aka M1) Macs.

@@ -7,3 +7,3 @@ from setuptools import setup, find_packages

name='macpm',
version='0.14',
version='0.15',
author='Jinyu Chen',

@@ -10,0 +10,0 @@ author_email='visualcjy@mail.com',