Ruby is too slow

Hello Aleksei,

Thursday, November 21, 2002, 10:34:36 AM, you wrote:

Ruby has a perfect mechanism of binding native machine code.
It’s AG> very easy and I prefere using it for such tasks.
Extending process is described in the readme file shipped with the
Ruby itself.

i think you say about smth like Inline::C module

···


Best regards,
Bulat mailto:bulatz@integ.ru

“Bulat Ziganshin” bulatz@integ.ru wrote in message news:36275642663.20021121125533@integ.ru

Hello Peter,

Thursday, November 21, 2002, 12:31:04 PM, you wrote:

it is because ruby interpreted language, while java and c++ are
compiled to machine code. this sort of tasks definitely not for
ruby

Java compiles to byte code that is then interpreted.

… or compiled using JIT. based on timings in original post, i think,
his code is compiled

The Jave code was compiled using Sun JDK 1.4 for Win32, which uses
their hotspot technology. I think that is just their latest name for
JIT.
I didn’t test timings, but the C++/Java comparisons I did were not
exactly fair. I knew the C++ could compile more efficiently. At
least
without clever optimization.
C++, *imageIt = lookup[*imageIt]; imageIt++
Java, image[i] = lookup[image[i]]; i++;

I also recognize that Ruby is interpreted. However, I did not expect
the
factor of 200 difference. The interpreter only needs to parse the
loop
once, it should then have byte code to execute for each iteration. Of
course,
it must translate the byte code to machine code, for execution. I
would have expected some constant overhead for this translation on the
order of 2 or 3 times. This is a very tight loop though and every
extra op makes a significant difference.

I knew Ruby was not up for my current task. That is why it is being
written in C++. I was just curious at close it could come. I was
really blown away, by exactly how inadequate it is at such things.

However, Ruby blocks are really nice. I have been trying to make my
C++ do the same thing and I just end up with this mess.

template
void map(FuncData &data, T &v)
{
v = data.lookup[v];
}

template
void for_each_pixel(ImageData &id, FuncData &fd, void
(*func)(FuncDataOnly &fdo, T &v) )
{
T *imageIt = id.image;
T *pLast = imageIt + id.imageSize;
while (imageIt != pLast)
{
(*func)(fd, *imageIt);
imageIt++;
}
}

Hello Isak,

Friday, November 22, 2002, 1:05:47 PM, you wrote:

I’ve read that using the Array’s at function is faster than
operator because it doesn’t support ranges.

in this situation it’s like giving a banana to man who don’t eat for
30 days :slight_smile:

···


Best regards,
Bulat mailto:bulatz@integ.ru

“Bulat Ziganshin” bulatz@integ.ru wrote in message
news:53267683037.20021121104254@integ.ru

Hello Aleksei,

Thursday, November 21, 2002, 10:34:36 AM, you wrote:

Ruby has a perfect mechanism of binding native machine code.
It’s AG> very easy and I prefere using it for such tasks.
Extending process is described in the readme file shipped with the
Ruby itself.

i think you say about smth like Inline::C module

no inline::C.

Usually I create my own module having methods and Classes written in C
and/or assembler language.

···


Best regards,
Bulat mailto:bulatz@integ.ru

Certainly Ruby is not designed for this particular application, but also
you used a particular feature of Ruby that would have a particularly bad
effect on performance (blocks) in a performance critical loop.

Your C++ code was implemented using direct pointer dereferences. If you
had instead written your code to construct non-trivial intermediate
objects representing each pixel, the inner loop would have to call the
constructor and destructor for those classes thousands of times,
resulting in poor performance. That would not mean that C++ is slow,
just that that example of C++ code is slow.

So, yes Ruby is slow compared to C++ (it is interpreted after all), but
it is also like any other language in that you have to be careful how
you use the features of the language if performance is important.

Cheers,
Nat.

···

On Thu, 2002-11-21 at 18:56, MetalOne wrote:

I also recognize that Ruby is interpreted. However, I did not expect
the
factor of 200 difference. The interpreter only needs to parse the
loop
once, it should then have byte code to execute for each iteration. Of
course,
it must translate the byte code to machine code, for execution. I
would have expected some constant overhead for this translation on the
order of 2 or 3 times. This is a very tight loop though and every
extra op makes a significant difference.

I knew Ruby was not up for my current task. That is why it is being
written in C++. I was just curious at close it could come. I was
really blown away, by exactly how inadequate it is at such things.


Nat Pryce nat.pryce@b13media.com
B13media

I didn’t test timings, but the C++/Java comparisons I did were not
exactly fair. I knew the C++ could compile more efficiently. At
least
without clever optimization.
C++, *imageIt = lookup[*imageIt]; imageIt++

Change that to ++imageIt and you may get a speed improvement on some
compilers (++imageIt has to create a temporary copy of the iterator,
increment the iterator, and return the copy).

Java, image[i] = lookup[image[i]]; i++;

I also recognize that Ruby is interpreted. However, I did not expect
the factor of 200 difference. The interpreter only needs to parse the
loop once, it should then have byte code to execute for each
iteration.

The Ruby interpreter does not presently use byte code; it traverses a
tree that represents your program.

I knew Ruby was not up for my current task. That is why it is being
written in C++. I was just curious at close it could come. I was
really blown away, by exactly how inadequate it is at such things.

As some people have already suggested, the development model that seems
to work best is to write it in Ruby, profile it, then rewrite the parts
that are too slow as a C extension.

However, Ruby blocks are really nice. I have been trying to make my
C++ do the same thing and I just end up with this mess.

