[lnkForumImage]
TotalShareware - Download Free Software

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


 

Eric Hodel

5/3/2005 5:23:00 PM

Yup, rb_intern needs to be cached. Yup, the __self thing is wrong (it
was late, and I forgot about NODE_SELF). No, it doesn't let you
directly call C code either (yet?).

$ cat demo/factorial.rb
class F
def factorial(n)
f = 1
n.downto(2) { |x| f *= x }
return f
end

def main # horrid but funny hack
return factorial(5)
end
end
$ ./translate2.rb demo/factorial.rb > f.c
$ cc -dynamic -bundle -undefined suppress -flat_namespace -g -O2 -pipe
-fno-common -I /usr/local/lib/ruby/1.8/powerpc-darwin7.9.0 f.c -o
F.bundle
$ ruby -I. -rF -e 'p F.new.factorial(5)'
120
$ time ruby -Idemo -rfactorial -e 'p F.new.factorial(9999)' > /dev/null

real 0m3.938s
user 0m3.360s
sys 0m0.080s
$ time ruby -I. -rF -e 'p F.new.factorial(9999)' > /dev/null

real 0m3.751s
user 0m3.340s
sys 0m0.060s

(but I don't expect a speed increase, the way it works)

$ cat f.c
// BEGIN METARUBY PREAMBLE
#include <ruby.h>
#define case_equal_long(x, y) (rb_funcall((x), rb_intern("==="), 1,
(y)))
// END METARUBY PREAMBLE
// class F < Object

static VALUE
rrc_cF_factorial(VALUE __self, VALUE n) {
VALUE f;
VALUE x;
f = LONG2FIX(1);
x = n;
while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
f = rb_funcall(f, rb_intern("*"), 1, x);
x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
};
return f;
}

static VALUE
rrc_cF_main(VALUE __self) {
return rb_funcall(__self, rb_intern("factorial"), 1, LONG2FIX(5));
}

void
Init_F() {
VALUE rrc_cF = rb_define_class("F", rb_path2class("Object"));

rb_define_method(rrc_cF, "factorial", rrc_cF_factorial, 1);
rb_define_method(rrc_cF, "main", rrc_cF_main, 0);

}

--
Eric Hodel - drbrain@segment7.net - http://se...
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04



9 Answers

ptkwt

5/3/2005 5:47:00 PM

0

In article <dd6604df17395617d9dd5740c057200a@segment7.net>,
Eric Hodel <drbrain@segment7.net> wrote:
>Yup, rb_intern needs to be cached. Yup, the __self thing is wrong (it
>was late, and I forgot about NODE_SELF). No, it doesn't let you
>directly call C code either (yet?).
>
>$ cat demo/factorial.rb
>class F
> def factorial(n)
> f = 1
> n.downto(2) { |x| f *= x }
> return f
> end
>
> def main # horrid but funny hack
> return factorial(5)
> end
>end
>$ ./translate2.rb demo/factorial.rb > f.c
>$ cc -dynamic -bundle -undefined suppress -flat_namespace -g -O2 -pipe
>-fno-common -I /usr/local/lib/ruby/1.8/powerpc-darwin7.9.0 f.c -o
>F.bundle
>$ ruby -I. -rF -e 'p F.new.factorial(5)'
>120
>$ time ruby -Idemo -rfactorial -e 'p F.new.factorial(9999)' > /dev/null
>
>real 0m3.938s
>user 0m3.360s
>sys 0m0.080s
>$ time ruby -I. -rF -e 'p F.new.factorial(9999)' > /dev/null
>
>real 0m3.751s
>user 0m3.340s
>sys 0m0.060s
>
>(but I don't expect a speed increase, the way it works)
>
>$ cat f.c
>// BEGIN METARUBY PREAMBLE
>#include <ruby.h>
>#define case_equal_long(x, y) (rb_funcall((x), rb_intern("==="), 1,
>(y)))
>// END METARUBY PREAMBLE
>// class F < Object
>
>static VALUE
>rrc_cF_factorial(VALUE __self, VALUE n) {
>VALUE f;
>VALUE x;
>f = LONG2FIX(1);
>x = n;
>while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
>f = rb_funcall(f, rb_intern("*"), 1, x);
>x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
>};
>return f;
>}
>
>static VALUE
>rrc_cF_main(VALUE __self) {
>return rb_funcall(__self, rb_intern("factorial"), 1, LONG2FIX(5));
>}
>
>void
>Init_F() {
>VALUE rrc_cF = rb_define_class("F", rb_path2class("Object"));
>
>rb_define_method(rrc_cF, "factorial", rrc_cF_factorial, 1);
>rb_define_method(rrc_cF, "main", rrc_cF_main, 0);
>
>}
>


