First, I apologize for the repeated feedback on issues #618 and #617, as I couldn't find a way to modify the status of the ticket.
Now the Gio version I use is v0.7.1-0.20241025200657-8daff13af6cd
(in go.mod
file) after using go get gioui.org@main
, and there is still an issue with abnormal CPU consumption after minimizing the window.
Here is the minimal reproducible code:
package main
import (
"os"
"strconv"
"time"
"gioui.org/app"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/widget/material"
)
func main() {
go func() {
run(new(app.Window))
os.Exit(0)
}()
app.Main()
}
func run(window *app.Window) {
var result string
var ops op.Ops
ticker := time.NewTicker(time.Millisecond)
go func() {
start := time.Now()
for tick := range ticker.C {
result = strconv.FormatInt(tick.Sub(start).Milliseconds(), 10)
// window.Invalidate()
}
}()
for {
switch e := window.Event().(type) {
case app.DestroyEvent:
return
case app.FrameEvent:
gtx := app.NewContext(&ops, e)
layout.Center.Layout(gtx, material.Label(material.NewTheme(), 10, result).Layout)
e.Frame(gtx.Ops)
gtx.Execute(op.InvalidateCmd{})
}
}
}
In this version of Gio, interacting with the widgets (#617 and #618) will not cause the abnormal CPU consumption after minimizing the window. However, the code mentioned above still causes an abnormal CPU usage. When running the code, open the Task Manager, set the refresh rate to maximum, and then minimize the window. I notice that the CPU usage of the program initially increases quickly and then drops to 0 (or close to 0).
It's worth noting that if I uncomment that line of code and remove the last line of the for loop, this refresh method will maintain high CPU usage after minimizing the window. Yes, I know that this method is less efficient than the previous one, but it doesn't cause such high CPU usage when the window is not minimized.
I inclined to say that "you're holding it wrong": waking up the window every millisecond is always a bad idea, even though it may be done more efficiently. I assume your actual code is doing something similar, but why?
I'm really sorry for causing confusion. Actually, I'm not a pro programmer, so please excuse my "foolish" coding ways.
The main thing of the original code is to display a stopwatch area with millisecond accuracy. Since this code wasn't good, I would like to ask how to use Gio in a better way to get this done?
Additionally, I brought up this issue because it's an unexpected thing. Even though this update method might not be that reasonable, the CPU usage of the two different states shouldn't be so different based on my gut feeling. Of course, it'd be great if this problem goes away by using a more sensible way to implement my requirement.
Your monitor isn't able to display 1000 frames per second, so it isn't realistically possible to display every timestamp. To display high-resolution time, you can modify your code to:
func run(window *app.Window) { var result string var ops op.Ops start := time.Now() for { switch e := window.Event().(type) { case app.DestroyEvent: return case app.FrameEvent: result = strconv.FormatInt(time.Now().Sub(start).Milliseconds(), 10) gtx := app.NewContext(&ops, e) layout.Center.Layout(gtx, material.Label(material.NewTheme(), 10, result).Layout) // Schedule another frame as soon as possible. gtx.Execute(op.InvalidateCmd{}) e.Frame(gtx.Ops) } } }This will draw frames as fast as the system supports, and will present a timestamp that is at most the render latency old.
Thanks for the suggestion, but with the new code, the CPU usage will remain high after the window is minimized. The problem remains.
Elias Naur referenced this ticket in commit a7a691e.
Elias Naur referenced this ticket in commit e89a386.
Elias Naur referenced this ticket in commit ccb1ab4.
Turns out the problem was in both macOS and Windows. Please try the newest version and let me know if it fixes your issue.
Elias Naur referenced this ticket in commit 1ae2b9b.
Elias Naur referenced this ticket in commit f200f0e.
The issue has been resolved after using version 0.8.0. Thanks!