# Trivia Question and a Free Book

I’d like to share a fun little JRuby trivia question, and I’ll give a
free copy of my new book, “Deploying with JRuby”, to the first person

So here’s the question:

I have the following program, which calculates fibonacci numbers:

puts Benchmark.measure { fibonacci(30) }
puts Benchmark.measure { fibonacci(30) }

When I run it on MRI, everything seems normal. But when I run it on
JRuby I get the following output:

0.329000 0.000000 0.329000 ( 0.273000)
0.084000 0.000000 0.084000 ( 0.085000)

Why is the second run of fibonacci numbers dramatically faster than the
first?

Hi Joe,

Is it because we’re seeing the JVM warming up and optimizing the byte
code? Or are you looking for something more specific?

Denny

On Mar 9, 2012, at 9:09 AM, Joe K. wrote:

I’d like to share a fun little JRuby trivia question, and I’ll give a
free copy of my new book, “Deploying with JRuby”, to the first person

So here’s the question:

I have the following program, which calculates fibonacci numbers:

require ‘benchmark’

def fibonacci(n)
if n < 2
n
else
fibonacci(n - 2) + fibonacci(n - 1)
end
end

puts Benchmark.measure { fibonacci(30) }
puts Benchmark.measure { fibonacci(30) }

When I run it on MRI, everything seems normal. But when I run it on
JRuby I get the following output:

0.329000 0.000000 0.329000 ( 0.273000)
0.084000 0.000000 0.084000 ( 0.085000)

Why is the second run of fibonacci numbers dramatically faster than the
first?

I thought it was the JIT, but disabling that still gives a
speedup:

~:\$ jruby -Xcompile.mode=OFF fib.jruby.rb
0.642000 0.000000 0.642000 ( 0.580000)
0.387000 0.000000 0.387000 ( 0.386000)

But I’m sure there are enough regulars here who can give
better guesses than me

I’m going to give the free book to Dennis, since the JVM is indeed
warming up and optimizing things at runtime. Dennis, I’ll send you some
details in a separate email.

I think Charlie’s (slightly old) blog post describes why you still see
some speed up with compile mode off (thanks for pointing that out Dick):

Thanks for playing!

get a Rails app running on JRuby and Trinidad:

-joe

On Mar 10, 2012, at 10:14 AM, Joe K. wrote:

I’m going to give the free book to Dennis, since the JVM is indeed warming up
and optimizing things at runtime. Dennis, I’ll send you some details in a
separate email.

If I run your original I get.

Mac-User:~ mjh\$ jruby fib.rb
0.630000 0.000000 0.630000 ( 0.256000)
0.134000 0.000000 0.134000 ( 0.134000)

Clearly showing a much slower first run.

I change it to…

require ‘benchmark’

x = 1
x = x + 1

def fibonacci(n)
if n < 2
n
else
fibonacci(n - 2) + fibonacci(n - 1)
end
end

puts Benchmark.measure { fibonacci(30) }
puts Benchmark.measure { fibonacci(30) }

Thinking maybe the minor changes at the start of the script will absorb
the initial ‘warming up’ hit and the lag will disappear from the
benchmark numbers.
I then get…
Mac-User:~ mjh\$ jruby fib.rb
0.290000 0.000000 0.290000 ( 0.245000)
0.137000 0.000000 0.137000 ( 0.137000)
Mac-User:~ mjh\$ jruby fib.rb
0.390000 0.000000 0.390000 ( 0.344000)
0.137000 0.000000 0.137000 ( 0.137000)

Maybe no longer ‘much’ slower but still the first run is still some
slower.

These runs are all pretty short, so there’s going to be a lot of

In general, you’ll see two bumps: one from JRuby and one from the JVM.
If you’re running JRuby in interpreted mode, you’ll only see the JVM
bump.

Your couple lines at the top may do a tiny bit of warmup for the
interpreter (in interpreted mode) and the + operation, but probably
not enough to really be noticeable. More likely is that your runs of
cached, so there’s a little less lag in getting going.

The usual recommendation when benchmarking straight-line performance
is to run things to a steady state and then throw out the early
results, since they’ll reflect filesystem caching, CPU ramping up
speed (on systems where it might throttle to save power),
startup-time, and early JIT and GC overhead.

Don’t worry too much about the first number

• Charlie

On Mar 10, 2012, at 2:12 PM, Charles Oliver N. wrote:

Don’t worry too much about the first number

Later runs within the same jvm instance can run into later gc concerns
though skewing benchmark runs?

More likely is that your runs of