In Ruby, if I declare a lambda function inside a loop, will it clean up properly after each iteration?

I have something like this:

for i in 1..100000
    template = GetTemplate(i)

    set_setting_lam = lambda do |setting|
        (...) # Would prefer not to duplicate the code for the loops below
        template.setting = setting
    end

    for setting in settingArray
        set_setting_lam.call(setting)
    end

    for setting in settingList
        set_setting_lam.call(setting)
    end
end

      

Will this generate 100,000 set_setting_lam

objects, or will it clean up after each iteration?

+3


source to share


3 answers


A lambda is an object like any other object.

Of course, if you create an object in a loop that runs 100,000 times, 100,000 objects will be created. This does not apply to lambdas, it applies to all objects. And of course, as soon as an object is no longer available, it becomes garbage collection. Again, this is not the case for lambdas, this is for all objects.



The system decides when to run the garbage collector and how many and what objects to collect. If you are running out of memory, the garbage collector might not work at all! Even if the garbage collector does eventually, it is impossible to tell when it will. And even when it works, there is no guarantee that it will collect all the suitable objects, and there is no way to tell which objects it will collect.

That it's all about automatic memory management: it's automatic!

+2


source


It will create objects and they will not be cleaned up after each iteration based on this:

object_ids = []
1.upto(5) { |i| object_ids << lambda{ i }.object_id }
object_ids.each do |object_id|
  puts "#{ ObjectSpace._id2ref(object_id) } - #{ ObjectSpace._id2ref(object_id).call }"
end

#<Proc:0x007fae509c7380@test1.rb:2 (lambda)> - 1
#<Proc:0x007fae509c7330@test1.rb:2 (lambda)> - 2
#<Proc:0x007fae509c72e0@test1.rb:2 (lambda)> - 3
#<Proc:0x007fae509c7290@test1.rb:2 (lambda)> - 4
#<Proc:0x007fae509c7240@test1.rb:2 (lambda)> - 5

      



UPD

It will start garbage collection after a while since 1000 888 objects were left in memory after the loop for me.

+4


source


After playing around with @Rustam A. Gasanov's answer, the answer is no: Ruby's garbage collector will start cleaning it up eventually, but not after every iteration.

Duration:

object_ids = []
1.upto(1000) { |i| object_ids << lambda{ i }.object_id }
object_ids.each_with_index do |object_id, index|
  puts index
  puts "#{ ObjectSpace._id2ref(object_id) } - #{ ObjectSpace._id2ref(object_id).call }"
end

      

results in _id2ref': 0x13a2c74 is recycled object (RangeError)

or something like that after a while (for me it gave an error at index 160).

0


source







All Articles