# Memory usage with blocks

**URL:** <https://www.ruby-forum.com/t/memory-usage-with-blocks/154623>\
**Category:** Ruby\
**Created:** [December 2, 2008, 9:25am UTC](https://www.ruby-forum.com/t/memory-usage-with-blocks/154623 "2008-12-02T09:25:26Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [December 2, 2008, 9:25am UTC](https://www.ruby-forum.com/t/memory-usage-with-blocks/154623/1 "2008-12-02T09:25:26Z")

</div>

Hi all,

I’ve got some code, which when run uses a lot of memory (aprox 600 MB  
for a  
particular given input). I am trying to figure out why it is using so  
much.

When I replace the following code:

```
            head.play_back do |root|
               block.call(root)
            end

```

With this:

```
            head.play_back(&block)

```

And make other similar changes. The program behaves exactly the same  
way,  
but now uses 200MB less. Can someone explain to me why this is the  
case?

I use blocks everywhere and I’m worried, they’re leaking in my code.

joky@linux08:~/wa/bvc-pure-cs/comet/src/swig\_client\_api/ruby $ ruby -v  
ruby 1.8.7 (2008-06-20 patchlevel 22) [i686-linux]

Thanks

-John

---

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [December 2, 2008, 9:39am UTC](https://www.ruby-forum.com/t/memory-usage-with-blocks/154623/2 "2008-12-02T09:39:30Z")

</div>

Hi,

I think it’s the memory profiler I’m using:

```
       MemoryProfiler.start

```

Nevermind.

Does anyone know how to properly find memory leaks in a ruby app?

Thanks,

-John

---

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [December 2, 2008, 1:28pm UTC](https://www.ruby-forum.com/t/memory-usage-with-blocks/154623/3 "2008-12-02T13:28:49Z")

</div>

John Ky wrote:

> And make other similar changes. The program behaves exactly the same way,  
> but now uses 200MB less.

Consider the following:

def x(&block)  
block  
end

def a(&block)  
tmp = create\_a\_two\_hundred\_mega\_byte\_object()  
x {block.call} # Create a new block which closes over the current  
scope  
end

def b(&block)  
tmp = create\_a\_two\_hundred\_mega\_byte\_object()  
x(&block) # Reuse the block that has been passed to this method.  
# Do not create a new block  
end

If I call b {puts “hello”}, the following will happen:  
The block {puts “hello”} is created. This block holds a reference to any  
local  
variable that has been defined in the scope in which I call method b.  
Now method b is called with that block as an argument.  
Then a 200mb object is created and stored in tmp.  
Now x is called. x returns a Proc representing the block passed to b.  
The method b ends, tmp goes out of scope and the 200mb object is garbage  
collected.

If I call a {puts “hello”}, this happens:  
The block {puts “hello”} is created. This block holds a reference to any  
local  
variable that has been defined in the scope in which I call method a.  
Now method a is called with that block as an argument.  
Then a 200mb object is created and stored in tmp.  
Now another block is created, which invokes the block passed to a.  
This new block holds a reference to any local variable tmp defined in  
the  
method body of a. Specifically it holds a reference to tmp.  
Now x is called. x returns a Proc representing this new block.  
The method a ends, but the 200mb is still referenced by the Proc that’s  
returned from a. So as long as reference to that Proc is stored, the  
200mb  
object will not be garbage collected.

I don’t know whether that’s what happens in your code, but it’s  
certainly  
worth looking into.

HTH,  
Sebastian

---

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [December 3, 2008, 4:33am UTC](https://www.ruby-forum.com/t/memory-usage-with-blocks/154623/4 "2008-12-03T04:33:01Z")

</div>

Hi Sebastian,

Why doesn’t ruby detect that tmp isn’t used in the block and not keep a  
reference to it?

I found the offending code:

```
     def play_back(&block)
        $trace.method_block "PlaybackChain::play_back(&)" do
           sub_block = Proc.new do
              @tail.play_back do |root|
                 block.call(root)
              end
           end
           @block.call(sub_block)
        end
     end

     def play_back(&block)
        @heads.each do |head|
           selector.select_each do |selection|
              block.call(selection)
           end
        end
     end

```

Replacing those to methods with

```
     def play_back(&block)
        $trace.method_block "PlaybackChain::play_back(&)" do
           sub_block = Proc.new do
              @tail.play_back(&block)
           end
           @block.call(sub_block)
        end
     end

     def play_back(&block)
        @heads.each do |head|
           head.play_back(&block)
        end
     end

```

wiped over 100 MB off the memory usage.

Thanks for your help,

-John

On Tue, Dec 2, 2008 at 11:21 PM, Sebastian H. \<

---

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [December 3, 2008, 4:34am UTC](https://www.ruby-forum.com/t/memory-usage-with-blocks/154623/5 "2008-12-03T04:34:46Z")

</div>

Runs heaps faster too. Woosh!

---

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [December 3, 2008, 9:20am UTC](https://www.ruby-forum.com/t/memory-usage-with-blocks/154623/6 "2008-12-03T09:20:18Z")

</div>

John Ky wrote:

> Why doesn’t ruby detect that tmp isn’t used in the block and not keep a  
> reference to it?

Because tmp can still be accessed using the block even if it’s not used  
in the  
block directly:  
def foo()  
x = 5  
lambda {puts “Hello world”}  
end  
hello\_world\_block = foo  
eval(“x”, hello\_world\_block) #=\> 5

HTH,  
Sebastian
