Performance: Ruby vs Java

L

Lalit Pant

I'm a newcomer to Ruby, and thought I would write a little
brute-force-search program to see how Ruby compares to Java -
performance wise. The results surprised me (I was hoping Ruby would
fare a lot better than it did!). On my WinXP box (AthlonXP 1800+,
768Meg RAM), the Ruby program takes 1min 50secs to complete, while a
similar java program takes 0.6 secs.

Here are the programs:

Ruby (ruby 1.8.0 (2003-08-04) [i386-mswin32]):
def isPrime(n)
for i in 1..n-1 do
for j in 1..n-1 do
if i * j == n then
return false
end
end
end
return true
end

puts isPrime(2)
puts isPrime(4)
puts isPrime(7)
puts isPrime(25)
puts isPrime(400003)

Java (HotSpot(TM) Client VM (build 1.4.2_01-b06, mixed mode)):
public class Prime
{
public static void main(String[] args)
{
Prime p = new Prime();
System.out.println(p.isPrime(2));
System.out.println(p.isPrime(4));
System.out.println(p.isPrime(7));
System.out.println(p.isPrime(25));
System.out.println(p.isPrime(400003));
}

private boolean isPrime(int n)
{
for (int i = 1; i < n; i++)
{
for (int j = 1; j < n; j++)
{
if (i*j == n)
{
return false;
}
}
}
return true;
}
}

Kindly note that the isPrime() method above is not meant to be the
most efficient way of finding primes!

Any ideas on why i'm seeing such a big difference in performance?
 
T

Thomas Sondergaard

The difference is that ruby is interpreted and has a dynamic nature that
makes it difficult to optimize (or so I understand), while java is jitted
and for this single non-OO example it is probably as fast as C.

I can't resist the temptation of plugging my own project rubydotnet, which
allows you to implement such performance critical code in a .net language.

CS_SCRIPT = <<-EOF
int n = (int) args[0];
for (int i=0; i<n-1; ++i)
for (int j=0; j<n-1; ++j)
if (j*i == n)
return false;
return true;
EOF

def isPrime(n)
cs_eval(CS_SCRIPT, n)
end

puts isPrime(2)
puts isPrime(4)
puts isPrime(7)
puts isPrime(25)
puts isPrime(400003)

On my laptop (3ghz P4):
$ time ruby prime.rb
true
false
true
false
false

real 0m0.666s
user 0m0.015s
sys 0m0.000s

Neat, huh?

Cheers,

Thomas
 
H

Hal Fulton

Lalit said:
I'm a newcomer to Ruby, and thought I would write a little
brute-force-search program to see how Ruby compares to Java -
performance wise. The results surprised me (I was hoping Ruby would
fare a lot better than it did!). On my WinXP box (AthlonXP 1800+,
768Meg RAM), the Ruby program takes 1min 50secs to complete, while a
similar java program takes 0.6 secs.

[snip]

This *must* be a JIT issue, since the difference is so big.

I compared the Ruby version to the C version (below) and got
a comparable ratio. I bet you will, too.

Bottom line: Ruby is slower because it doesn't do any JIT.

Other factors might be the lack of bytecode compilation and
the startup time of the interpreter (though Java has that,
too).

Some JIT implementations are pretty good. I once had to do a
little demonstration to prove to my officemate that a program
(similar to this one) actually ran faster in Java than in C.
Of course, that's highly dependent on the compilers, the
nature of the code, your default optimizations, and the phase
of the moon.

Hal
 
T

Thomas Link

I'm a newcomer to Ruby, and thought I would write a little
brute-force-search program to see how Ruby compares to Java -
performance wise. The results surprised me (I was hoping Ruby would
fare a lot better than it did!). On my WinXP box (AthlonXP 1800+,
768Meg RAM), the Ruby program takes 1min 50secs to complete, while a
similar java program takes 0.6 secs.

Just a note/thought: I once implemented a similar program in several
programming languages. When it came to ruby, my conclusion was to rather
use "Narray" for code like this. Narray is a ruby extension written in
C, which makes it sufficiently fast. It requires a small modification to
the algorithm though.

Cheers,
Thomas.
 
L

Lothar Scholz