How does this differ from the current RubyToC stuff?
Is this newer version available for download yet?

Phil

Eric Hodel

5/3/2005 6:27:00 PM

0

On 03 May 2005, at 11:09, Phil Tomson wrote:

> In article <dd6604df17395617d9dd5740c057200a@segment7.net>,
> Eric Hodel <drbrain@segment7.net> wrote:
>> $ cat f.c
>> // BEGIN METARUBY PREAMBLE
>> #include <ruby.h>
>> #define case_equal_long(x, y) (rb_funcall((x), rb_intern("==="), 1,
>> (y)))
>> // END METARUBY PREAMBLE
>> // class F < Object
>>
>> static VALUE
>> rrc_cF_factorial(VALUE __self, VALUE n) {
>> VALUE f;
>> VALUE x;
>> f = LONG2FIX(1);
>> x = n;
>> while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
>> f = rb_funcall(f, rb_intern("*"), 1, x);
>> x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
>> };
>> return f;
>> }
>>
>> static VALUE
>> rrc_cF_main(VALUE __self) {
>> return rb_funcall(__self, rb_intern("factorial"), 1, LONG2FIX(5));
>> }
>>
>> void
>> Init_F() {
>> VALUE rrc_cF = rb_define_class("F", rb_path2class("Object"));
>>
>> rb_define_method(rrc_cF, "factorial", rrc_cF_factorial, 1);
>> rb_define_method(rrc_cF, "main", rrc_cF_main, 0);
>>
>> }
>>
>
>
> How does this differ from the current RubyToC stuff?

This one (Ruby2RubyC) generates a C extension, where the other tail
generates raw, type inferenced C code.

I think Ruby2RubyC can make optimizations for Fixnum math and other
boolean logic, but I haven't explored that yet.

Ruby2RubyC is also dynamic code safe. It automatically converts from
Fixnum to Bignum, thanks to the Ruby C runtime. (I snipped the output
of factorial(9999), but it outputs a handful of lines of numbers.)

For example, the other tail could not handle factorial(9999) because C
doesn't have Bignums.

> Is this newer version available for download yet?

No, not yet. Maybe after Thursday hacking.

--
Eric Hodel - drbrain@segment7.net - http://se...
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04



Linus Sellberg

5/3/2005 8:25:00 PM

0

> This one (Ruby2RubyC) generates a C extension, where the other tail
> generates raw, type inferenced C code.

Sounds like a nice way to obfuscate code a bit, for those that are
inclined that way.



Gyoung-Yoon Noh

5/3/2005 8:32:00 PM

0