template
void map(FuncData &data, T &v)
{
v = data.lookup[v];
}

template
void for_each_pixel(ImageData &id, FuncData &fd, void
(*func)(FuncDataOnly &fdo, T &v) )
{
T *imageIt = id.image;
T *pLast = imageIt + id.imageSize;
while (imageIt != pLast)
{
(*func)(fd, *imageIt);
imageIt++;
}
}

You shouldn’t have to write your own for_each_pixel; the C++ standard
library already has a for_each function, thus you can write:

template
struct map {
map(FuncData & data) : data_(data) { }
void operator(T & v) { v = data.lookup[v]; }
FuncData const & data_;
};

std::for_each(id.image, id.image + id.imageSize, map(fd));

Or you could instead use std::transform (see
Cash Advance Loans, Instant Decisions | £100 to £5000 in 15 Mins).

You can also get block-like effects with template tricks. This is what
the lambda library and phoenix do:

Chapter 18. Boost.Lambda - 1.84.0
The Spirit Parser Library download | SourceForge.net

Neither is as neat or clean as Ruby’s blocks, but they are fast, are
generated at compile-time, and they are all you’ve got if you want
lambda functions in C++.

Paul

···

On Fri, Nov 22, 2002 at 03:56:18AM +0900, MetalOne wrote:

Hello MetalOne,

Thursday, November 21, 2002, 9:56:18 PM, you wrote:

I also recognize that Ruby is interpreted. However, I did not
expect the factor of 200 difference. The interpreter only needs to
parse the loop once, it should then have byte code to execute for
each iteration. Of course, it must translate the byte code to
machine code, for execution.

ruby is dynamic interpreted language, so for even trivial “x[y]”
computation executor must

  1. find x var in current context
  2. find operator in stack of x classes
  3. find y var in current context
  4. call the operator found with value of y

each step itself is tens or hundreds asm operations, while in C “x[y]”
usually translated into 2 asm ops

···


Best regards,
Bulat mailto:bulatz@integ.ru

Hello Bulat!

I’ve read that using the Array’s at function is faster than
operator because it doesn’t support ranges.

in this situation it’s like giving a banana to man who don’t eat for
30 days :slight_smile:

I guess you’re right, but I couldn’t help trying: Changing the inner
loop like this saved 10% of the execution time:

image[i] = lookup.at(image.at(i))

I guess there are situations where that would matter even if it is not
remotely sufficient in this case…

Writing “image.at(i) = …” gives me a parse error. Why?

Isak

Hello Aleksei,

Thursday, November 21, 2002, 11:14:48 AM, you wrote:

Usually I create my own module having methods and Classes written
in C and/or assembler language.

interesting… what sort of programs you write?

···


Best regards,
Bulat mailto:bulatz@integ.ru

How slow really is Ruby?

How does it compare with Perl, Python, Smalltalk, Java, etc?
Of course Ruby is not going to beat C at speed. But how does it compare
with languages that might be used for similar tasks?

Daniel.

Hello Isak,

Friday, November 22, 2002, 4:11:46 PM, you wrote:

image[i] = lookup.at(image.at(i))

I guess there are situations where that would matter even if it is not
remotely sufficient in this case…

in any other situation difference will be even less than 10% :slight_smile:

Writing “image.at(i) = …” gives me a parse error. Why?

y=a # used method “”, equal to y=a.
a=y # used method “=”, equal to a.=(x,y)
y=a.at(x) #used method “at”
a.at=y #used method “at=”, equal to a.at=(y)
a.at(x)=y #is not ruby syntax

···


Best regards,
Bulat mailto:bulatz@integ.ru

Processing graphics in publishing. Large amounts of vector and raster
images.

Google tells me: http://www.bagley.org/~doug/shootout/

···

Daniel Carrera dcarrera@math.umd.edu wrote:

How does it compare with Perl, Python, Smalltalk, Java, etc?
Of course Ruby is not going to beat C at speed. But how does it
compare with languages that might be used for similar tasks?


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

Hello Daniel,

Thursday, November 21, 2002, 10:36:47 PM, you wrote:

How does it compare with Perl, Python, Smalltalk, Java, etc? Of

in different tests, i got 1.5 to 4 times worse than Perl

···


Best regards,
Bulat mailto:bulatz@integ.ru

I apologize for asking this as I know I’ve seen it, but I can’t find
it. =(

Is there a ruby equivalent to perl’s “$|”? Setting that magic var to
non-0 causes perl to not buffer its output.

Thanks.

···

=====

Yahoo IM: michael_s_campbell


Do you Yahoo!?
Yahoo! Mail Plus – Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com

Hi,

···

In message “Ruby equivalent to perl’s…” on 02/11/22, Michael Campbell michael_s_campbell@yahoo.com writes:

Is there a ruby equivalent to perl’s “$|”? Setting that magic var to
non-0 causes perl to not buffer its output.

STDOUT.sync = true

						matz.

Excellent; thanks.

···

— Yukihiro Matsumoto matz@ruby-lang.org wrote:

Hi,

In message “Ruby equivalent to perl’s…” > on 02/11/22, Michael Campbell michael_s_campbell@yahoo.com > writes:

Is there a ruby equivalent to perl’s “$|”? Setting that magic var
to
non-0 causes perl to not buffer its output.

STDOUT.sync = true

=====

Yahoo IM: michael_s_campbell


Do you Yahoo!?
Yahoo! Mail Plus – Powerful. Affordable. Sign up now.