[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Ruby is a slow performer

Sergei Gnezdov

10/9/2004 8:42:00 AM

Hi,

I just found an interesting benchmark site. I am sure many of you know
about it :)

http://shootout.alioth.d...

Ruby is one of the slowest performers among compared languages.
Are there any plans to get better?


Thank you
24 Answers

gabriele renzi

10/9/2004 8:57:00 AM

0

Sergei Gnezdov ha scritto:

> Hi,
>
> I just found an interesting benchmark site. I am sure many of you know
> about it :)
>
> http://shootout.alioth.d...
>
> Ruby is one of the slowest performers among compared languages.
> Are there any plans to get better?

I guess there are :)
The latest message about YARV that plans to make ruby from 50% to >300%
faster (warning benchmarks are 80% made of..) not to mention the
rubydium JIT.
So let's join koichi and alexander hacking on them ASAP :)


About the shootout. Most of the stuff is plan useless in ruby.
You won't implemente heapsort in ruby, cause you have sort/sort_by.
Nor you would use
http://shootout.alioth.d...lang/ruby/random.ruby.html
because you have rand().
(note that this gen_random algorithm is applied in other places slowing
down even those)

Basically remeber that ruby is 'fast enough' for most things, useless
for others. You can't have everything I guess :)


PS
Anyway, stuff from that shootout is wildly unidiomatic, just look at
http://shootout.alioth.d...lang/ruby/lists.ruby.html

I remember sending a message to them but getting no feedback. Maybe I
should try again.

ptkwt

10/9/2004 6:21:00 PM

0

In article <1097311171.Cz/0lZE0M9/toShS+N4TCA@teranews>,
Sergei Gnezdov <nobody@noresponse.net> wrote:
>Hi,
>
>I just found an interesting benchmark site. I am sure many of you know
>about it :)
>
> http://shootout.alioth.d...
>
>Ruby is one of the slowest performers among compared languages.
>Are there any plans to get better?
>

Rite (Ruby 2.0) is planned to use a VM. Perhaps YARV or maybe another.

Also, Ruby is generally 'fast enough' for most tasks. For things where
you need more speed it's quite easy to write a C extension either
directly using the Ruby C API (quite easy really) or by using RubyInline
or CGenerator. Often you only need to speed up a few methods in your
whole application by writing them in C.

Phil

Fritz Heinrichmeyer

10/12/2004 6:42:00 AM

0

Sergei Gnezdov wrote:
> Hi,
>
> I just found an interesting benchmark site. I am sure many of you know
> about it :)
>
> http://shootout.alioth.d...
>
> Ruby is one of the slowest performers among compared languages.
> Are there any plans to get better?
>
>
> Thank you

simply set the lines of code multiplier to 1 and all others to 0 and
recalculate. There ruby shines :-) together with haskell, ocaml and pike
(!?).

--
Mit freundlichen Gruessen
Fritz Heinrichmeyer FernUniversitaet, LG ES, 58084 Hagen (Germany)
tel:+49 2331/987-1166 fax:987-355

Christian Szegedy

11/5/2004 9:22:00 PM

0

gabriele renzi wrote:

> About the shootout. Most of the stuff is plan useless in ruby.
> You won't implemente heapsort in ruby, cause you have sort/sort_by.
> Nor you would use
> http://shootout.alioth.debian.org/lang/ruby/random...
> because you have rand().

You are correct. I would say that the shootout is extremely
misleading, for example the Python people do dubious tricks
to make it look fast: for example the matrix multiplication is
implemented by calling the an extension method.

> Basically remeber that ruby is 'fast enough' for most things, useless
> for others. You can't have everything I guess :)

I find Ocaml very approporiate for almost all tasks ;)
Only for very short scripts (up to 100 lines) has Ruby
a clear competitive edge.

David G. Andersen

11/5/2004 9:32:00 PM

0

