Skip to content

Commit 03bb092

Browse files
committed
fix: performance issue caused by the render calls
mactop has high CPU usage. Running it with cpuprofiling shows that the top CPU time is spent in the termui.Render calls (to be specific, in the ioctl syscalls there). I removed a bunch of unnecessary Render calls (there were some duplicates) and replaced all the other calls with a throttled version: I call Render in the main process but not more often than twice in the single "update interval" period. This should address issue #13.
1 parent 28cdb2f commit 03bb092

File tree

1 file changed

+35
-11
lines changed

1 file changed

+35
-11
lines changed

main.go

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,35 @@ type MemoryMetrics struct {
4848
Total, Used, Available, SwapTotal, SwapUsed uint64
4949
}
5050

51+
type EventThrottler struct {
52+
timer *time.Timer
53+
gracePeriod time.Duration
54+
55+
C chan struct{}
56+
}
57+
58+
func NewEventThrottler(gracePeriod time.Duration) *EventThrottler {
59+
return &EventThrottler{
60+
timer: nil,
61+
gracePeriod: gracePeriod,
62+
C: make(chan struct{}, 1),
63+
}
64+
}
65+
66+
func (e *EventThrottler) Notify() {
67+
if e.timer != nil {
68+
return
69+
}
70+
71+
e.timer = time.AfterFunc(e.gracePeriod, func() {
72+
e.timer = nil
73+
select {
74+
case e.C <- struct{}{}:
75+
default:
76+
}
77+
})
78+
}
79+
5180
var (
5281
cpu1Gauge, cpu2Gauge, gpuGauge, aneGauge *w.Gauge
5382
TotalPowerChart *w.BarChart
@@ -173,7 +202,6 @@ func setupGrid() {
173202

174203
func switchGridLayout() {
175204
if currentGridLayout == "default" {
176-
ui.Clear()
177205
newGrid := ui.NewGrid()
178206
newGrid.Set(
179207
ui.NewRow(1.0/2, // This row now takes half the height of the grid
@@ -196,9 +224,7 @@ func switchGridLayout() {
196224
newGrid.SetRect(0, 0, termWidth, termHeight)
197225
grid = newGrid
198226
currentGridLayout = "alternative"
199-
ui.Render(grid)
200227
} else {
201-
ui.Clear()
202228
newGrid := ui.NewGrid()
203229
newGrid.Set(
204230
ui.NewRow(1.0/2,
@@ -219,7 +245,6 @@ func switchGridLayout() {
219245
newGrid.SetRect(0, 0, termWidth, termHeight)
220246
grid = newGrid
221247
currentGridLayout = "default"
222-
ui.Render(grid)
223248
}
224249
}
225250

@@ -352,21 +377,24 @@ func main() {
352377
appleSiliconModel := getSOCInfo()
353378
go collectMetrics(done, cpuMetricsChan, gpuMetricsChan, netdiskMetricsChan, processMetricsChan, appleSiliconModel["name"].(string))
354379
lastUpdateTime = time.Now()
380+
needRender := NewEventThrottler(time.Duration(updateInterval/2) * time.Millisecond)
355381
go func() {
356382
for {
357383
select {
358384
case cpuMetrics := <-cpuMetricsChan:
359385
updateCPUUI(cpuMetrics)
360386
updateTotalPowerChart(cpuMetrics.PackageW)
361-
ui.Render(grid)
387+
needRender.Notify()
362388
case gpuMetrics := <-gpuMetricsChan:
363389
updateGPUUI(gpuMetrics)
364-
ui.Render(grid)
390+
needRender.Notify()
365391
case netdiskMetrics := <-netdiskMetricsChan:
366392
updateNetDiskUI(netdiskMetrics)
367-
ui.Render(grid)
393+
needRender.Notify()
368394
case processMetrics := <-processMetricsChan:
369395
updateProcessUI(processMetrics)
396+
needRender.Notify()
397+
case <-needRender.C:
370398
ui.Render(grid)
371399
case <-quit:
372400
close(done)
@@ -489,7 +517,6 @@ func updateTotalPowerChart(newPowerValue float64) {
489517
}
490518
powerValues = nil
491519
lastUpdateTime = currentTime
492-
ui.Render(TotalPowerChart)
493520
}
494521
}
495522

@@ -507,8 +534,6 @@ func updateCPUUI(cpuMetrics CPUMetrics) {
507534
memoryMetrics := getMemoryMetrics()
508535
memoryGauge.Title = fmt.Sprintf("Memory Usage: %.2f GB / %.2f GB (Swap: %.2f/%.2f GB)", float64(memoryMetrics.Used)/1024/1024/1024, float64(memoryMetrics.Total)/1024/1024/1024, float64(memoryMetrics.SwapUsed)/1024/1024/1024, float64(memoryMetrics.SwapTotal)/1024/1024/1024)
509536
memoryGauge.Percent = int((float64(memoryMetrics.Used) / float64(memoryMetrics.Total)) * 100)
510-
ui.Render(grid)
511-
ui.Render(cpu1Gauge, cpu2Gauge, gpuGauge, aneGauge, memoryGauge, modelText, PowerChart)
512537
}
513538

514539
func updateGPUUI(gpuMetrics GPUMetrics) {
@@ -532,7 +557,6 @@ func updateProcessUI(processMetrics []ProcessMetrics) {
532557
for _, pm := range processMetrics {
533558
ProcessInfo.Text += fmt.Sprintf("%d - %s: %.2f ms/s\n", pm.ID, pm.Name, pm.CPUUsage)
534559
}
535-
ui.Render(ProcessInfo)
536560
}
537561

538562
func parseProcessMetrics(powermetricsOutput string, processMetrics []ProcessMetrics) []ProcessMetrics {

0 commit comments

Comments
 (0)