On 5/4/05, Eric Hodel <drbrain@segment7.net> wrote:
> On 03 May 2005, at 11:09, Phil Tomson wrote:
>
> > In article <dd6604df17395617d9dd5740c057200a@segment7.net>,
> > Eric Hodel <drbrain@segment7.net> wrote:
> >> $ cat f.c
> >> // BEGIN METARUBY PREAMBLE
> >> #include <ruby.h>
> >> #define case_equal_long(x, y) (rb_funcall((x), rb_intern("==="), 1,
> >> (y)))
> >> // END METARUBY PREAMBLE
> >> // class F < Object
> >>
> >> static VALUE
> >> rrc_cF_factorial(VALUE __self, VALUE n) {
> >> VALUE f;
> >> VALUE x;
> >> f = LONG2FIX(1);
> >> x = n;
> >> while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
> >> f = rb_funcall(f, rb_intern("*"), 1, x);
> >> x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
> >> };
> >> return f;
> >> }
> >>
> >> static VALUE
> >> rrc_cF_main(VALUE __self) {
> >> return rb_funcall(__self, rb_intern("factorial"), 1, LONG2FIX(5));
> >> }
> >>
> >> void
> >> Init_F() {
> >> VALUE rrc_cF = rb_define_class("F", rb_path2class("Object"));
> >>
> >> rb_define_method(rrc_cF, "factorial", rrc_cF_factorial, 1);
> >> rb_define_method(rrc_cF, "main", rrc_cF_main, 0);
> >>
> >> }
> >>
> >
> >
> > How does this differ from the current RubyToC stuff?
>
> This one (Ruby2RubyC) generates a C extension, where the other tail
> generates raw, type inferenced C code.
>
> I think Ruby2RubyC can make optimizations for Fixnum math and other
> boolean logic, but I haven't explored that yet.
>
> Ruby2RubyC is also dynamic code safe. It automatically converts from
> Fixnum to Bignum, thanks to the Ruby C runtime. (I snipped the output
> of factorial(9999), but it outputs a handful of lines of numbers.)
>
> For example, the other tail could not handle factorial(9999) because C
> doesn't have Bignums.
>
> > Is this newer version available for download yet?
>
> No, not yet. Maybe after Thursday hacking.
>
> --
> Eric Hodel - drbrain@segment7.net - http://se...
> FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
>
>

Python has PyRex which enables writing CPython extensions
with python-like syntax. I guess Ruby2RubyC can do a foundation
role for future great works such as writing extensions with ruby
syntax, enhancing performance easily with type conversion,
or can be used as intermediate format for translating Ruby to C.

Cheers,

--
http://nohmad.su...



Ryan Davis

5/3/2005 10:19:00 PM

0


On May 3, 2005, at 10:23 AM, Eric Hodel wrote:

> Yup, rb_intern needs to be cached. Yup, the __self thing is wrong (it
> was late, and I forgot about NODE_SELF). No, it doesn't let you
> directly call C code either (yet?).
...
> $ cat f.c
> ...
> static VALUE
> rrc_cF_factorial(VALUE __self, VALUE n) {
> VALUE f;
> VALUE x;
> f = LONG2FIX(1);
> x = n;
> while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
> f = rb_funcall(f, rb_intern("*"), 1, x);
> x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
> };
> return f;

YAY! You do rock! And no, "__self" doesn't suck, but most of the C impl
I've seen just calls it "self" straight up. This is really cool and I
can't wait to read the code.



Ryan Davis

5/3/2005 10:21:00 PM

0


On May 3, 2005, at 1:32 PM, Gyoung-Yoon Noh wrote:

> Python has PyRex which enables writing CPython extensions
> with python-like syntax. I guess Ruby2RubyC can do a foundation
> role for future great works such as writing extensions with ruby
> syntax, enhancing performance easily with type conversion,
> or can be used as intermediate format for translating Ruby to C.

Ruby2RubyC will probably not, for the first few months at least,
improve performance with any sort of type conversion at all. In fact, I
suspect that Eric's current version will start to get fairly severe
penalties until we move away from using rb_funcall for everything. If
you want performance then you should either hand write (using
RubyInline!) or take a peek at zenoptimizer when it gets released in my
ZenHacks package (it uses a combination of ruby2c and rubyinline with a
custom lightweight profiler I wrote last week).

--
ryand-ruby@zenspider.com - Seattle.rb -
http://www.zenspider.com/...
http://blog.zens... - http://rubyforge.org/proje...



Eric Hodel

5/3/2005 10:46:00 PM

0

On 03 May 2005, at 15:21, Ryan Davis wrote:

> On May 3, 2005, at 1:32 PM, Gyoung-Yoon Noh wrote:
>
>> Python has PyRex which enables writing CPython extensions
>> with python-like syntax. I guess Ruby2RubyC can do a foundation
>> role for future great works such as writing extensions with ruby
>> syntax, enhancing performance easily with type conversion,
>> or can be used as intermediate format for translating Ruby to C.
>
> Ruby2RubyC will probably not, for the first few months at least,
> improve performance with any sort of type conversion at all. In fact,
> I suspect that Eric's current version will start to get fairly severe
> penalties until we move away from using rb_funcall for everything.

