I rock.

E

Eric Hodel

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

}
 
P

Phil Tomson

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
 
E

Eric Hodel

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

Linus Sellberg

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

Gyoung-Yoon Noh

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.


No, not yet. Maybe after Thursday hacking.

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,
 
R

Ryan Davis

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

Ryan Davis

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

Eric Hodel

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

Ryan Davis

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.

oooh. I didn't think of that. Not sure why. :p
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.

*nod*

I expect that we'll do a version down the line that includes
TypeChecker in the SexpProcessor pipeline and we'll have better sends
in that version.

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! ;)
 
G

Gyoung-Yoon Noh

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

Bill Guindon

oooh. I didn't think of that. Not sure why. :p


*nod*

I expect that we'll do a version down the line that includes
TypeChecker in the SexpProcessor pipeline and we'll have better sends
in that version.

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?

If a full conversion is likely, any idea on a time line? What would
be the likely limitations?

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 :)
 
E

Eric Hodel

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

Bill Guindon

I think that is on-target.


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.


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' ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top