On Sat, Nov 06, 2004 at 06:23:41AM +0900, Christian Szegedy scribed:
> gabriele renzi wrote:
>
> >About the shootout. Most of the stuff is plan useless in ruby.
> >You won't implemente heapsort in ruby, cause you have sort/sort_by.
> >Nor you would use
> >http://shootout.alioth.debian.org/lang/ruby/random...
> >because you have rand().
>
> You are correct. I would say that the shootout is extremely
> misleading, for example the Python people do dubious tricks
> to make it look fast: for example the matrix multiplication is
> implemented by calling the an extension method.

Why is that unrealistic? You could do the same in Ruby by
implementing the library 'Matrix' class in C. We already have
a library that handles the stuff; it's just a matter of
optimization (== time == extra code in C that's harder to
maintain, unfortunately). I actually played with this a bit.
Right now, using the Ruby matrix class does two things to
that test:

a) Reduces the lines of code by nearly half
b) Increases the runtime by a factor of two. (ouch)

If we had a superfast matrix class, it would give (a) along
with decreasing the runtime by a factor of ten or so. Sounds
reasonable. The same test in matlab would be about 1/4 the lines of
code and 20x faster if implemented the way it should be.

Admittedly, most people would probably use external hooks
to lapack for serious matrix manipulation, but who's counting?
There's something to be said, in all honesty, for fast built-in
library support.

The shootout _is_ useful for understanding some general
aspects of the languages, and for looking for things that
you might want to really work on speeding up (say, for
instance, the fact that Ruby's hash accesses seem to be
about 1/2 the speed of Perl's. ;-)

-Dave

--
work: dga@lcs.mit.edu me: dga@pobox.com
MIT Laboratory for Computer Science http://www....


Michael Neumann

11/5/2004 10:00:00 PM

0

On Sat, Nov 06, 2004 at 06:31:33AM +0900, David G. Andersen wrote:
> On Sat, Nov 06, 2004 at 06:23:41AM +0900, Christian Szegedy scribed:
> > gabriele renzi wrote:
> >
> > >About the shootout. Most of the stuff is plan useless in ruby.
> > >You won't implemente heapsort in ruby, cause you have sort/sort_by.
> > >Nor you would use
> > >http://shootout.alioth.debian.org/lang/ruby/random...
> > >because you have rand().
> >
> > You are correct. I would say that the shootout is extremely
> > misleading, for example the Python people do dubious tricks
> > to make it look fast: for example the matrix multiplication is
> > implemented by calling the an extension method.
>
> Why is that unrealistic? You could do the same in Ruby by
> implementing the library 'Matrix' class in C. We already have
> a library that handles the stuff; it's just a matter of
> optimization (== time == extra code in C that's harder to
> maintain, unfortunately). I actually played with this a bit.
> Right now, using the Ruby matrix class does two things to
> that test:
>
> a) Reduces the lines of code by nearly half
> b) Increases the runtime by a factor of two. (ouch)
>
> If we had a superfast matrix class, it would give (a) along
> with decreasing the runtime by a factor of ten or so. Sounds

We have a superfast matrix class: NArray (not in standard lib).
It claimed to be 3x faster than NumPy for some tests and a bit faster
than Octave for for matrix operations.

http://www.ir.isas.ac.jp/~masa/ruby/in...

Regards,

Michael


ptkwt

11/5/2004 10:51:00 PM

0

