85
85
86
86
stderrLogger = log .New (os .Stderr , "" , 0 )
87
87
currentGridLayout = "default"
88
+ updateInterval = 1000
88
89
)
89
90
90
91
func setupUI () {
@@ -246,11 +247,9 @@ func StderrToLogfile(logfile *os.File) {
246
247
}
247
248
248
249
// mactop main function
249
-
250
250
func main () {
251
251
252
- // get version from git
253
- version := "v0.1.4"
252
+ version := "v0.1.5"
254
253
if len (os .Args ) > 1 && os .Args [1 ] == "--version" {
255
254
fmt .Println ("mactop version:" , version )
256
255
os .Exit (0 )
@@ -268,6 +267,15 @@ func main() {
268
267
os .Exit (1 )
269
268
}
270
269
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
+
271
279
logfile , err := setupLogfile ()
272
280
if err != nil {
273
281
stderrLogger .Fatalf ("failed to setup log file: %v" , err )
@@ -280,14 +288,11 @@ func main() {
280
288
defer ui .Close ()
281
289
282
290
StderrToLogfile (logfile )
283
-
284
291
setupUI () // Initialize UI components and layout
285
-
286
292
setupGrid ()
287
293
288
294
termWidth , termHeight := ui .TerminalDimensions ()
289
295
grid .SetRect (0 , 0 , termWidth , termHeight )
290
-
291
296
ui .Render (grid )
292
297
293
298
cpuMetricsChan := make (chan CPUMetrics )
@@ -386,7 +391,7 @@ func collectMetrics(done chan struct{}, cpumetricsChan chan CPUMetrics, gpumetri
386
391
var gpuMetrics GPUMetrics
387
392
var netdiskMetrics NetDiskMetrics
388
393
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 ) )
390
395
stdout , err := cmd .StdoutPipe ()
391
396
if err != nil {
392
397
stderrLogger .Fatalf ("failed to get stdout pipe: %v" , err )
@@ -483,27 +488,20 @@ func updateNetDiskUI(netdiskMetrics NetDiskMetrics) {
483
488
}
484
489
485
490
func updateProcessUI (processMetrics []ProcessMetrics ) {
486
- // Assuming `ProcessInfo` is a Paragraph widget from termui
487
- // Clear previous content
488
491
ProcessInfo .Text = ""
489
492
490
- // Sort processMetrics by CPU ms/s in descending order
491
493
sort .Slice (processMetrics , func (i , j int ) bool {
492
494
return processMetrics [i ].CPUUsage > processMetrics [j ].CPUUsage
493
495
})
494
496
495
- // Limit the number of entries to 15
496
497
maxEntries := 15
497
498
if len (processMetrics ) > maxEntries {
498
499
processMetrics = processMetrics [:maxEntries ]
499
500
}
500
501
501
- // Create a string with each process on a new line
502
502
for _ , pm := range processMetrics {
503
503
ProcessInfo .Text += fmt .Sprintf ("%d - %s: %.2f ms/s\n " , pm .ID , pm .Name , pm .CPUUsage )
504
504
}
505
-
506
- // Render the updated ProcessInfo
507
505
ui .Render (ProcessInfo )
508
506
}
509
507
@@ -695,20 +693,17 @@ func parseCPUMetrics(powermetricsOutput string, cpuMetrics CPUMetrics) CPUMetric
695
693
cpuMetrics .EClusterFreqMHz = max (cpuMetrics .E0ClusterFreqMHz , cpuMetrics .E1ClusterFreqMHz )
696
694
}
697
695
698
- if cpuMetrics .PClusterActive != 0 {
696
+ if cpuMetrics .P3ClusterActive != 0 {
699
697
// 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
712
707
}
713
708
714
709
// Calculate average active residency and frequency for E and P clusters
@@ -729,16 +724,6 @@ func max(nums ...int) int {
729
724
return maxVal
730
725
}
731
726
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
-
742
727
func parseGPUMetrics (powermetricsOutput string , gpuMetrics GPUMetrics ) GPUMetrics {
743
728
re := regexp .MustCompile (`GPU\s*(HW)?\s*active\s*(residency|frequency):\s+(\d+\.\d+)%?` )
744
729
freqRe := regexp .MustCompile (`(\d+)\s*MHz:\s*(\d+)%` )
0 commit comments