-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
internal/driver/glfw: clean the cache periodically. #5112
base: develop
Are you sure you want to change the base?
Conversation
The cache is supposed to be cleaned periodically, but the glfw driver does not do this as the mobile driver does. This commit adds similar logic to the glfw driver as exists in the mobile driver, to periodically clean the cache on paint events. Fixes fyne-io#4903
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a good fix. Are you happy we land this before looking at the refactor we discussed @dweymouth ?
I suppose, though I suspect we are now doing double cache cleaning work on each clean, since it is calling both cache.Clean and cache.CleanCanvases, which duplicate most of the cleanup tasks. I had thought perhaps cache.CleanCanvases was introduced because cache.Clean couldn't be used in the desktop driver for whatever reason, but if we are calling cache.Clean now, it is very likely CleanCanvases is totally redundant and we should evaluate and remove it |
From a quick glance it seems the only clean task missing from CleanCanvases is the call to destroyExpiredFontMetrics, so another fix could be just adding that call to CleanCanvases. I would really love if someone who was involved in the initial caching design could review these two funcs more deeply and figure out if we still need the separation between the two |
fyne/internal/driver/glfw/loop.go Lines 78 to 98 in 7d81356
The issue is that Lines 132 to 145 in 7d81356
If we want Line 51 in 7d81356
|
I really hope @andydotxyz or someone else with deeper knowledge into the initial design of the cache and clean tasks can take another look at this, since I don't understand the design well enough to recommend between merging CleanCanvases and Clean into one func, or adding the missed |
In my fork I've removed the renderer cache entirely since it was causing issues, and I can't see, from a technical perspective, what benefit it brings that outweighs the downsides. Issues included:
There are two potential benefits to the render cache that I see, listed here along with counter-points:
In the process of these changes, I also discovered a number of bugs, mostly related to widgets failing to call If the project is interested in my modifications, I will clean it up and put up another PR for review. Based on my profiling, this improves performance in a number of cases, and probably improves correctness. |
By getting rid of the render cache, do you mean in your fork the widget gets a new renderer created every time it is rendered? I imagine that would bring its own set of memory and performance issues, I think we'd be more interested in fixing the incorrectness with the current render cache than removing it entirely |
No, each widget keeps a reference to its renderer. In practice, this is handled by the base widgets. I added a
And then all calls to This, of course, does change the API, and so would probably require a major version bump. But there are ways around that if you want to keep the existing API. |
Ah yes, that would be a breaking public API change, as existing widgets would now have to add this new method to continue to function, but could be an option for Fyne 3.x if we ever have the need to introduce other breaking changes (it is not planned anytime soon). In the meantime, fixing the render cache mechanism is something we will need to pursue. I haven't encountered any issues other than the memory leak you've identified with the current system though. |
When I have more free time to work on this, I'll try to produce a sample application that demonstrates the other issues. The race condition will probably be hard to trigger, but I should be able to trigger the freeze since that was happening very regularly. |
Yes, when you have the time please file an issue report for the freezing you're seeing along with a toy app to demonstrate it - as I don't believe any contributors have encountered anything like that and it's an unknown issue right now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just commenting to put a block on merging so we don't accidentally merge this and introduce the window-freezing bug @knusbaum described
@knusbaum Is your change in your fork to remove the renderer cache on a public branch somewhere? I'd be curious to take a look at it (and maybe considering using it in my fork for my app as well if it's a simple diff) |
@dweymouth It's not public at the moment. It's mixed in with a bunch of other changes I've made testing out optimizations. Some have worked and others have not been valuable. I will pull that change out and put it on a public branch. When it's done I'll let you know here. |
@dweymouth here's my branch with the cache removed, based on the develop branch: I'm not sure everything's fixed, and I haven't updated the tests at all. |
Description:
The cache is supposed to be cleaned periodically, but the glfw driver does not do this as the mobile driver does.
This commit adds similar logic to the glfw driver as exists in the mobile driver, to periodically clean the cache on paint events.
Fixes #4903
Notes to Reviewers:
I'm calling
cache.Clean
in a similar way to how it's done in the mobile driver:fyne/internal/driver/mobile/driver.go
Lines 280 to 293 in 5fb3d75
I don't fully understand what the boolean value passed to clean represents, or if what I'm doing makes sense. I'm just mimicking the code from mobile.
I have not written regression tests for this, as I'm not familiar enough with the code to confidently do so.
Checklist:
Not all the tests pass on the current
develop
branch, but this PR does not cause new test failures.