In article <20041105220018.GA5484@miya.intranet.ntecs.de>,
Michael Neumann <mneumann@ntecs.de> wrote:
>On Sat, Nov 06, 2004 at 06:31:33AM +0900, David G. Andersen wrote:
>> On Sat, Nov 06, 2004 at 06:23:41AM +0900, Christian Szegedy scribed:
>> > gabriele renzi wrote:
>> >
>> > >About the shootout. Most of the stuff is plan useless in ruby.
>> > >You won't implemente heapsort in ruby, cause you have sort/sort_by.
>> > >Nor you would use
>> > >http://shootout.alioth.debian.org/lang/ruby/random...
>> > >because you have rand().
>> >
>> > You are correct. I would say that the shootout is extremely
>> > misleading, for example the Python people do dubious tricks
>> > to make it look fast: for example the matrix multiplication is
>> > implemented by calling the an extension method.
>>
>> Why is that unrealistic? You could do the same in Ruby by
>> implementing the library 'Matrix' class in C. We already have
>> a library that handles the stuff; it's just a matter of
>> optimization (== time == extra code in C that's harder to
>> maintain, unfortunately). I actually played with this a bit.
>> Right now, using the Ruby matrix class does two things to
>> that test:
>>
>> a) Reduces the lines of code by nearly half
>> b) Increases the runtime by a factor of two. (ouch)
>>
>> If we had a superfast matrix class, it would give (a) along
>> with decreasing the runtime by a factor of ten or so. Sounds
>
>We have a superfast matrix class: NArray (not in standard lib).
>It claimed to be 3x faster than NumPy for some tests and a bit faster
>than Octave for for matrix operations.
>
>http://www.ir.isas.ac.jp/~masa/ruby/in...
>

Is the Python extension in question part of Python's standard lib? If so,
I could see how using it in the shootout would be OK. Perhaps it's time
to nominate NArray for inclusion in Ruby's standard lib. Given that
matrix operations are one of the more compute intensive tasks it might be
a good idea.

....Also, I wonder if NArray might be in need of renaming. maybe something
like FastArray/FastMatrix/FastVector - that would make the purpose perhaps
a bit clearer. I find that I always forget about NArray when I need a
fast matrix (which isn't often, but sometimes).

Phil

David G. Andersen

11/6/2004 12:07:00 AM

0

On Sat, Nov 06, 2004 at 07:00:23AM +0900, Michael Neumann scribed:
> >
> > If we had a superfast matrix class, it would give (a) along
> > with decreasing the runtime by a factor of ten or so. Sounds
>
> We have a superfast matrix class: NArray (not in standard lib).
> It claimed to be 3x faster than NumPy for some tests and a bit faster
> than Octave for for matrix operations.
>
> http://www.ir.isas.ac.jp/~masa/ruby/in...

This looks great, btw. Not having looked at the code
size, I don't know if it's worth having it replace the library
version of 'Matrix' or not. If we actually just want some
quick speedups to our current matrix class, I offer the
following bit of code that performs most of the matrix multiplication
in C. It could be faster if it assumed anything about the contents
of the matrix; as it is, it's pretty much a straightforward
translation of the current matrix code into C. It speeds matrix
multiplication up by about an order of magnitude. Division is
implemented as multiplication by the inverse, so it's also accelerated
somewhat.

The code is attached at the end of this message. It should probably
be extended with a few more sanity checks by someone who knows what
they're doing. I haven't tested it extensively. I mostly wrote
it to see how well it would work to just make a minor tweak with a
little bit of C code, while preserving the majority of the 1,200
lines of ruby. The answer seems to be "pretty well!"

It takes 100 iterations of the computer shootout matrix
test from 7.5 seconds (their version) / 13 seconds (ruby 'matrix')
down to about 1.3 seconds. The perl version takes 3.4 seconds.
The modified python version takes under .2 seconds, in comparison,
as would a Ruby version using NArray...

The happy part about this is that it's all of 103 lines of
C, since all of the wrapper code for matrix handling is still done
in ruby. To use it, modify matrix.rb to include fastmath after
the class definition, and dispatch to the mult version instead.
Bonus points if you want to make it depend on having fastmath
installed; should be easy. :)

***************
*** 107,112 ****
--- 107,113 ----
class Matrix
@RCS_ID='-$Id: matrix.rb,v 1.11 1999/10/06 11:01:53 keiju Exp keiju $-'

