fyne-io / fyne

Cross platform GUI toolkit in Go inspired by Material Design

Home Page:https://fyne.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Form layout allocates a new 2d slice on each MinSize and Layout call

Jacalz opened this issue · comments

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

I noticed that the form layout allocates a two-dimensional slice on each call to Layout and MinSize:
fyne-io/fyne/blob/d8e9fe02c9bb9e4b4c42778f5cae8ffcc43f36e2/layout/formlayout.go#L38

This was likely a way to write simpler code some time but it does mean that (especially noticeable for large forms) the layout can allocate a lot of garbage each second when layout and minsize has to be computed often.

How to reproduce

Look at memory profiles or use b.ReportAllocs() in benchmarks.

Fyne version

v2.4.5

Go compiler version

1.22.1

Operating system and version

Fedora Silverblue 40

Additional Information

I think the best option is to do a large refactor of the layout and remove the allocations from the fast path.
The code is also, in my opinion at least, quite convoluted and could do with a cleanup to make it more readable.

Hmm, I'm actually not sure there's a way to avoid allocation without the possibly worse tradeoff of invoking MinSize() twice per cell instead of once per cell. (Remembering that MinSize can be user code for a custom widget that may not be efficient). It could possibly be turned into a 1D slice of row heights that is allocated. And might be a candidate for using a sync.Pool since there are instances where MinSize and Layout will be called very frequently (eg user resizing a window or split container)

Using a pool would likely be a big improvement given how often it can be called. I'd need to look at the code more but I feel like there should be a better way to refactor the algorithm to not need that table. Maybe use some modulo operation into the object slice?

It seems to me (and initial prints seem to show the same thing) that the table is just a slice of the two exact same widths with only the height potentially differing.