Skip to content

Commit 9ce9546

Browse files
committed
Add --interval flag and working on fix for Max/Pro chip
1 parent befcf85 commit 9ce9546

File tree

4 files changed

+37
-40
lines changed

4 files changed

+37
-40
lines changed

.DS_Store

-6 KB
Binary file not shown.

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/logs
22

33
mactop
4-
dist/
5-
.DS_Store
4+
dist
5+
.DS_Store

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,23 @@ sudo ./mactop
7070

7171
`sudo` is required to run `mactop`
7272

73-
Use the following keys to interact with the application:
73+
## mactop Flags
74+
75+
- `--interval` or `-i`: Set the powermetrics update interval in milliseconds. Default is 1000. (For low-end M chips, you may want to increase this value)
76+
- `--version` or `-v`: Print the version of mactop.
77+
78+
## mactop Commands
79+
Use the following keys to interact with the application while its running:
7480
- `q`: Quit the application.
7581
- `r`: Refresh the UI data manually.
7682
- `l`: Toggle the current layout.
7783

84+
## Confirmed tested working M series chips
85+
86+
- M1
87+
- M1 Max
88+
- M1 Ultra
89+
7890
## Contributing
7991

8092
Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.

main.go

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ var (
8585

8686
stderrLogger = log.New(os.Stderr, "", 0)
8787
currentGridLayout = "default"
88+
updateInterval = 1000
8889
)
8990

