-
Notifications
You must be signed in to change notification settings - Fork 145
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
Fix Emitter memory leak #330
base: dev
Are you sure you want to change the base?
Fix Emitter memory leak #330
Conversation
Listeners created by `:once()` were put into an internal table and never removed. Fixed this by making the table weak-keyed.
I have a feeling this won't work. |
@GitSparTV The table is not array-like; keys are I stumbled upon this issue when I noticed that some of my objects (which used |
Does :once create Listener object? |
It does Discordia/libs/utils/Emitter.lua Lines 50 to 55 in f6aea20
|
Ok last question, when the emitter is not yet emitted, will the listener object live? What if GC cycle happens before emitting? |
There should also be a reference to the listener in the |
Nice |
Looking at my code, it looks like I never clean |
Discordia/libs/utils/Emitter.lua Lines 83 to 86 in 4736f7e
listeners[i] = false could be replaced with a table.remove(listeners, i) call (of course, you'd have to iterate backwards).
Discordia/libs/utils/Emitter.lua Lines 54 to 63 in 4736f7e
clean() if you did that unless you were planning to somehow optimize it.
|
Listeners are intentionally marked for deletion instead of directly removed to avoid unexpected behavior due to table contraction while actively iterating that table. Marked listeners are cleaned only after the |
My emitter implementation in the sandbox branch does not use the "once" table, so that leak is fixed there and will eventually merge into an active 3.0 branch (probably dev). I've also just committed a change to the sandbox so that listener tables are now correctly marked in the There is still the issue where the listener table can theoretically grow unbounded if a user continuously adds and removes listeners. To fix this, I think I need to use a different data structure than a simple Lua table. |
Listeners created by the
Emitter:once()
method get put into an internal table, but are never removed from said table, causing them to never be GC'd. This PR fixes this issue by making the internal table's keys be weak.(It also slightly simplifies the code used to clean the listener tables).