[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Ruby extensions question..

warhero

6/21/2007 5:23:00 PM

So I'm getting slightly confused with writing ruby extensions and what
is best for performance.

I'm working on writing an extension for Ruby, but almost everything i'm
doing at the C level is with rb_* functions using the Ruby C API. I
understand how it works but isn't that just as slow as using Ruby? Or
no?

thanks

--
Posted via http://www.ruby-....

15 Answers

james.d.masters

6/21/2007 5:56:00 PM

0

On Jun 21, 10:22 am, Aaron Smith <beingthexempl...@gmail.com> wrote:
> So I'm getting slightly confused with writing ruby extensions and what
> is best for performance.
>
> I'm working on writing an extension for Ruby, but almost everything i'm
> doing at the C level is with rb_* functions using the Ruby C API. I
> understand how it works but isn't that just as slow as using Ruby? Or
> no?
>
> thanks
>
> --
> Posted viahttp://www.ruby-....

The performance improvement is not found in the Ruby interface to C
but rather in what is going on in the C code itself.

Example:

I write C code that does something computationally intensive - say it
takes about 1 hour to run. If I were to write a Ruby equivalent (only
in Ruby) then let's say that it takes 2 hours. But if I extend that C
code using the Ruby C API then my performance would be 1 hour plus
interface (rb_*) overhead - maybe on the order of a few seconds or
perhaps minutes.

warhero

6/21/2007 6:55:00 PM

0

unknown wrote:
> On Jun 21, 10:22 am, Aaron Smith <beingthexempl...@gmail.com> wrote:
>> --
>> Posted viahttp://www.ruby-....
>
> The performance improvement is not found in the Ruby interface to C
> but rather in what is going on in the C code itself.
>
> Example:
>
> I write C code that does something computationally intensive - say it
> takes about 1 hour to run. If I were to write a Ruby equivalent (only
> in Ruby) then let's say that it takes 2 hours. But if I extend that C
> code using the Ruby C API then my performance would be 1 hour plus
> interface (rb_*) overhead - maybe on the order of a few seconds or
> perhaps minutes.


Thanks that helps.

One more question. Maybe this will end up having the same answer.. But
let's say I have an object that I pass to the ruby extension. and all
operations in the C code i'm doing are on that object passed using
rb_funcall, rb_iv_get, etc. is it still seeing performance gains with C?

thanks

--
Posted via http://www.ruby-....

MenTaLguY

6/21/2007 7:29:00 PM

0

On Fri, 22 Jun 2007 03:55:11 +0900, Aaron Smith <beingthexemplary@gmail.com> wrote:
> One more question. Maybe this will end up having the same answer.. But
> let's say I have an object that I pass to the ruby extension. and all
> operations in the C code i'm doing are on that object passed using
> rb_funcall, rb_iv_get, etc. is it still seeing performance gains with C?

Usually not much. Local variables are a little cheaper, and there's no AST-walking for evaluation, but that's about the extent of it. Ruby method calls are a lot more expensive, so the big wins are when you can avoid Ruby method calls (i.e. rb_funcall) altogether. Otherwise, it's just not worth the maintainability and portability problems.

-mental


warhero

6/21/2007 8:28:00 PM

0

MenTaLguY wrote:
> On Fri, 22 Jun 2007 03:55:11 +0900, Aaron Smith
> <beingthexemplary@gmail.com> wrote:
>> One more question. Maybe this will end up having the same answer.. But
>> let's say I have an object that I pass to the ruby extension. and all
>> operations in the C code i'm doing are on that object passed using
>> rb_funcall, rb_iv_get, etc. is it still seeing performance gains with C?
>
> Usually not much. Local variables are a little cheaper, and there's no
> AST-walking for evaluation, but that's about the extent of it. Ruby
> method calls are a lot more expensive, so the big wins are when you can
> avoid Ruby method calls (i.e. rb_funcall) altogether. Otherwise, it's
> just not worth the maintainability and portability problems.
>
> -mental

Thanks, helps more. I think where I'm going with this is that its best
to write a C program that does everything needed. Then come back and
extend Ruby with those pieces. Instead of worrying about Ruby
integration now, wait till the straight C functionality is there.. Then
there should only be slight overhead of a few rb_* calls.

--
Posted via http://www.ruby-....

MenTaLguY

6/21/2007 8:33:00 PM

0

On Fri, 22 Jun 2007 05:28:17 +0900, Aaron Smith <beingthexemplary@gmail.com> wrote:
> Thanks, helps more. I think where I'm going with this is that its best
> to write a C program that does everything needed. Then come back and
> extend Ruby with those pieces. Instead of worrying about Ruby
> integration now, wait till the straight C functionality is there.. Then
> there should only be slight overhead of a few rb_* calls.

I'd actually say it's the other way around -- write the program in Ruby, then
profile it to see where the slow spots are. Optimize those, and when
you've run out of things to optimize in Ruby, _then_ see if you can cut down
on method calls in critical places by pushing things into C. _if you need
to_ (you may not)

Trying to optimize too early just makes life harder for you, and there are a
surprising number of gotchas when embedding Ruby in a C program (rather than
vice-versa); the Ruby interpreter is not the most embedding-friendly.

-mental


warhero

6/21/2007 9:47:00 PM

0

MenTaLguY wrote:
> On Fri, 22 Jun 2007 05:28:17 +0900, Aaron Smith
> <beingthexemplary@gmail.com> wrote:
>> Thanks, helps more. I think where I'm going with this is that its best
>> to write a C program that does everything needed. Then come back and
>> extend Ruby with those pieces. Instead of worrying about Ruby
>> integration now, wait till the straight C functionality is there.. Then
>> there should only be slight overhead of a few rb_* calls.
>
> I'd actually say it's the other way around -- write the program in Ruby,
> then
> profile it to see where the slow spots are. Optimize those, and when
> you've run out of things to optimize in Ruby, _then_ see if you can cut
> down
> on method calls in critical places by pushing things into C. _if you
> need
> to_ (you may not)
>
> Trying to optimize too early just makes life harder for you, and there
> are a
> surprising number of gotchas when embedding Ruby in a C program (rather
> than
> vice-versa); the Ruby interpreter is not the most embedding-friendly.
>
> -mental

Thanks, Yes I have the ruby application RubyAMF already done. But I'm
trying to optimize the AMF de/serialization and figured C would be the
best solution. So now I just need write the C instead of worrying about
Ruby/AMF integration.. Once the C is working, tie that back into
Ruby/AMF.

--
Posted via http://www.ruby-....

MenTaLguY

6/21/2007 11:17:00 PM

0

On Fri, 22 Jun 2007 06:47:22 +0900, Aaron Smith <beingthexemplary@gmail.com> wrote:
> Thanks, Yes I have the ruby application RubyAMF already done. But I'm
> trying to optimize the AMF de/serialization and figured C would be the
> best solution. So now I just need write the C instead of worrying about
> Ruby/AMF integration.. Once the C is working, tie that back into
> Ruby/AMF.

Ah, {de,}serialization code is one of those places where C is more often helpful.

That said, have you done profiling and taken advantage of all of the
pure Ruby optimization opportunities you've had first?

Performance bottlenecks can happen in very unexpected places, and heavily optimizing
one part of the code won't help you much if 90% of the execution time is happening
in a different part.

Another question to consider is if you are interested in supporting other Ruby
implementations (e.g. JRuby or Ruby.NET). If so, then it's best to minimize the
amount of code you push into C.

Along those lines, profiling may highlight one or two specific methods that need
to be done in C, versus rewriting a large part of the application.

-mental


warhero

6/22/2007 2:50:00 AM

0

MenTaLguY wrote:
> On Fri, 22 Jun 2007 06:47:22 +0900, Aaron Smith
> <beingthexemplary@gmail.com> wrote:
>> Thanks, Yes I have the ruby application RubyAMF already done. But I'm
>> trying to optimize the AMF de/serialization and figured C would be the
>> best solution. So now I just need write the C instead of worrying about
>> Ruby/AMF integration.. Once the C is working, tie that back into
>> Ruby/AMF.
>
> Ah, {de,}serialization code is one of those places where C is more often
> helpful.
>
> That said, have you done profiling and taken advantage of all of the
> pure Ruby optimization opportunities you've had first?
>
> Performance bottlenecks can happen in very unexpected places, and
> heavily optimizing
> one part of the code won't help you much if 90% of the execution time is
> happening
> in a different part.
>
> Another question to consider is if you are interested in supporting
> other Ruby
> implementations (e.g. JRuby or Ruby.NET). If so, then it's best to
> minimize the
> amount of code you push into C.
>
> Along those lines, profiling may highlight one or two specific methods
> that need
> to be done in C, versus rewriting a large part of the application.
>
> -mental

Hm. I haven't thought about JRuby or Ruby.NET. Don't know if it's
something I should worry about. I've done some profiling and overall the
application is pretty well tuned. The times when the application
performs slowly is when returning thousands of records from mysql. When
it's in the serializing code.

Here are a couple ruby-prof call graphs that illustrate the timeliness
of mysql VS returning a string

returning 3000 mysql records:
http://blog.rubyamf.org/profiling/serialize/mysql_300...
http://blog.rubyamf.org/profiling/serialize/mysql_3000...

returning 1 string:
http://blog.rubyamf.org/profiling/serialize/strin...
http://blog.rubyamf.org/profiling/serialize/string...

returning some number
http://blog.rubyamf.org/profiling/serialize/bignu...
http://blog.rubyamf.org/profiling/serialize/fixnu...
http://blog.rubyamf.org/profiling/serialize/floa...

You can start to see processing times increase in the mysql one at the
end of flat version.. Take a look, let me know what you think. I think
the performance gains would definitely be seen writing the
de/serializers with C..

Thanks for talking shop.
-Aaron

--
Posted via http://www.ruby-....

warhero

6/22/2007 3:40:00 AM

0

oh, if you haven't seen ruby-prof or call graphs.. you can google "ruby
call graphs".. here is a good tutorial as well..
http://ruby-prof.rubyforge.org...
-Aaron

--
Posted via http://www.ruby-....

MenTaLguY

6/22/2007 4:44:00 AM

0

On Fri, 2007-06-22 at 11:49 +0900, Aaron Smith wrote:
> Here are a couple ruby-prof call graphs that illustrate the timeliness
> of mysql VS returning a string

Yeah, it does indeed look like the serializer is a good candidate for a
C rewrite, which should remove the need for a lot of method calls.

I was also concerned about RUBYAMF::Util::BinaryString, given its heavy
use of delegation (which is quite expensive in principle), except
looking at the profile it doesn't seem to contribute to the times
anywhere near as much.

Keep up the good work,

-mental