Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty but visible images consume high CPU on 2.4.x #4345

Closed
2 tasks done
dweymouth opened this issue Oct 26, 2023 · 6 comments
Closed
2 tasks done

Empty but visible images consume high CPU on 2.4.x #4345

dweymouth opened this issue Oct 26, 2023 · 6 comments
Labels
bug Something isn't working optimization Tickets that could help Fyne apps run faster

Comments

@dweymouth
Copy link
Contributor

dweymouth commented Oct 26, 2023

Checklist

  • I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
  • This issue only relates to a single bug. I will open new issues for any other problems.

Describe the bug

A canvas.Image that is empty (no image.Image, fyne.Resource or file set) but not hidden will cause high CPU use as it causes constant texture cache misses and a new GL texture to be created for the "image" on every redraw. This is a regression from 2.3.x.

How to reproduce

Run the example app

Screenshots

Example code

package main

import (
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
)

func main() {

	myApp := app.New()
	myWindow := myApp.NewWindow("Empty image perf regression")

	myWindow.SetContent(canvas.NewImageFromImage(nil))
	myWindow.Resize(fyne.NewSize(400, 400))
	myWindow.ShowAndRun()
}

Fyne version

2.4.1

Go compiler version

go1.21.1

Operating system and version

macOS Ventura M2

Additional Information

No response

@dweymouth dweymouth added the unverified A bug that has been reported but not verified label Oct 26, 2023
@dweymouth dweymouth changed the title Image performance regression in 2.4.x compared to 2.3.x Image-related CPU use performance regression in 2.4.x compared to 2.3.x Oct 26, 2023
@dweymouth dweymouth added the optimization Tickets that could help Fyne apps run faster label Oct 26, 2023
@dweymouth
Copy link
Contributor Author

OK I've managed to work out that it's texture cache misses. newGlImageTexture which is in the pprof trace is only referenced here in drawImage, and print statements in getTexture (which is called by drawTextureWithDetails) reveal that on 2.3.x there are a handful of cache misses on startup (as expected), but then none until mousing over an image. On 2.4.x however it continues to have dozens of cache misses a second even when not interacting with the app

@dweymouth dweymouth added bug Something isn't working and removed unverified A bug that has been reported but not verified labels Oct 31, 2023
@dweymouth dweymouth changed the title Image-related CPU use performance regression in 2.4.x compared to 2.3.x Empty but visible images consume high CPU on 2.4.x Oct 31, 2023
@dweymouth dweymouth added this to the D fixes (v2.4.x) milestone Oct 31, 2023
dweymouth added a commit to dweymouth/supersonic that referenced this issue Nov 1, 2023
@andydotxyz
Copy link
Member

Should we mark this as blocker for v2.4.3 (i.e. the point release after current work)?

@dweymouth
Copy link
Contributor Author

Should we mark this as blocker for v2.4.3 (i.e. the point release after current work)?

I imagine this should be a quick fix to someone familiar with the image painter but I don't know what the fix is. On the other hand it has a very easy workaround (hide empty images) so personally I don't feel it needs to be high priority, unless others complain about it.

@andydotxyz
Copy link
Member

I'm inclined to agree - unless there is a common case when images may be empty and developers won't know, or be able to tell?

@andydotxyz
Copy link
Member

I wonder if the following is a good solution? It doesn't seem to take the CPU usage to 0 though...

--- a/internal/painter/gl/draw.go
+++ b/internal/painter/gl/draw.go
@@ -36,6 +36,9 @@ func (p *painter) drawGradient(o fyne.CanvasObject, texCreator func(fyne.CanvasO
 }
 
 func (p *painter) drawImage(img *canvas.Image, pos fyne.Position, frame fyne.Size) {
+       if img.Image == nil && img.File == "" && img.Resource == nil || img.Translucency == 1.0 {
+               return
+       }
        p.drawTextureWithDetails(img, p.newGlImageTexture, pos, img.Size(), frame, img.FillMode, float32(img.Alpha()), 0)
 }

@andydotxyz
Copy link
Member

Resolved by #5290, I'm glad to have found a better solution than I proposed before - it helps when you identify the root cause ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working optimization Tickets that could help Fyne apps run faster
Projects
None yet
Development

No branches or pull requests

2 participants