Yup, it only bypasses the fast parts of eval.c (AST walking), and none
of the slow parts (rb_funcall) so you get almost zero speed benefit out
of it currently. (See the "time factorial(9999)" output further up the
thread).

> If you want performance then you should either hand write (using
> RubyInline!) or take a peek at zenoptimizer when it gets released in
> my ZenHacks package (it uses a combination of ruby2c and rubyinline
> with a custom lightweight profiler I wrote last week).

Yes. When you find a slow part, you could use this as your template.
You'll have working Ruby/C code to refactor into faster C code in no
time at all.

I should be able to skip rb_funcall for places where I know the types,
and directly call the C implementation of a method. That will be more
work though, because I'll have to fall back in case a TypeError is
raised in addition to pulling the right bits from the VALUE.

Or something.

--
Eric Hodel - drbrain@segment7.net - http://se...
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04



Gyoung-Yoon Noh

5/4/2005 2:48:00 AM

0

On 5/4/05, Eric Hodel <drbrain@segment7.net> wrote:
> On 03 May 2005, at 15:21, Ryan Davis wrote:
>
> > On May 3, 2005, at 1:32 PM, Gyoung-Yoon Noh wrote:
> >
> >> Python has PyRex which enables writing CPython extensions
> >> with python-like syntax. I guess Ruby2RubyC can do a foundation
> >> role for future great works such as writing extensions with ruby
> >> syntax, enhancing performance easily with type conversion,
> >> or can be used as intermediate format for translating Ruby to C.
> >
> > Ruby2RubyC will probably not, for the first few months at least,
> > improve performance with any sort of type conversion at all. In fact,
> > I suspect that Eric's current version will start to get fairly severe
> > penalties until we move away from using rb_funcall for everything.
>
> Yup, it only bypasses the fast parts of eval.c (AST walking), and none
> of the slow parts (rb_funcall) so you get almost zero speed benefit out
> of it currently. (See the "time factorial(9999)" output further up the
> thread).


Oops, by 'type conversion', I meant PyRex-style C types usage.
PyRex enables feeding native C types, instead of PythonC types,
easily within its python-like syntax anywhere. In case of ruby, I think
it will be much greater if it's possible to use RubyDL's type wrapper
against native C types.

--
http://nohmad.su...



Bill Guindon

5/5/2005 2:39:00 AM

0

On 5/4/05, Eric Hodel <drbrain@segment7.net> wrote:
> > On 5/3/05, Ryan Davis <ryand-ruby@zenspider.com> wrote:
> >> Isn't it cool that we have these discussions out on a public list like
> >> ruby-talk??? It is almost like, oh I dunno, we want people to look at
> >> the software! ;)
> >
> > Not being a c programmer, I've been watching this thread (and some
> > others) mostly out of curiousity. But I'm beginning to get the
> > impression that the two of you are on the verge of having a full Ruby
> > to C converter. Is that an overestimate?
>
> I think that is on-target.
>
> > If a full conversion is likely, any idea on a time line? What would
> > be the likely limitations?
>
> For Ruby2RubyC, you trade safety for speed (but I may be able to do
> something about that), and you are limited in what is translatable.
> Code in a class or module, or at the top level can't be translated.
>
> The translator isn't fully done yet, I don't know if things like
> constant lookup actually works, and I didn't do anything to make global
> variables work. Those things can be fixed.
>
> It may do different things with scoping of variables too.
>
> > Write it in Ruby, convert it to c, compile it, distribute it. That
> > really would be something. Especially for the non c programmers like
> > myself :)
>
> For a Ruby subset, yes, you can do that. Just for a larger subset than
> Ruby2C.

Eric, you and Ryan have impressed me before, but this takes the cake.

I'll keep watching, and I hope others can do more than just watch. I
expect that subset will be growing, and I look forward to it.

I've used Erik Veenstra's RubyScript2Exe a couple times to share toys
with non-ruby coders, and I think it's a great tool, but this would be
much more impressive (losing size/speed issues).

Keep up the great work. I imagine many others feel the same way.
Consider this an 'advocacy bump' ;-)

--
Bill Guindon (aka aGorilla)