+ require 'fastmath'
# extend Exception2MessageMapper
include ExceptionForMatrix

***************
*** 465,470 ****
--- 466,472 ----
return r.column(0)
when Matrix
Matrix.Raise ErrDimensionMismatch if column_size != m.row_size
+ return Matrix[ *self.mult(m) ]

rows = (0 .. row_size - 1).collect {
|i|

-Dave

=========== ext/matrix/fastmath/extconf.rb =======
require 'mkmf'
create_makefile 'matrix/fastmath'

=========== ext/matrix/fastmath/fastmath.c =======

/*
fastmath.c -- matrix manipulation core

Copyright (c) 2004 David Andersen <dga@pobox.com>

This library is free software.
You can distribute/modify this program under the same terms of ruby.
(I hereby assign copyright to matz if he wants it).

*/

#include "ruby.h"
#include <stdio.h>


VALUE matclass; /* Set in Init */
static int id_length;
static int id_plus;
static int id_mul;

#define FASTMATH_VERSION "0.0.1"

/*
=begin
= Fastmath methods.
= end
*/

/*
=begin
--- mult
Multiplies two matrices. Returns an array that must be
coerced back into a matrix by the caller.
=end
*/

static VALUE
fastmath_mult(VALUE self, VALUE other)
{
VALUE a, b, c, item, tmp, val, row, m1i, at, bt;
int arows, acols;
int brows, bcols;
int crows, ccols;
int i, j, k;
/* Note: Might be better to call to_a .. this is not speed critical */
a = rb_iv_get(self, "@rows");
b = rb_iv_get(other, "@rows");
if (rb_obj_is_instance_of(other, matclass) != Qtrue) {
rb_raise(rb_eTypeError, "type of arg must be Matrix");
return self;
}
tmp = rb_funcall(a, id_length, 0);
arows = NUM2INT(tmp);
tmp = rb_funcall(b, id_length, 0);
brows = NUM2INT(tmp);
if (!arows || !brows) return self;

item = rb_ary_entry(a, 0);
if (NIL_P(item) || TYPE(item) != T_ARRAY) {
raise(rb_eIndexError, "Invalid self matrix");
return self;
}
tmp = rb_funcall(item, id_length, 0);
acols = NUM2INT(tmp);

item = rb_ary_entry(b, 0);
if (NIL_P(item) || TYPE(item) != T_ARRAY) {
raise(rb_eIndexError, "Invalid self matrix");
return self;
}
tmp = rb_funcall(item, id_length, 0);
bcols = NUM2INT(tmp);

crows = arows;
ccols = bcols;

c = rb_ary_new2(crows);
for (i = 0; i < crows; i++) {
row = rb_ary_new2(ccols);
m1i = rb_ary_entry(a, i);
for (j = 0; j < ccols; j++) {
val = INT2FIX(0);
for (k = 0; k < ccols; k++) {
at = rb_ary_entry(m1i, k);
bt = rb_ary_entry(rb_ary_entry(b, k), j);
val = rb_funcall(val, id_plus, 1,
rb_funcall(at, id_mul, 1, bt));
}
rb_ary_store(row, j, val);
}
rb_ary_store(c, i, row);
}

return c; /* remember to coerce to matrix in caller */
}

void
Init_fastmath()
{
matclass = rb_const_get(rb_cObject, rb_intern("Matrix"));
rb_define_method(matclass, "mult", fastmath_mult, 1);
id_length = rb_intern("length");
id_plus = rb_intern("+");
id_mul = rb_intern("*");
}


David G. Andersen

11/6/2004 1:26:00 AM

0

On Sat, Nov 06, 2004 at 09:06:38AM +0900, David G. Andersen scribed:

> I offer the following bit of code that performs most of the matrix
> multiplication in C.

> The code is attached at the end of this message. It should probably
> be extended with a few more sanity checks by someone who knows what
> they're doing. I haven't tested it extensively. I mostly wrote
> [...]

I've added the requisite sanity checks to the code and
converted it to directly access the array elements. It's about
10% faster, a bit more readable, and decidedly safer. :). As
before, it preserves the semantics of matrix.rb, so it should
be drop-in compatible.

