-
Notifications
You must be signed in to change notification settings - Fork 21
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
Widget memory is not freed when removed #126
Comments
Could you try running the program with this? GOTK4_DEBUG=trace-objects,toggle-refs go run -v . This will cause gotk4 to give you a log file that you can |
It might also be worth it to run |
Also as a side note, it can be really hard for Go's GC to know when to actually run, because the bulk of the allocations are on the C heap. For this reason, gotkit/gtkutil/aggressivegc exists. |
I can manually trigger GC on every button click and it makes little difference, memory still goes up each time. Tried looking at the log, but I don't see anything useful in there. Edit: is it supposed to show when an object is freed? All I see is these two lines being repeated:
Here's a pprof graph with total memory being a few hundred megs: And here's the same with memory >1GB: So while most of the memory is C heap, I think it's Go that's keeping the references alive. But this stuff's a little out of my league 😄 Also updated the code above with pprof and GC calls if you want to try for yourself. |
Yeah, this isn't good. The debug is supposed to say when objects are being freed. I'm busy this weekends but I will look into this as soon as I can. I think the same bug is appearing on gtkcord4 as well. |
I figured it out! The ref-counting for floating references was all out of wack. |
--- a/pkg/core/intern/intern.go
+++ b/pkg/core/intern/intern.go
// We should already have a strong reference. Sink the object in case. This
// will force the reference to be truly strong.
if C.g_object_is_floating(C.gpointer(gobject)) != C.FALSE {
+ // First, we need to ref_sink the object to convert the floating
+ // reference to a strong reference.
C.g_object_ref_sink(C.gpointer(gobject))
+ // Then, we need to unref it to balance the ref_sink.
+ C.g_object_unref(C.gpointer(gobject))
+
+ if toggleRefs != nil {
+ toggleRefs.Println(objInfo(gobject),
+ "Get: ref_sink'd the object, current ref =", objRefCount(gobject))
+ }
} |
As a side note, using toggle references for all objects likely kills performance a lot. It's much more ideal if they're only used if we're working with closures attached to objects. |
Awesome, that fixes it! Thank you |
Reopening due to a regression. |
would this cause |
The |
Hm... because if i remove the Edit: I've switched |
Ah, it looks like Could you open a separate issue for this? |
would somekinda bug bounty be an option? is anyone else able to fix this? i'm afraid money doesn't change the fact @diamondburned has no time to fix this.... someone else? |
Actually, once golang/go#67535 lands in Go 1.24, I'll definitely be fixing this problem, now that it's... actually fixable. |
Words alone cannot express how excited I am for this feature to land so I can finally fix this years-old bug in gotk4 that I spent years thinking about @@ |
I've noticed that memory usage increases over time in my application, and it seems to be directly related to the replacement of widgets. A GtkColumnView does not leak memory when re-rendering, but when I remove and recreate widgets myself, it appears that the old ones are not freed. Here's an example program:
With enough clicks, you can reach one gigabyte and more. The widgets aren't referenced after being removed so I'd expect GC to trigger, but it doesn't.
The text was updated successfully, but these errors were encountered: