This is a story of that time I banged my head against the table.
I was writing a procedure for finding out the number of times the method String#size was called during the runtime of a snippet. When the snippet was run using Rubinius, it resulted in a count of n+1 where n was the result under MRI (both 2.0). After fiddling with the code for a bit, I realized that the “require” call in Rubinius internally calls the method String#size. I forgot that much of Rubinius is written in Ruby.
Run 1
The following is a simpler version of the call counter I implemented.
The snippet I wanted to measure was in another file and the above counter.rb
file was required in the snippet file:
When the file is run using ruby snippet.rb
, it results in the following output:
Note that the snippet has nothing to do with threading-related errors.
After some digging around and blaming the interpolation (#{}
) literal initially, I later realized I was wrong. I added some print statements here and there and realized that the @counter
was getting incremented right before the (1..100000).each {}
block.
Run 2
Instead of including the counter.rb
file, I copied the contents and pasted them into snippet.rb
and removed the require
clause. Boom!
Just as it should be.
Are we there yet?
I did see a call to #size
method in the puts
method and to test the effect of that call, I added another call to puts
inside the at_exit{}
block like so:
Output:
(Rubinius)
(MRI)
In Rubinius, IO#puts
has a call to the String#suffix?
method which has a call to String#size
and so, our counter is incremented after the first puts
call. Refer to Rubinius to the IO and String classes.
So, what’s the point?
I always wondered why tools like ruby-prof
or rblineprof
were unavailable for Ruby implementations other than MRI and how difficult it would be to port those to other implementations. Now I guess the above behaviour can be cited as one reason. I now realize that performance monitoring applications are not at all straight-forward and that these kinds of subtleties should be kept in mind.
Also, this is fun.