Skip to content

Commit 6c0d43e

Browse files
authored
Merge pull request #25 from context-labs/development
Fixes large P-CPU % bug
2 parents c41465d + 74e32fa commit 6c0d43e

File tree

2 files changed

+77
-64
lines changed

2 files changed

+77
-64
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/context-labs/mactop/total) ![GitHub Release](https://img.shields.io/github/v/release/context-labs/mactop)
44

5-
`mactop` is a terminal-based monitoring tool "top" designed to display real-time metrics for Apple Silicon chips. It provides a simple and efficient way to monitor CPU and GPU usage, E-Cores and P-Cores, power consumption, and other system metrics directly from your terminal!
5+
`mactop` is a terminal-based monitoring tool "top" designed to display real-time metrics for Apple Silicon chips written by Carsen Klock. It provides a simple and efficient way to monitor CPU and GPU usage, E-Cores and P-Cores, power consumption, and other system metrics directly from your terminal!
66

77
![mactop](screenshot2.png)
88

@@ -95,7 +95,8 @@ Options are 'green', 'red', 'blue', 'cyan', 'magenta', 'yellow', and 'white'. (-
9595
Use the following keys to interact with the application while its running:
9696
- `q`: Quit the application.
9797
- `r`: Refresh the UI data manually.
98-
- `l`: Toggle the current layout.
98+
- `l`: Toggle the main display's layout.
99+
- `h`: Toggle the help menu.
99100

100101
## Example Theme (Green) Screenshot (sudo mactop -c green)
101102

@@ -138,7 +139,7 @@ Contributions are what make the open-source community such an amazing place to l
138139

139140
Distributed under the MIT License. See `LICENSE` for more information.
140141

141-
## Contact
142+
## Author and Contact
142143

143144
Carsen Klock - [@carsenklock](https://twitter.com/carsenklock)
144145

main.go

Lines changed: 73 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,17 @@ func (e *EventThrottler) Notify() {
7878
}
7979

8080
var (
81-
cpu1Gauge, cpu2Gauge, gpuGauge, aneGauge *w.Gauge
82-
TotalPowerChart *w.BarChart
83-
memoryGauge *w.Gauge
84-
modelText, PowerChart, NetworkInfo, ProcessInfo *w.Paragraph
85-
grid *ui.Grid
86-
powerValues []float64
87-
lastUpdateTime time.Time
88-
stderrLogger = log.New(os.Stderr, "", 0)
89-
currentGridLayout = "default"
90-
updateInterval = 1000
81+
cpu1Gauge, cpu2Gauge, gpuGauge, aneGauge *w.Gauge
82+
TotalPowerChart *w.BarChart
83+
memoryGauge *w.Gauge
84+
modelText, PowerChart, NetworkInfo, ProcessInfo, helpText *w.Paragraph
85+
grid *ui.Grid
86+
powerValues []float64
87+
lastUpdateTime time.Time
88+
stderrLogger = log.New(os.Stderr, "", 0)
89+
currentGridLayout = "default"
90+
showHelp = false
91+
updateInterval = 1000
9192
)
9293

9394
var (
@@ -104,8 +105,9 @@ var (
104105

105106
func setupUI() {
106107
appleSiliconModel := getSOCInfo()
107-
modelText = w.NewParagraph()
108+
modelText, helpText = w.NewParagraph(), w.NewParagraph()
108109
modelText.Title = "Apple Silicon"
110+
helpText.Title = "mactop help menu"
109111
modelName, ok := appleSiliconModel["name"].(string)
110112
if !ok {
111113
modelName = "Unknown Model"
@@ -129,41 +131,28 @@ func setupUI() {
129131
pCoreCount,
130132
gpuCoreCount,
131133
)
134+
helpText.Text = "mactop is open source monitoring tool for Apple Silicon authored by Carsen Klock in Go Lang!\n\nRepo: github.com/context-labs/mactop\n\nControls:\n- r: Refresh the UI data manually\n- l: Toggle the main display's layout\n- h or ?: Toggle this help menu\n- q or <C-c>: Quit the application\n\nStart Flags:\n--help, -h: Show this help menu\n--version, -v: Show the version of mactop\n--interval, -i: Set the powermetrics update interval in milliseconds. Default is 1000.\n--color, -c: Set the UI color. Default is none. Options are 'green', 'red', 'blue', 'cyan', 'magenta', 'yellow', and 'white'."
132135
stderrLogger.Printf("Model: %s\nE-Core Count: %d\nP-Core Count: %d\nGPU Core Count: %s",
133136
modelName,
134137
eCoreCount,
135138
pCoreCount,
136139
gpuCoreCount,
137140
)
138141

139-
cpu1Gauge = w.NewGauge()
140-
cpu1Gauge.Title = "E-CPU Usage"
141-
cpu1Gauge.Percent = 0
142-
cpu1Gauge.BarColor = ui.ColorGreen
143-
144-
cpu2Gauge = w.NewGauge()
145-
cpu2Gauge.Title = "P-CPU Usage"
146-
cpu2Gauge.Percent = 0
147-
cpu2Gauge.BarColor = ui.ColorYellow
148-
149-
gpuGauge = w.NewGauge()
150-
gpuGauge.Title = "GPU Usage"
151-
gpuGauge.Percent = 0
152-
gpuGauge.BarColor = ui.ColorMagenta
153-
154-
aneGauge = w.NewGauge()
155-
aneGauge.Title = "ANE"
156-
aneGauge.Percent = 0
157-
aneGauge.BarColor = ui.ColorBlue
158-
159-
PowerChart = w.NewParagraph()
160-
PowerChart.Title = "Power Usage"
161-
162-
NetworkInfo = w.NewParagraph()
163-
NetworkInfo.Title = "Network & Disk Info"
142+
gauges := []*w.Gauge{
143+
w.NewGauge(), w.NewGauge(), w.NewGauge(), w.NewGauge(), w.NewGauge(),
144+
}
145+
titles := []string{"E-CPU Usage", "P-CPU Usage", "GPU Usage", "ANE", "Memory Usage"}
146+
colors := []ui.Color{ui.ColorGreen, ui.ColorYellow, ui.ColorMagenta, ui.ColorBlue, ui.ColorCyan}
147+
for i, gauge := range gauges {
148+
gauge.Percent = 0
149+
gauge.Title = titles[i]
150+
gauge.BarColor = colors[i]
151+
}
152+
cpu1Gauge, cpu2Gauge, gpuGauge, aneGauge, memoryGauge = gauges[0], gauges[1], gauges[2], gauges[3], gauges[4]
164153

165-
ProcessInfo = w.NewParagraph()
166-
ProcessInfo.Title = "Process Info"
154+
PowerChart, NetworkInfo, ProcessInfo = w.NewParagraph(), w.NewParagraph(), w.NewParagraph()
155+
PowerChart.Title, NetworkInfo.Title, ProcessInfo.Title = "Power Usage", "Network & Disk Info", "Process Info"
167156

168157
TotalPowerChart = w.NewBarChart()
169158
TotalPowerChart.Title = "~ W Total Power"
@@ -175,10 +164,6 @@ func setupUI() {
175164
TotalPowerChart.NumFormatter = func(num float64) string {
176165
return ""
177166
}
178-
memoryGauge = w.NewGauge()
179-
memoryGauge.Title = "Memory Usage"
180-
memoryGauge.Percent = 0
181-
memoryGauge.BarColor = ui.ColorCyan
182167
}
183168

184169
func setupGrid() {
@@ -248,6 +233,33 @@ func switchGridLayout() {
248233
}
249234
}
250235

236+
func toggleHelpMenu() {
237+
showHelp = !showHelp
238+
if showHelp {
239+
newGrid := ui.NewGrid()
240+
newGrid.Set(
241+
ui.NewRow(1.0,
242+
ui.NewCol(1.0, helpText),
243+
),
244+
)
245+
termWidth, termHeight := ui.TerminalDimensions()
246+
helpTextGridWidth := termWidth
247+
helpTextGridHeight := termHeight
248+
x := (termWidth - helpTextGridWidth) / 2
249+
y := (termHeight - helpTextGridHeight) / 2
250+
newGrid.SetRect(x, y, x+helpTextGridWidth, y+helpTextGridHeight)
251+
grid = newGrid
252+
} else {
253+
currentGridLayout = map[bool]string{
254+
true: "alternative",
255+
false: "default",
256+
}[currentGridLayout == "default"]
257+
switchGridLayout()
258+
}
259+
ui.Clear()
260+
ui.Render(grid)
261+
}
262+
251263
func StderrToLogfile(logfile *os.File) {
252264
syscall.Dup2(int(logfile.Fd()), 2)
253265
}
@@ -259,17 +271,11 @@ func main() {
259271
err error
260272
setColor, setInterval bool
261273
)
262-
version := "v0.1.8"
274+
version := "v0.1.9"
263275
for i := 1; i < len(os.Args); i++ {
264276
switch os.Args[i] {
265277
case "--help", "-h":
266-
fmt.Println("Usage: mactop [--help] [--version] [--interval] [--color]")
267-
fmt.Println("--help: Show this help message")
268-
fmt.Println("--version: Show the version of mactop")
269-
fmt.Println("--interval: Set the powermetrics update interval in milliseconds. Default is 1000.")
270-
fmt.Println("--color: Set the UI color. Default is white. Options are 'green', 'red', 'blue', 'cyan', 'magenta', 'yellow', and 'white'. (-c green)")
271-
fmt.Println("You must use sudo to run mactop, as powermetrics requires root privileges.")
272-
fmt.Println("For more information, see https://github.com/context-labs/mactop")
278+
fmt.Print("Usage: mactop [--help] [--version] [--interval] [--color]\n--help: Show this help message\n--version: Show the version of mactop\n--interval: Set the powermetrics update interval in milliseconds. Default is 1000.\n--color: Set the UI color. Default is none. Options are 'green', 'red', 'blue', 'cyan', 'magenta', 'yellow', and 'white'. (-c green)\n\nYou must use sudo to run mactop, as powermetrics requires root privileges.\n\nFor more information, see https://github.com/context-labs/mactop written by Carsen Klock.\n")
273279
os.Exit(0)
274280
case "--version", "-v":
275281
fmt.Println("mactop version:", version)
@@ -431,6 +437,12 @@ func main() {
431437
ui.Clear()
432438
switchGridLayout()
433439
ui.Render(grid)
440+
case "h", "?": // "h" or "?" to open help menu
441+
termWidth, termHeight := ui.TerminalDimensions()
442+
grid.SetRect(0, 0, termWidth, termHeight)
443+
ui.Clear()
444+
toggleHelpMenu()
445+
ui.Render(grid)
434446
}
435447
case <-done:
436448
ui.Close()
@@ -758,10 +770,10 @@ func parseCPUMetrics(powermetricsOutput string, cpuMetrics CPUMetrics, modelName
758770
cpuMetrics.P3ClusterFreqMHz = freqMHz
759771
}
760772
if strings.HasPrefix(cluster, "E") {
761-
eClusterFreqTotal += int(freqMHz)
773+
eClusterFreqTotal += freqMHz
762774
cpuMetrics.EClusterFreqMHz = eClusterFreqTotal
763775
} else if strings.HasPrefix(cluster, "P") {
764-
pClusterFreqTotal += int(freqMHz)
776+
pClusterFreqTotal += freqMHz
765777
cpuMetrics.PClusterFreqMHz = pClusterFreqTotal
766778
}
767779
}
@@ -805,24 +817,24 @@ func parseCPUMetrics(powermetricsOutput string, cpuMetrics CPUMetrics, modelName
805817

806818
cpuMetrics.ECores = eCores
807819
cpuMetrics.PCores = pCores
808-
if cpuMetrics.E1ClusterActive != 0 {
809-
// M1 Ultra
820+
multra, mmax := false, false
821+
if cpuMetrics.E1ClusterActive != 0 { // M1 Ultra
810822
cpuMetrics.EClusterActive = (cpuMetrics.E0ClusterActive + cpuMetrics.E1ClusterActive) / 2
811823
cpuMetrics.EClusterFreqMHz = max(cpuMetrics.E0ClusterFreqMHz, cpuMetrics.E1ClusterFreqMHz)
824+
multra = true
812825
}
813-
if cpuMetrics.P3ClusterActive != 0 {
814-
// M1 Ultra
826+
if cpuMetrics.P3ClusterActive != 0 { // M1 Ultra
815827
cpuMetrics.PClusterActive = (cpuMetrics.P0ClusterActive + cpuMetrics.P1ClusterActive + cpuMetrics.P2ClusterActive + cpuMetrics.P3ClusterActive) / 4
816828
cpuMetrics.PClusterFreqMHz = max(cpuMetrics.P0ClusterFreqMHz, cpuMetrics.P1ClusterFreqMHz, cpuMetrics.P2ClusterFreqMHz, cpuMetrics.P3ClusterFreqMHz)
817-
} else if cpuMetrics.P1ClusterActive != 0 {
818-
// M1/M2/M3 Max/Pro
829+
multra = true
830+
} else if cpuMetrics.P1ClusterActive != 0 && !multra { // M1/M2/M3 Max/Pro
819831
cpuMetrics.PClusterActive = (cpuMetrics.P0ClusterActive + cpuMetrics.P1ClusterActive) / 2
820832
cpuMetrics.PClusterFreqMHz = max(cpuMetrics.P0ClusterFreqMHz, cpuMetrics.P1ClusterFreqMHz)
821-
} else {
822-
// M1
833+
mmax = true
834+
} else if !multra && !mmax { // M1
823835
cpuMetrics.PClusterActive = cpuMetrics.PClusterActive + cpuMetrics.P0ClusterActive
824836
}
825-
if eClusterCount > 0 { // Calculate average active residency and frequency for E and P clusters
837+
if eClusterCount > 0 && !multra && !mmax { // Calculate average active residency and frequency for E and P clusters
826838
cpuMetrics.EClusterActive = eClusterActiveTotal / eClusterCount
827839
}
828840
}

0 commit comments

Comments
 (0)