From: "ioquatix (Samuel Williams) via ruby-core" Date: 2023-01-16T09:53:07+00:00 Subject: [ruby-core:111830] [Ruby master Feature#19333] Setting (Fiber Local|Thread Local|Fiber Storage) to nil should delete value in order to avoid memory leaks. Issue #19333 has been updated by ioquatix (Samuel Williams). While the proposed idea is a good move in the right direction, it doesn't handle cases where several (a large number) threads all have the SAME thread local, and that thread local goes out of scope, e.g. ``` name = ":local-#{object_id} 100.times do Thread.new do thing = ... something that consumes memory ... Thread.current.thread_variable_set(name, thing) # Thread lives for a long time while job = jobs.pop job.call end end end ``` Even when `name` is no longer useful for any purpose, all those threads sill still have that thread local set. There is no global way to say "For all threads that have a thread local set for name, please clear it". In order to do that, we'd need to introduce a `Thread::Local` object which uniquely identifies an association in 0 or more threads, and when that `Thread::Local` instance is GCed, all threads which have it set, have it cleared. This ensures that threads don't leak memory. Consider a work pool that allocates a new `Thread::Local `every now and then... eventually threads will have lots of locals which are potentially no longer useful. That being said, the other option is just not to encourage people to have long running threads that accumulate cruft over time. ---------------------------------------- Feature #19333: Setting (Fiber Local|Thread Local|Fiber Storage) to nil should delete value in order to avoid memory leaks. https://bugs.ruby-lang.org/issues/19333#change-101239 * Author: ioquatix (Samuel Williams) * Status: Open * Priority: Normal ---------------------------------------- As it stands, Fiber Locals, Thread Locals and Fiber Storage have no way of deleting key-value associations. ```ruby 100.times do |i| name = :"variable-#{i}" Thread.current[name] = 10 end ``` Because of this, dynamically generated associations can leak over time. This is worse for things like Threads that might be pooled (or maybe an argument against user-space pooling). In any case, having a way to delete those associations would allow application code to at least delete the associations when they no longer make sense. I propose that assigning `nil` to "locals" or "storage" should effectively delete them. e.g. ```ruby 100.times do |i| name = :"variable-#{i}" Thread.current[name] = 10 Thread.current[name] = nil # delete association end ``` A more invasive alternative would be to define new interfaces like `Thread::Local`, `Fiber::Local` and `Fiber::Storage::Local` (or something) which correctly clean up on GC. -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/