Hello Lalit,

Monday, September 22, 2003, 1:48:09 AM, you wrote:

LP> I'm a newcomer to Ruby, and thought I would write a little
LP> brute-force-search program to see how Ruby compares to Java -
LP> performance wise. The results surprised me (I was hoping Ruby would
LP> fare a lot better than it did!). On my WinXP box (AthlonXP 1800+,
LP> 768Meg RAM), the Ruby program takes 1min 50secs to complete, while a
LP> similar java program takes 0.6 secs.

Ruby is the wrong language for programs like this. A speed difference
of 18000% (or 180 times) is not unusual if you try to port algorithms on large data
sets with lots of low level calculations.

Writing parsers (that can't use regular expressions) or numerical
computing are the best visible sign that ruby is dynamic and untyped.

By the way. Common Lisp will not be much slower then Java, if used
with type declarations. There is a lot of possible optimizations, but
common lisp costs around 5000$ a license. I doubt that ruby has more
then a handfull of users who wants to pay this.
 
Y

Yvon Thoraval

Thomas Link said:
It requires a small modification to
the algorithm though.

He said "brute force"...
the algo, mathematically should stop at sqrt(n)...
 
L

Lalit Pant

Thanks a lot for the feedback, guys. I'll get on with the job of
learning/having fun with Ruby. Seems like a fascinating language...
 
D

Dave Brown

: On the other hand, Ruby, as I understand it, executes a program by
: walking over its parse tree, in the classic Gang-of-Four Interpreter
: pattern. Even compared to pure bytecode interpreters, tree-walking
: tends to be inefficient, especially for nested loops running over a
: large number of integers. (A bytecode interpreter is planned, but
: apparently still just a twinkle in Matz's eye.)

Isn't a Ruby bytecode interpreter kind of dependent on the Parrot
guys getting their bit done first?

--Dave
 
E

Eric Hodel

--HCdXmnRlPgeNBad2
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Isn't a Ruby bytecode interpreter kind of dependent on the Parrot
guys getting their bit done first?

No. Anyone can write a Ruby bytecode interpereter.

;) ;)

--=20
Eric Hodel - (e-mail address removed) - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04


--HCdXmnRlPgeNBad2
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (FreeBSD)

iD8DBQE/bz41MypVHHlsnwQRAvrwAJ9URkW7EotkG/QCB35KSiffxzGhFACgzBNd
Y4632ZMsIQj3clPStVYEcEs=
=EBJ0
-----END PGP SIGNATURE-----

--HCdXmnRlPgeNBad2--
 
H

Hal Fulton