9091
func setupUI() {
@@ -246,11 +247,9 @@ func StderrToLogfile(logfile *os.File) {
246247
}
247248

248249
// mactop main function
249-
250250
func main() {
251251

252-
// get version from git
253-
version := "v0.1.4"
252+
version := "v0.1.5"
254253
if len(os.Args) > 1 && os.Args[1] == "--version" {
255254
fmt.Println("mactop version:", version)
256255
os.Exit(0)
@@ -268,6 +267,15 @@ func main() {
268267
os.Exit(1)
269268
}
270269

270+
if len(os.Args) > 1 && os.Args[1] == "--interval" || len(os.Args) > 1 && os.Args[1] == "-i" {
271+
interval, err := strconv.Atoi(os.Args[2])
272+
if err != nil {
273+
fmt.Println("Invalid interval:", err)
274+
os.Exit(1)
275+
}
276+
updateInterval = interval
277+
}
278+
271279
logfile, err := setupLogfile()
272280
if err != nil {
273281
stderrLogger.Fatalf("failed to setup log file: %v", err)
@@ -280,14 +288,11 @@ func main() {
280288
defer ui.Close()
281289

282290
StderrToLogfile(logfile)
283-
284291
setupUI() // Initialize UI components and layout
285-
286292
setupGrid()
287293

288294
termWidth, termHeight := ui.TerminalDimensions()
289295
grid.SetRect(0, 0, termWidth, termHeight)
290-
291296
ui.Render(grid)
292297

293298
cpuMetricsChan := make(chan CPUMetrics)
@@ -386,7 +391,7 @@ func collectMetrics(done chan struct{}, cpumetricsChan chan CPUMetrics, gpumetri
386391
var gpuMetrics GPUMetrics
387392
var netdiskMetrics NetDiskMetrics
388393
var processMetrics []ProcessMetrics
389-
cmd := exec.Command("powermetrics", "--samplers", "cpu_power,gpu_power,thermal,network,disk", "--show-process-gpu", "--show-process-energy", "--show-initial-usage", "--show-process-netstats", "-i 1000")
394+
cmd := exec.Command("powermetrics", "--samplers", "cpu_power,gpu_power,thermal,network,disk", "--show-process-gpu", "--show-process-energy", "--show-initial-usage", "--show-process-netstats", "-i", strconv.Itoa(updateInterval))
390395
stdout, err := cmd.StdoutPipe()
391396
if err != nil {
392397
stderrLogger.Fatalf("failed to get stdout pipe: %v", err)
@@ -483,27 +488,20 @@ func updateNetDiskUI(netdiskMetrics NetDiskMetrics) {
483488
}
484489

485490
func updateProcessUI(processMetrics []ProcessMetrics) {
486-
// Assuming `ProcessInfo` is a Paragraph widget from termui
487-
// Clear previous content
488491
ProcessInfo.Text = ""
489492

490-
// Sort processMetrics by CPU ms/s in descending order
491493
sort.Slice(processMetrics, func(i, j int) bool {
492494
return processMetrics[i].CPUUsage > processMetrics[j].CPUUsage
493495
})
494496

495-
// Limit the number of entries to 15
496497
maxEntries := 15
497498
if len(processMetrics) > maxEntries {
498499
processMetrics = processMetrics[:maxEntries]
499500
}
500501

501-
// Create a string with each process on a new line
502502
for _, pm := range processMetrics {
503503
ProcessInfo.Text += fmt.Sprintf("%d - %s: %.2f ms/s\n", pm.ID, pm.Name, pm.CPUUsage)
504504
}
505-
506-
// Render the updated ProcessInfo
507505
ui.Render(ProcessInfo)
508506
}
509507

@@ -695,20 +693,17 @@ func parseCPUMetrics(powermetricsOutput string, cpuMetrics CPUMetrics) CPUMetric
695693
cpuMetrics.EClusterFreqMHz = max(cpuMetrics.E0ClusterFreqMHz, cpuMetrics.E1ClusterFreqMHz)
696694
}
697695

698-
if cpuMetrics.PClusterActive != 0 {
696+
if cpuMetrics.P3ClusterActive != 0 {
699697
// M1 Ultra
700-
if cpuMetrics.P2ClusterActive != 0 {
701-
cpuMetrics.PClusterActive = (cpuMetrics.P0ClusterActive + cpuMetrics.P1ClusterActive + cpuMetrics.P2ClusterActive + cpuMetrics.P3ClusterActive) / 4
702-
freqs := []int{cpuMetrics.P0ClusterFreqMHz, cpuMetrics.P1ClusterFreqMHz, cpuMetrics.P2ClusterFreqMHz, cpuMetrics.P3ClusterFreqMHz}
703-
cpuMetrics.PClusterFreqMHz = maxInt(freqs)
704-
} else {
705-
if cpuMetrics.P0ClusterActive != 0 {
706-
cpuMetrics.PClusterActive = (cpuMetrics.P0ClusterActive + cpuMetrics.P1ClusterActive) / 2
707-
cpuMetrics.PClusterFreqMHz = max(cpuMetrics.P0ClusterFreqMHz, cpuMetrics.P1ClusterFreqMHz)
708-
} else {
709-
cpuMetrics.PClusterActive = cpuMetrics.PClusterActive + cpuMetrics.P0ClusterActive
710-
}
711-
}
698+
cpuMetrics.PClusterActive = (cpuMetrics.P0ClusterActive + cpuMetrics.P1ClusterActive + cpuMetrics.P2ClusterActive + cpuMetrics.P3ClusterActive) / 4
699+
cpuMetrics.PClusterFreqMHz = max(cpuMetrics.P0ClusterFreqMHz, cpuMetrics.P1ClusterFreqMHz, cpuMetrics.P2ClusterFreqMHz, cpuMetrics.P3ClusterFreqMHz)
700+
} else if cpuMetrics.P1ClusterActive != 0 {
701+
// M1/M2/M3 Max/Pro
702+
cpuMetrics.PClusterActive = (cpuMetrics.P0ClusterActive + cpuMetrics.P1ClusterActive) / 2
703+
cpuMetrics.PClusterFreqMHz = max(cpuMetrics.P0ClusterFreqMHz, cpuMetrics.P1ClusterFreqMHz)
704+
} else {
705+
// M1
706+
cpuMetrics.PClusterActive = cpuMetrics.PClusterActive + cpuMetrics.P0ClusterActive
712707
}
713708

714709
// Calculate average active residency and frequency for E and P clusters
@@ -729,16 +724,6 @@ func max(nums ...int) int {
729724
return maxVal
730725
}
731726

732-
func maxInt(nums []int) int {
733-
max := nums[0]
734-
for _, num := range nums {
735-
if num > max {
736-
max = num
737-
}
738-
}
739-
return max
740-
}
741-
742727
func parseGPUMetrics(powermetricsOutput string, gpuMetrics GPUMetrics) GPUMetrics {
743728
re := regexp.MustCompile(`GPU\s*(HW)?\s*active\s*(residency|frequency):\s+(\d+\.\d+)%?`)
744729
freqRe := regexp.MustCompile(`(\d+)\s*MHz:\s*(\d+)%`)

0 commit comments

Comments
 (0)