[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Performance: Ruby vs Java

lalit_pant

9/22/2003 12:48:00 AM

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?
17 Answers

Thomas Sondergaard

9/22/2003 1:30:00 AM

0

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

"Lalit Pant" <lalit_pant@yahoo.com> wrote in message
news:f260fa27.0309211647.3bb8bc95@posting.google.com...
> 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?


Hal E. Fulton

9/22/2003 1:51:00 AM

0

Lalit Pant wrote:
> 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


Frank Mitchell

9/22/2003 1:54:00 AM

0

Lalit Pant wrote:
>
> 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.

[programs snipped]

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

File this explanation under "duh", but an obvious big reason for the
difference would be the difference in runtimes. Java''s HotSpot (at some
point) compiles Java bytecodes into native code, so at some point your
Java program will be compiled to the equivalent of a C program.

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.)

For raw number-crunching, you probably wouldn''t want to use Ruby (or
Python, or Perl, or Tcl). Ruby and similar languages *can* match Java
speeds in other tasks, notably when the script spends most of its time
using builtin objects implemented in C.

You may be interested in a comparison of C, C++, Java, Perl, Python,
Rexx, and Tcl:
<http://wwwipd.ira.uka.de/~prechelt/Biblio/jccpprt_computer20...
Obviously it doesn''t refer directly to Ruby, but many observations from
the latter four languages apply to Ruby.

--
Frank Mitchell (frankm each bayarea period net)

Please avoid sending me Word or PowerPoint attachments.
See http://www.fsf.org/philosophy/no-word-attach...

Frank Mitchell

9/22/2003 3:24:00 AM

0

BTW, just for comparison I translated your program into Python and Lua.
(See www.python.org and www.lua.org, respectively.) Both languages
compile their scripts into bytecodes before running them.

On my pathetic 166 MHz laptop running Linux, calculating whether 400003
was prime took too long, so I knocked out a couple of zeroes. These are
the timings I ended up with:

prime.lua: 0:57.96 # Lua 5.0
prime.py: 3:23.01 # Python 2.2.2
prime.rb: 4:50.35 # Ruby 1.8.0
Prime.java 0:08.01 # Kaffe 1.0.7, JIT enabled

So, even with Kaffe, the JIT makes one or two orders of magnitude
difference. (The Lua number shows what a small and ultra-optimized
interpreter could do.)

Attached are the Python and Lua translations.

--
Frank Mitchell (frankm each bayarea period net)

Please avoid sending me Word or PowerPoint attachments.
See http://www.fsf.org/philosophy/no-word-attachm...!/usr/bin/env python

def is_prime(n):
for i in range(1, n):
for j in range(1, n):
if i * j == n:
return 0
return 1

print is_prime(2)
print is_prime(4)
print is_prime(7)
print is_prime(25)
print is_prime(4003)
# print is_prime(400003)
#!/usr/bin/env lua

function is_prime(n)
for i = 1, (n-1) do
for j = 1, (n-1) do
if (i * j) == n then
return nil
end
end
end
return 1
end

print(is_prime(2))
print(is_prime(4))
print(is_prime(7))
print(is_prime(25))
print(is_prime(4003))
-- print(is_prime(400003))

Frank Mitchell

9/22/2003 4:03:00 AM

0

(I just can''t let this go ...)

Frank Mitchell wrote:
> (The Lua number shows what a small and ultra-optimized
> interpreter could do.)

Immediately after posting, I realized the Lua instruction

for i = a,b do ... end

is specifically for iterating over numbers from a to b. Ruby and Python
only iterate over sequences of object instances (including integers),
created lazily. That may explain part of the 3-5x speed difference.

--
Frank Mitchell (frankm each bayarea period net)

Please avoid sending me Word or PowerPoint attachments.
See http://www.fsf.org/philosophy/no-word-attach...

Thomas Link

9/22/2003 9:52:00 AM

0

> 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.

Lothar Scholz

9/22/2003 10:34:00 AM

0

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.


--
Best regards,
Lothar mailto:mailinglists@scriptolutions.com


yvon.thoravallist

9/22/2003 10:44:00 AM

0

Thomas Link <samul@web.de> wrote:

> It requires a small modification to
> the algorithm though.

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

lalit_pant

9/22/2003 1:36:00 PM

0

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...

dagbrown

9/22/2003 5:39:00 PM

0

In article <3F6E5631.F7C124A8@bayFNORDarea.net>,
Frank Mitchell <frankm@bayFNORDarea.net> wrote:
: 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