(Sorry for the 100 line email)

-Dave

/*
fastmath.c -- matrix manipulation core

Copyright (c) 2004 David Andersen <dga@pobox.com>

This library is free software.
You can distribute/modify this program under the same terms of ruby.
*/

#include "ruby.h"
#include <stdio.h>

VALUE matclass; /* Set in Init */
static int id_length, id_plus, id_mul;

#define FASTMATH_VERSION "0.0.1"

/*
=begin
= Fastmath methods.
= end
*/

/*
=begin
--- mult
Multiplies two matrices
=end
*/

static VALUE
fastmath_mult(VALUE self, VALUE other)
{
VALUE a, b, c, val, row, m1i, at, bt;
int arows, brows, bcols, i, j, k;

if (rb_obj_is_instance_of(other, matclass) != Qtrue) {
rb_raise(rb_eTypeError, "type of arg must be Matrix");
}

a = rb_iv_get(self, "@rows");
b = rb_iv_get(other, "@rows");
if (NIL_P(a) || NIL_P(b) || TYPE(a) != T_ARRAY || TYPE(b) != T_ARRAY) {
rb_raise(rb_eTypeError, "invalid matrix arguments");
}
arows = RARRAY(a)->len;
brows = RARRAY(b)->len;
if (!arows || !brows) {
rb_raise(rb_eIndexError, "Zero-length matrix");
}

row = RARRAY(b)->ptr[0];
if (NIL_P(row) || TYPE(row) != T_ARRAY) {
rb_raise(rb_eIndexError, "Invalid other matrix");
}
bcols = RARRAY(row)->len;

for (i = 0; i < brows; i++) {
row = RARRAY(b)->ptr[i];
if (TYPE(row) != T_ARRAY || RARRAY(row)->len != arows) {
rb_raise(rb_eIndexError, "Invalid other row");
}
}

c = rb_ary_new2(arows);
for (i = 0; i < arows; i++) {
row = rb_ary_new2(bcols);
m1i = RARRAY(a)->ptr[i];
if (TYPE(m1i) != T_ARRAY || RARRAY(m1i)->len != brows) {
rb_raise(rb_eIndexError, "Invalid self row len");
}
for (j = 0; j < bcols; j++) {
val = INT2FIX(0);
for (k = 0; k < bcols; k++) {
at = RARRAY(m1i)->ptr[k];
bt = RARRAY(RARRAY(b)->ptr[k])->ptr[j];
val = rb_funcall(val, id_plus, 1,
rb_funcall(at, id_mul, 1, bt));
}
RARRAY(row)->ptr[j] = val;
}
RARRAY(row)->len = bcols;
rb_ary_store(c, i, row);
}

if (OBJ_TAINTED(self) || OBJ_TAINTED(other)) OBJ_TAINT(c);
return c; /* remember to coerce to matrix in caller */
}

void
Init_fastmath()
{
matclass = rb_const_get(rb_cObject, rb_intern("Matrix"));
rb_define_method(matclass, "mult", fastmath_mult, 1);
id_length = rb_intern("length");
id_plus = rb_intern("+");
id_mul = rb_intern("*");
}


bazad

11/6/2004 2:52:00 AM

0

Christian Szegedy <szegedy@t-online.de> writes:

> gabriele renzi wrote:
>
> > About the shootout. Most of the stuff is plan useless in ruby.
[snip]
>
> I find Ocaml very approporiate for almost all tasks ;)
> Only for very short scripts (up to 100 lines) has Ruby
> a clear competitive edge.

I was supprised to learn about existence of Ocaml. I just don't know
how valuable (in all possible meanings) it is.