Dave said:
: On the other hand, Ruby, as I understand it, executes a program by
: walking over its parse tree, in the classic Gang-of-Four Interpreter
: pattern. Even compared to pure bytecode interpreters, tree-walking
: tends to be inefficient, especially for nested loops running over a
: large number of integers. (A bytecode interpreter is planned, but
: apparently still just a twinkle in Matz's eye.)

Isn't a Ruby bytecode interpreter kind of dependent on the Parrot
guys getting their bit done first?

No, because Matz wants his own bytecode set. Generating Parrot
bytecodes is a separate issue.

Hal
 
A

Avi Bryant

Thomas Sondergaard said:
The difference is that ruby is interpreted and has a dynamic nature that
makes it difficult to optimize (or so I understand), while java is jitted
and for this single non-OO example it is probably as fast as C.

I've said this before, and I think it's important to say it again: the
performance difference between Java and Ruby has *everything* to do
with the JIT and *nothing* to do with Ruby's "dynamic nature", or the
fact that Java is statically typed.

This is easy to demonstrate with Smalltalk, an equally dynamic
language that has JITted implementations. My point here isn't to plug
Smalltalk (who, me?), but to drive home my point about JIT compilation
vs. static typing.

On my machine (Athlon 1400), Ruby takes 121.969s to try that algorithm
on 400003. VisualWorks Smalltalk takes 2.158 seconds. That's a 60x
speedup, without any ugly primitive types or type declarations.

Of course, a good interpeter can help a lot too. Squeak Smalltalk,
which is a straight bytecode interpreter with no JIT, manages it in
16.147s - still almost an order of magnitude faster than Ruby.

By the way, the code I used in Smalltalk was

Integer>>isPrime
1 to: self - 1 do:
[:i |
1 to: self - 1 do:
[:j |
i*j = self ifTrue: [^ false]]].
^ true

Although this is idiomatic Smalltalk (in the same way that the Java
code presented was idiomatic Java), we can actually make it closer to
the Ruby version by creating range objects and iterating over them:

Integer>>isPrime
(1 to: self - 1) do:
[:i |
(1 to: self - 1) do:
[:j |
i*j = self ifTrue: [^ false]]].
^ true

In both Squeak and VisualWorks this roughly doubles the times.
 
P

Phil Tomson

The difference is that ruby is interpreted and has a dynamic nature that
makes it difficult to optimize (or so I understand), while java is jitted
and for this single non-OO example it is probably as fast as C.

I can't resist the temptation of plugging my own project rubydotnet, which
allows you to implement such performance critical code in a .net language.

CS_SCRIPT = <<-EOF
int n = (int) args[0];
for (int i=0; i<n-1; ++i)
for (int j=0; j<n-1; ++j)
if (j*i == n)
return false;
return true;
EOF

def isPrime(n)
cs_eval(CS_SCRIPT, n)
end

puts isPrime(2)
puts isPrime(4)
puts isPrime(7)
puts isPrime(25)
puts isPrime(400003)

On my laptop (3ghz P4):
$ time ruby prime.rb
true
false
true
false
false

real 0m0.666s
user 0m0.015s
sys 0m0.000s

Or, for those of us not on a .NET platform (Windows) or those of us who
are wary of it...

You could do something very similar using Ryan Davis' RubyInline package.

http://sourceforge.net/projects/rubyinline/

Phil
 
P

Phil Tomson

Hello Lalit,

Monday, September 22, 2003, 1:48:09 AM, you wrote:

LP> I'm a newcomer to Ruby, and thought I would write a little
LP> brute-force-search program to see how Ruby compares to Java -
LP> performance wise. The results surprised me (I was hoping Ruby would
LP> fare a lot better than it did!). On my WinXP box (AthlonXP 1800+,
LP> 768Meg RAM), the Ruby program takes 1min 50secs to complete, while a
LP> similar java program takes 0.6 secs.

Ruby is the wrong language for programs like this. A speed difference
of 18000% (or 180 times) is not unusual if you try to port algorithms on
large data
sets with lots of low level calculations.

But that doesn't mean you can't use Ruby on the project... How much code
is really speed critical? It's going to vary depending on what
type of project you're doing, but in most cases it's probably 10% or less.

Since it's easy to extend Ruby with C/C++ code, Ruby can still be a very
good choice for a project which requires high performance in some areas of
the code. Tools like swig (http://www.swig.org), rubyinline
(http://sourceforge.net/projects/rubyinline/), and cgenerator
(http://redshift.sourceforge.net/cgen/) make it even easier to create
C/C++ extensions for code that is performance sensitive.

Phil
 
J

Jason Creighton

By the way. Common Lisp will not be much slower then Java, if used
with type declarations. There is a lot of possible optimizations, but
common lisp costs around 5000$ a license. I doubt that ruby has more
then a handfull of users who wants to pay this.

Huh?

Perhaps there's an implementation of Common Lisp that costs $5000 a
license, but there's several free (as in speech) implementations
availible. I'm just playing around with CL, so I don't know which one is
the "best" but the one I'm using to toy around with CL is CMUCL. (Sorry,
I don't have a URL. Google for it.)

Jason Creighton
 
R

Robert Klemme

Lothar Scholz said:
By the way. Common Lisp will not be much slower then Java, if used
with type declarations. There is a lot of possible optimizations, but
common lisp costs around 5000$ a license. I doubt that ruby has more
then a handfull of users who wants to pay this.

Lisp can even be faster than Java:
http://www.flownet.com/gat/papers/lisp-java.pdf

The article about the original study - if you're an ACM member
http://portal.acm.org/citation.cfm?id=317683&coll=portal&dl=ACM&CFID=12344240&CFTOKEN=52361301

Regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top