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

Memory leak in widget renderer and texture caches #2069

Closed
fpabl0 opened this issue Mar 8, 2021 · 10 comments
Closed

Memory leak in widget renderer and texture caches #2069

fpabl0 opened this issue Mar 8, 2021 · 10 comments
Labels
bug Something isn't working

Comments

@fpabl0
Copy link
Member

fpabl0 commented Mar 8, 2021

Describe the bug:

Fyne widgets use internally a renderer cache to improve performance, however when the widget goes out of the scope, Fyne does not have any way to free that memory from the cache.

var renderers sync.Map

The same thing occurs with canvas primitives and the texture cache:

var textures = make(map[fyne.CanvasObject]Texture, 1024)

This memory leak occurs commonly when user replaces objects in containers:

c.Objects[2] = widget.NewLabel("Hello1")
c.Objects[3] = canvas.NewText("Text1", color.Black)
...
c.Objects[2] = widget.NewLabel("Hello2") //  🔴 "Hello1" renderer is kept in renderer cache and have no way to be freed
c.Objects[3] = canvas.NewText("Text2", color.Black) // 🔴 "Text1" is kept in texture cache and have no way to be freed

This could be the root cause of #348.
This is also an extension from #735.

To Reproduce:

This memory can be seen in fyne_demo, when the tutorials contents are set:

fyne/cmd/fyne_demo/main.go

Lines 111 to 112 in 8fa5af4

content.Objects = []fyne.CanvasObject{t.View(w)}
content.Refresh()

  1. Run fyne_demo.
  2. Change tutorial views.
  3. Use the Activity Monitor and see how the memory used is increased every time you change the view.

Device (this issue is platform independent):

  • OS: MacOS
  • Version: 10.15.4 Catalina
  • Go version: 1.16
  • Fyne version: develop @ 8fa5af4
@fpabl0 fpabl0 added the bug Something isn't working label Mar 8, 2021
@fpabl0
Copy link
Member Author

fpabl0 commented Mar 8, 2021

This introduce also a severe memory leak when selecting text in widget.Entry, because selection rectangles are regenerated:

fyne/widget/entry.go

Lines 1464 to 1467 in 8fa5af4

if len(r.selection) <= i {
box := canvas.NewRectangle(theme.PrimaryColor())
r.selection = append(r.selection, box)
}

And the entry's objects are generated dynamically:

fyne/widget/entry.go

Lines 1358 to 1363 in 8fa5af4

// Objects are generated dynamically force selection rectangles to appear underneath the text
if r.content.entry.selecting {
objs := make([]fyne.CanvasObject, 0, len(r.selection)+len(r.objects))
objs = append(objs, r.selection...)
return append(objs, r.objects...)
}

if you keep selecting and deselecting text, you will see that the memory used will increase.

@fpabl0
Copy link
Member Author

fpabl0 commented Mar 8, 2021

Same memory leak issue has the widget.List:

fyne/widget/list.go

Lines 405 to 407 in 8fa5af4

objects := l.children
objects = append(objects, l.separators...)
l.list.scroller.Content.(*fyne.Container).Objects = objects

Maybe other widgets like widget.Tree may have the same issue, needs investigation.

@andydotxyz
Copy link
Member

Yes, this is an issue that needs resolved. We have Destroy for widget, but that is not catching all of the instances.
What I think we need to do is identify when widgets / objects disappear and schedule them for cleanup.

Probably a duplicate of #348

@Jacalz
Copy link
Member

Jacalz commented Mar 8, 2021

What I think we need to do is identify when widgets / objects disappear and schedule them for cleanup.

We might be able to utilize https://golang.org/pkg/runtime/#SetFinalizer for part of that cleanup (perhaps setting the Destroy() function in it). Just throwing the thought out there in case it can be helpful 🙂

@andydotxyz
Copy link
Member

The issue here isn't so much that the widgets are done but that some texture cached in the driver is unused.
They don't map 1:1

@fpabl0
Copy link
Member Author

fpabl0 commented Mar 8, 2021

Probably a duplicate of #348

Maybe, although that issue was treated as specific for images (but it is not). Indeed, this should be the root cause of it, as I said in the first comment. This could be a duplicated of #735 (although in that issue texture cache is not pointed out)

@andydotxyz
Copy link
Member

They are indeed all related. Not clear which are the true root cause, but various caches should be cleared once we are able to track what objects / caches are no longer needed.

@fpabl0
Copy link
Member Author

fpabl0 commented Mar 8, 2021

Hmm maybe we should walk over the object tree at fixed intervals and compare them with caches, if an object is in the cache but not in tree, then it should be removed from the cache. However, not sure how this would impact the performance, cause we would need to walk the object tree quite often.

@andydotxyz
Copy link
Member

andydotxyz commented Mar 9, 2021

Yes, that is the balance to be found. Though we would get away with not-very-often I would think.

@fpabl0
Copy link
Member Author

fpabl0 commented Jul 27, 2021

Fixed on develop :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants