[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Why Ruby do not optimize code at all?

Heesob Park

3/28/2008 2:38:00 PM

Hi,

I do not undertand why ruby doesn't do any optimization at all during
parsing time.
Some optimization maybe affects debugging process.
Nevertheless, it seems "Constant folding" is not harmful but helpful.
I tried some pre-evaluation of constant or literal nodes in parsing
time.

Consider this code

i = 320 * 200 * 32

Original ruby-1.8.6 parsed it like this:

0:[NODE_BLOCK],0xb7f93ce4,p1:-9,p2:12,p3:1}
-9:[NODE_NEWLINE],0xb7f93d98,u1:0,u2:1,p3:-17}
-17:[NODE_LASGN],0xb7f93e38,u1:10473,p2:-10,u3:2}
-10:[NODE_CALL],0xb7f93dac,p1:-13,u2:42,p3:-11}
-13:[NODE_CALL],0xb7f93de8,p1:-16,u2:42,p3:-14}
-16:[NODE_LIT],0xb7f93e24,u1:641,u2:0,u3:0}
-14:[NODE_ARRAY],0xb7f93dfc,p1:-15,u2:1,u3:0}
-15:[NODE_LIT],0xb7f93e10,u1:401,u2:0,u3:0}
-11:[NODE_ARRAY],0xb7f93dc0,p1:-12,u2:1,u3:0}
-12:[NODE_LIT],0xb7f93dd4,u1:65,u2:0,u3:0}

My modified ruby parsed it like this:

0:[NODE_BLOCK],0xb7f5cd0c,p1:-9,p2:12,p3:1}
-9:[NODE_NEWLINE],0xb7f5cdc0,u1:0,u2:1,p3:-15}
-15:[NODE_LASGN],0xb7f5ce38,u1:10473,p2:-10,u3:2}
-10:[NODE_LIT],0xb7f5cdd4,u1:4096001,u2:0,u3:0}

A little more complex code

c = (12-3) * Math.sin(100) + 1.300 * (2 + 3) * Math.log(100)

Original parser:
0:[NODE_BLOCK],0xb7f35b08,p1:-9,p2:1,p3:1}
-9:[NODE_NEWLINE],0xb7f35bbc,u1:0,u2:4,p3:-38}
-38:[NODE_LASGN],0xb7f35e00,u1:10473,p2:-10,u3:2}
-10:[NODE_CALL],0xb7f35bd0,p1:-27,u2:43,p3:-11}
-27:[NODE_CALL],0xb7f35d24,p1:-33,u2:42,p3:-28}
-33:[NODE_NEWLINE],0xb7f35d9c,u1:0,u2:4,p3:-34}
-34:[NODE_CALL],0xb7f35db0,p1:-37,u2:45,p3:-35}
-37:[NODE_LIT],0xb7f35dec,u1:25,u2:0,u3:0}
-35:[NODE_ARRAY],0xb7f35dc4,p1:-36,u2:1,u3:0}
-36:[NODE_LIT],0xb7f35dd8,u1:7,u2:0,u3:0}
-28:[NODE_ARRAY],0xb7f35d38,p1:-29,u2:1,u3:0}
-29:[NODE_CALL],0xb7f35d4c,p1:-32,u2:9961,p3:-30}
-32:[NODE_CONST],0xb7f35d88,u1:9925,u2:0,u3:0}
-30:[NODE_ARRAY],0xb7f35d60,p1:-31,u2:1,u3:0}
-31:[NODE_LIT],0xb7f35d74,u1:201,u2:0,u3:0}
-11:[NODE_ARRAY],0xb7f35be4,p1:-12,u2:1,u3:0}
-12:[NODE_CALL],0xb7f35bf8,p1:-18,u2:42,p3:-13}
-18:[NODE_CALL],0xb7f35c70,p1:-25,u2:42,p3:-19}
-25:[NODE_LIT],0xb7f35cfc,p1:-26,u2:0,u3:0}
-19:[NODE_ARRAY],0xb7f35c84,p1:-20,u2:1,u3:0}
-20:[NODE_NEWLINE],0xb7f35c98,u1:0,u2:4,p3:-21}
-21:[NODE_CALL],0xb7f35cac,p1:-24,u2:43,p3:-22}
-24:[NODE_LIT],0xb7f35ce8,u1:5,u2:0,u3:0}
-22:[NODE_ARRAY],0xb7f35cc0,p1:-23,u2:1,u3:0}
-23:[NODE_LIT],0xb7f35cd4,u1:7,u2:0,u3:0}
-13:[NODE_ARRAY],0xb7f35c0c,p1:-14,u2:1,u3:0}
-14:[NODE_CALL],0xb7f35c20,p1:-17,u2:10057,p3:-15}
-17:[NODE_CONST],0xb7f35c5c,u1:9925,u2:0,u3:0}
-15:[NODE_ARRAY],0xb7f35c34,p1:-16,u2:1,u3:0}
-16:[NODE_LIT],0xb7f35c48,u1:201,u2:0,u3:0}
Modified parser:
0:[NODE_BLOCK],0xb7f0fae8,p1:-9,p2:1,p3:1}
-9:[NODE_NEWLINE],0xb7f0fb9c,u1:0,u2:4,p3:-40}
-40:[NODE_LASGN],0xb7f0fe08,u1:10473,p2:-10,u3:2}
-10:[NODE_LIT],0xb7f0fbb0,p1:-11,u2:0,u3:0}

String operation code
s = ("hello " + "world ")*100

Original parser:
0:[NODE_BLOCK],0xb7fa4c74,p1:-11,p2:1,p3:1}
-11:[NODE_NEWLINE],0xb7fa4d50,u1:0,u2:2,p3:-22}
-22:[NODE_LASGN],0xb7fa4e2c,u1:10473,p2:-12,u3:2}
-12:[NODE_CALL],0xb7fa4d64,p1:-15,u2:42,p3:-13}
-15:[NODE_NEWLINE],0xb7fa4da0,u1:0,u2:2,p3:-16}
-16:[NODE_CALL],0xb7fa4db4,p1:-19,u2:43,p3:-21}
-19:[NODE_STR],0xb7fa4df0,p1:-20,u2:0,u3:0}
-21:[NODE_ARRAY],0xb7fa4e18,p1:-17,u2:1,u3:0}
-17:[NODE_STR],0xb7fa4dc8,p1:-18,u2:0,u3:0}
-13:[NODE_ARRAY],0xb7fa4d78,p1:-14,u2:1,u3:0}
-14:[NODE_LIT],0xb7fa4d8c,u1:2001,u2:0,u3:0}

Modified parser:
0:[NODE_BLOCK],0xb7efdc6c,p1:-11,p2:1,p3:1}
-11:[NODE_NEWLINE],0xb7efdd48,u1:0,u2:2,p3:-22}
-22:[NODE_LASGN],0xb7efde24,u1:10473,p2:-12,u3:2}
-12:[NODE_STR],0xb7efdd5c,p1:-13,u2:0,u3:0}

In the loop it make considerable difference
With the code
for i in 1..10000
s = "hello"*10000
end
puts s

Original ruby:
real 0m2.591s
user 0m2.579s
sys 0m0.013s

Modified ruby:
real 0m0.010s
user 0m0.007s
sys 0m0.003s

What do you think of the minimum optimization?

Regards,

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

27 Answers

Jason Roelofs

3/28/2008 2:46:00 PM

0

On Fri, Mar 28, 2008 at 10:38 AM, Heesob Park <phasis@gmail.com> wrote:
> Hi,
>
> I do not undertand why ruby doesn't do any optimization at all during
> parsing time.
> Some optimization maybe affects debugging process.
> Nevertheless, it seems "Constant folding" is not harmful but helpful.
> I tried some pre-evaluation of constant or literal nodes in parsing
> time.
>
> Consider this code
>
> i = 320 * 200 * 32
>
> Original ruby-1.8.6 parsed it like this:
>
> 0:[NODE_BLOCK],0xb7f93ce4,p1:-9,p2:12,p3:1}
> -9:[NODE_NEWLINE],0xb7f93d98,u1:0,u2:1,p3:-17}
> -17:[NODE_LASGN],0xb7f93e38,u1:10473,p2:-10,u3:2}
> -10:[NODE_CALL],0xb7f93dac,p1:-13,u2:42,p3:-11}
> -13:[NODE_CALL],0xb7f93de8,p1:-16,u2:42,p3:-14}
> -16:[NODE_LIT],0xb7f93e24,u1:641,u2:0,u3:0}
> -14:[NODE_ARRAY],0xb7f93dfc,p1:-15,u2:1,u3:0}
> -15:[NODE_LIT],0xb7f93e10,u1:401,u2:0,u3:0}
> -11:[NODE_ARRAY],0xb7f93dc0,p1:-12,u2:1,u3:0}
> -12:[NODE_LIT],0xb7f93dd4,u1:65,u2:0,u3:0}
>
> My modified ruby parsed it like this:
>
> 0:[NODE_BLOCK],0xb7f5cd0c,p1:-9,p2:12,p3:1}
> -9:[NODE_NEWLINE],0xb7f5cdc0,u1:0,u2:1,p3:-15}
> -15:[NODE_LASGN],0xb7f5ce38,u1:10473,p2:-10,u3:2}
> -10:[NODE_LIT],0xb7f5cdd4,u1:4096001,u2:0,u3:0}
>
> A little more complex code
>
> c = (12-3) * Math.sin(100) + 1.300 * (2 + 3) * Math.log(100)
>
> Original parser:
> 0:[NODE_BLOCK],0xb7f35b08,p1:-9,p2:1,p3:1}
> -9:[NODE_NEWLINE],0xb7f35bbc,u1:0,u2:4,p3:-38}
> -38:[NODE_LASGN],0xb7f35e00,u1:10473,p2:-10,u3:2}
> -10:[NODE_CALL],0xb7f35bd0,p1:-27,u2:43,p3:-11}
> -27:[NODE_CALL],0xb7f35d24,p1:-33,u2:42,p3:-28}
> -33:[NODE_NEWLINE],0xb7f35d9c,u1:0,u2:4,p3:-34}
> -34:[NODE_CALL],0xb7f35db0,p1:-37,u2:45,p3:-35}
> -37:[NODE_LIT],0xb7f35dec,u1:25,u2:0,u3:0}
> -35:[NODE_ARRAY],0xb7f35dc4,p1:-36,u2:1,u3:0}
> -36:[NODE_LIT],0xb7f35dd8,u1:7,u2:0,u3:0}
> -28:[NODE_ARRAY],0xb7f35d38,p1:-29,u2:1,u3:0}
> -29:[NODE_CALL],0xb7f35d4c,p1:-32,u2:9961,p3:-30}
> -32:[NODE_CONST],0xb7f35d88,u1:9925,u2:0,u3:0}
> -30:[NODE_ARRAY],0xb7f35d60,p1:-31,u2:1,u3:0}
> -31:[NODE_LIT],0xb7f35d74,u1:201,u2:0,u3:0}
> -11:[NODE_ARRAY],0xb7f35be4,p1:-12,u2:1,u3:0}
> -12:[NODE_CALL],0xb7f35bf8,p1:-18,u2:42,p3:-13}
> -18:[NODE_CALL],0xb7f35c70,p1:-25,u2:42,p3:-19}
> -25:[NODE_LIT],0xb7f35cfc,p1:-26,u2:0,u3:0}
> -19:[NODE_ARRAY],0xb7f35c84,p1:-20,u2:1,u3:0}
> -20:[NODE_NEWLINE],0xb7f35c98,u1:0,u2:4,p3:-21}
> -21:[NODE_CALL],0xb7f35cac,p1:-24,u2:43,p3:-22}
> -24:[NODE_LIT],0xb7f35ce8,u1:5,u2:0,u3:0}
> -22:[NODE_ARRAY],0xb7f35cc0,p1:-23,u2:1,u3:0}
> -23:[NODE_LIT],0xb7f35cd4,u1:7,u2:0,u3:0}
> -13:[NODE_ARRAY],0xb7f35c0c,p1:-14,u2:1,u3:0}
> -14:[NODE_CALL],0xb7f35c20,p1:-17,u2:10057,p3:-15}
> -17:[NODE_CONST],0xb7f35c5c,u1:9925,u2:0,u3:0}
> -15:[NODE_ARRAY],0xb7f35c34,p1:-16,u2:1,u3:0}
> -16:[NODE_LIT],0xb7f35c48,u1:201,u2:0,u3:0}
> Modified parser:
> 0:[NODE_BLOCK],0xb7f0fae8,p1:-9,p2:1,p3:1}
> -9:[NODE_NEWLINE],0xb7f0fb9c,u1:0,u2:4,p3:-40}
> -40:[NODE_LASGN],0xb7f0fe08,u1:10473,p2:-10,u3:2}
> -10:[NODE_LIT],0xb7f0fbb0,p1:-11,u2:0,u3:0}
>
> String operation code
> s = ("hello " + "world ")*100
>
> Original parser:
> 0:[NODE_BLOCK],0xb7fa4c74,p1:-11,p2:1,p3:1}
> -11:[NODE_NEWLINE],0xb7fa4d50,u1:0,u2:2,p3:-22}
> -22:[NODE_LASGN],0xb7fa4e2c,u1:10473,p2:-12,u3:2}
> -12:[NODE_CALL],0xb7fa4d64,p1:-15,u2:42,p3:-13}
> -15:[NODE_NEWLINE],0xb7fa4da0,u1:0,u2:2,p3:-16}
> -16:[NODE_CALL],0xb7fa4db4,p1:-19,u2:43,p3:-21}
> -19:[NODE_STR],0xb7fa4df0,p1:-20,u2:0,u3:0}
> -21:[NODE_ARRAY],0xb7fa4e18,p1:-17,u2:1,u3:0}
> -17:[NODE_STR],0xb7fa4dc8,p1:-18,u2:0,u3:0}
> -13:[NODE_ARRAY],0xb7fa4d78,p1:-14,u2:1,u3:0}
> -14:[NODE_LIT],0xb7fa4d8c,u1:2001,u2:0,u3:0}
>
> Modified parser:
> 0:[NODE_BLOCK],0xb7efdc6c,p1:-11,p2:1,p3:1}
> -11:[NODE_NEWLINE],0xb7efdd48,u1:0,u2:2,p3:-22}
> -22:[NODE_LASGN],0xb7efde24,u1:10473,p2:-12,u3:2}
> -12:[NODE_STR],0xb7efdd5c,p1:-13,u2:0,u3:0}
>
> In the loop it make considerable difference
> With the code
> for i in 1..10000
> s = "hello"*10000
> end
> puts s
>
> Original ruby:
> real 0m2.591s
> user 0m2.579s
> sys 0m0.013s
>
> Modified ruby:
> real 0m0.010s
> user 0m0.007s
> sys 0m0.003s
>
> What do you think of the minimum optimization?
>
> Regards,
>
> Park Heesob
> --
> Posted via http://www.ruby-....
>
>

I guess the first question is does Ruby with your parser changes pass
all the tests?

Second, could you post a patch for people to try out and evaluate?
We'll need to see the actual code to really evaluate if you've got
something here.

Jason

Jason Roelofs

3/28/2008 2:53:00 PM

0

On Fri, Mar 28, 2008 at 10:45 AM, Jason Roelofs <jameskilton@gmail.com> wrote:
>
> On Fri, Mar 28, 2008 at 10:38 AM, Heesob Park <phasis@gmail.com> wrote:
> > Hi,
> >
> > I do not undertand why ruby doesn't do any optimization at all during
> > parsing time.
> > Some optimization maybe affects debugging process.
> > Nevertheless, it seems "Constant folding" is not harmful but helpful.
> > I tried some pre-evaluation of constant or literal nodes in parsing
> > time.
> >
> > Consider this code
> >
> > i = 320 * 200 * 32
> >
> > Original ruby-1.8.6 parsed it like this:
> >
> > 0:[NODE_BLOCK],0xb7f93ce4,p1:-9,p2:12,p3:1}
> > -9:[NODE_NEWLINE],0xb7f93d98,u1:0,u2:1,p3:-17}
> > -17:[NODE_LASGN],0xb7f93e38,u1:10473,p2:-10,u3:2}
> > -10:[NODE_CALL],0xb7f93dac,p1:-13,u2:42,p3:-11}
> > -13:[NODE_CALL],0xb7f93de8,p1:-16,u2:42,p3:-14}
> > -16:[NODE_LIT],0xb7f93e24,u1:641,u2:0,u3:0}
> > -14:[NODE_ARRAY],0xb7f93dfc,p1:-15,u2:1,u3:0}
> > -15:[NODE_LIT],0xb7f93e10,u1:401,u2:0,u3:0}
> > -11:[NODE_ARRAY],0xb7f93dc0,p1:-12,u2:1,u3:0}
> > -12:[NODE_LIT],0xb7f93dd4,u1:65,u2:0,u3:0}
> >
> > My modified ruby parsed it like this:
> >
> > 0:[NODE_BLOCK],0xb7f5cd0c,p1:-9,p2:12,p3:1}
> > -9:[NODE_NEWLINE],0xb7f5cdc0,u1:0,u2:1,p3:-15}
> > -15:[NODE_LASGN],0xb7f5ce38,u1:10473,p2:-10,u3:2}
> > -10:[NODE_LIT],0xb7f5cdd4,u1:4096001,u2:0,u3:0}
> >
> > A little more complex code
> >
> > c = (12-3) * Math.sin(100) + 1.300 * (2 + 3) * Math.log(100)
> >
> > Original parser:
> > 0:[NODE_BLOCK],0xb7f35b08,p1:-9,p2:1,p3:1}
> > -9:[NODE_NEWLINE],0xb7f35bbc,u1:0,u2:4,p3:-38}
> > -38:[NODE_LASGN],0xb7f35e00,u1:10473,p2:-10,u3:2}
> > -10:[NODE_CALL],0xb7f35bd0,p1:-27,u2:43,p3:-11}
> > -27:[NODE_CALL],0xb7f35d24,p1:-33,u2:42,p3:-28}
> > -33:[NODE_NEWLINE],0xb7f35d9c,u1:0,u2:4,p3:-34}
> > -34:[NODE_CALL],0xb7f35db0,p1:-37,u2:45,p3:-35}
> > -37:[NODE_LIT],0xb7f35dec,u1:25,u2:0,u3:0}
> > -35:[NODE_ARRAY],0xb7f35dc4,p1:-36,u2:1,u3:0}
> > -36:[NODE_LIT],0xb7f35dd8,u1:7,u2:0,u3:0}
> > -28:[NODE_ARRAY],0xb7f35d38,p1:-29,u2:1,u3:0}
> > -29:[NODE_CALL],0xb7f35d4c,p1:-32,u2:9961,p3:-30}
> > -32:[NODE_CONST],0xb7f35d88,u1:9925,u2:0,u3:0}
> > -30:[NODE_ARRAY],0xb7f35d60,p1:-31,u2:1,u3:0}
> > -31:[NODE_LIT],0xb7f35d74,u1:201,u2:0,u3:0}
> > -11:[NODE_ARRAY],0xb7f35be4,p1:-12,u2:1,u3:0}
> > -12:[NODE_CALL],0xb7f35bf8,p1:-18,u2:42,p3:-13}
> > -18:[NODE_CALL],0xb7f35c70,p1:-25,u2:42,p3:-19}
> > -25:[NODE_LIT],0xb7f35cfc,p1:-26,u2:0,u3:0}
> > -19:[NODE_ARRAY],0xb7f35c84,p1:-20,u2:1,u3:0}
> > -20:[NODE_NEWLINE],0xb7f35c98,u1:0,u2:4,p3:-21}
> > -21:[NODE_CALL],0xb7f35cac,p1:-24,u2:43,p3:-22}
> > -24:[NODE_LIT],0xb7f35ce8,u1:5,u2:0,u3:0}
> > -22:[NODE_ARRAY],0xb7f35cc0,p1:-23,u2:1,u3:0}
> > -23:[NODE_LIT],0xb7f35cd4,u1:7,u2:0,u3:0}
> > -13:[NODE_ARRAY],0xb7f35c0c,p1:-14,u2:1,u3:0}
> > -14:[NODE_CALL],0xb7f35c20,p1:-17,u2:10057,p3:-15}
> > -17:[NODE_CONST],0xb7f35c5c,u1:9925,u2:0,u3:0}
> > -15:[NODE_ARRAY],0xb7f35c34,p1:-16,u2:1,u3:0}
> > -16:[NODE_LIT],0xb7f35c48,u1:201,u2:0,u3:0}
> > Modified parser:
> > 0:[NODE_BLOCK],0xb7f0fae8,p1:-9,p2:1,p3:1}
> > -9:[NODE_NEWLINE],0xb7f0fb9c,u1:0,u2:4,p3:-40}
> > -40:[NODE_LASGN],0xb7f0fe08,u1:10473,p2:-10,u3:2}
> > -10:[NODE_LIT],0xb7f0fbb0,p1:-11,u2:0,u3:0}
> >
> > String operation code
> > s = ("hello " + "world ")*100
> >
> > Original parser:
> > 0:[NODE_BLOCK],0xb7fa4c74,p1:-11,p2:1,p3:1}
> > -11:[NODE_NEWLINE],0xb7fa4d50,u1:0,u2:2,p3:-22}
> > -22:[NODE_LASGN],0xb7fa4e2c,u1:10473,p2:-12,u3:2}
> > -12:[NODE_CALL],0xb7fa4d64,p1:-15,u2:42,p3:-13}
> > -15:[NODE_NEWLINE],0xb7fa4da0,u1:0,u2:2,p3:-16}
> > -16:[NODE_CALL],0xb7fa4db4,p1:-19,u2:43,p3:-21}
> > -19:[NODE_STR],0xb7fa4df0,p1:-20,u2:0,u3:0}
> > -21:[NODE_ARRAY],0xb7fa4e18,p1:-17,u2:1,u3:0}
> > -17:[NODE_STR],0xb7fa4dc8,p1:-18,u2:0,u3:0}
> > -13:[NODE_ARRAY],0xb7fa4d78,p1:-14,u2:1,u3:0}
> > -14:[NODE_LIT],0xb7fa4d8c,u1:2001,u2:0,u3:0}
> >
> > Modified parser:
> > 0:[NODE_BLOCK],0xb7efdc6c,p1:-11,p2:1,p3:1}
> > -11:[NODE_NEWLINE],0xb7efdd48,u1:0,u2:2,p3:-22}
> > -22:[NODE_LASGN],0xb7efde24,u1:10473,p2:-12,u3:2}
> > -12:[NODE_STR],0xb7efdd5c,p1:-13,u2:0,u3:0}
> >
> > In the loop it make considerable difference
> > With the code
> > for i in 1..10000
> > s = "hello"*10000
> > end
> > puts s
> >
> > Original ruby:
> > real 0m2.591s
> > user 0m2.579s
> > sys 0m0.013s
> >
> > Modified ruby:
> > real 0m0.010s
> > user 0m0.007s
> > sys 0m0.003s
> >
> > What do you think of the minimum optimization?
> >
> > Regards,
> >
> > Park Heesob
> > --
> > Posted via http://www.ruby-....
> >
> >
>
> I guess the first question is does Ruby with your parser changes pass
> all the tests?
>
> Second, could you post a patch for people to try out and evaluate?
> We'll need to see the actual code to really evaluate if you've got
> something here.
>
> Jason
>

Oh, and this belongs in the Ruby Core mailing list.

Jason

ts

3/28/2008 3:18:00 PM

0

Heesob Park wrote:
> String operation code
> s = ("hello " + "world ")*100
>

[...]

> Modified parser:
> 0:[NODE_BLOCK],0xb7efdc6c,p1:-11,p2:1,p3:1}
> -11:[NODE_NEWLINE],0xb7efdd48,u1:0,u2:2,p3:-22}
> -22:[NODE_LASGN],0xb7efde24,u1:10473,p2:-12,u3:2}
> -12:[NODE_STR],0xb7efdd5c,p1:-13,u2:0,u3:0}

What do you do, if someone write this

vgs% /usr/bin/ruby
class String
def +(x)
"#{x} #{self}"
end
end

p "a" + "b"
^D
"b a"
vgs%

I know, the example is stupid :-)




Guy Decoux

Chiyuan Zhang

3/28/2008 3:20:00 PM

0

I think the problem is that you can redefine any method
of any class at any time. If some one redefined the `*'
method of Fixnum, your code won't pass, I guess.

2008/3/28, Heesob Park <phasis@gmail.com>:
> Hi,
>
> I do not undertand why ruby doesn't do any optimization at all during
> parsing time.
> Some optimization maybe affects debugging process.
> Nevertheless, it seems "Constant folding" is not harmful but helpful.
> I tried some pre-evaluation of constant or literal nodes in parsing
> time.
>
> Consider this code
>
> i = 320 * 200 * 32
>
> Original ruby-1.8.6 parsed it like this:
>
> 0:[NODE_BLOCK],0xb7f93ce4,p1:-9,p2:12,p3:1}
> -9:[NODE_NEWLINE],0xb7f93d98,u1:0,u2:1,p3:-17}
> -17:[NODE_LASGN],0xb7f93e38,u1:10473,p2:-10,u3:2}
> -10:[NODE_CALL],0xb7f93dac,p1:-13,u2:42,p3:-11}
> -13:[NODE_CALL],0xb7f93de8,p1:-16,u2:42,p3:-14}
> -16:[NODE_LIT],0xb7f93e24,u1:641,u2:0,u3:0}
> -14:[NODE_ARRAY],0xb7f93dfc,p1:-15,u2:1,u3:0}
> -15:[NODE_LIT],0xb7f93e10,u1:401,u2:0,u3:0}
> -11:[NODE_ARRAY],0xb7f93dc0,p1:-12,u2:1,u3:0}
> -12:[NODE_LIT],0xb7f93dd4,u1:65,u2:0,u3:0}
>
> My modified ruby parsed it like this:
>
> 0:[NODE_BLOCK],0xb7f5cd0c,p1:-9,p2:12,p3:1}
> -9:[NODE_NEWLINE],0xb7f5cdc0,u1:0,u2:1,p3:-15}
> -15:[NODE_LASGN],0xb7f5ce38,u1:10473,p2:-10,u3:2}
> -10:[NODE_LIT],0xb7f5cdd4,u1:4096001,u2:0,u3:0}
>
> A little more complex code
>
> c = (12-3) * Math.sin(100) + 1.300 * (2 + 3) * Math.log(100)
>
> Original parser:
> 0:[NODE_BLOCK],0xb7f35b08,p1:-9,p2:1,p3:1}
> -9:[NODE_NEWLINE],0xb7f35bbc,u1:0,u2:4,p3:-38}
> -38:[NODE_LASGN],0xb7f35e00,u1:10473,p2:-10,u3:2}
> -10:[NODE_CALL],0xb7f35bd0,p1:-27,u2:43,p3:-11}
> -27:[NODE_CALL],0xb7f35d24,p1:-33,u2:42,p3:-28}
> -33:[NODE_NEWLINE],0xb7f35d9c,u1:0,u2:4,p3:-34}
> -34:[NODE_CALL],0xb7f35db0,p1:-37,u2:45,p3:-35}
> -37:[NODE_LIT],0xb7f35dec,u1:25,u2:0,u3:0}
> -35:[NODE_ARRAY],0xb7f35dc4,p1:-36,u2:1,u3:0}
> -36:[NODE_LIT],0xb7f35dd8,u1:7,u2:0,u3:0}
> -28:[NODE_ARRAY],0xb7f35d38,p1:-29,u2:1,u3:0}
> -29:[NODE_CALL],0xb7f35d4c,p1:-32,u2:9961,p3:-30}
> -32:[NODE_CONST],0xb7f35d88,u1:9925,u2:0,u3:0}
> -30:[NODE_ARRAY],0xb7f35d60,p1:-31,u2:1,u3:0}
> -31:[NODE_LIT],0xb7f35d74,u1:201,u2:0,u3:0}
> -11:[NODE_ARRAY],0xb7f35be4,p1:-12,u2:1,u3:0}
> -12:[NODE_CALL],0xb7f35bf8,p1:-18,u2:42,p3:-13}
> -18:[NODE_CALL],0xb7f35c70,p1:-25,u2:42,p3:-19}
> -25:[NODE_LIT],0xb7f35cfc,p1:-26,u2:0,u3:0}
> -19:[NODE_ARRAY],0xb7f35c84,p1:-20,u2:1,u3:0}
> -20:[NODE_NEWLINE],0xb7f35c98,u1:0,u2:4,p3:-21}
> -21:[NODE_CALL],0xb7f35cac,p1:-24,u2:43,p3:-22}
> -24:[NODE_LIT],0xb7f35ce8,u1:5,u2:0,u3:0}
> -22:[NODE_ARRAY],0xb7f35cc0,p1:-23,u2:1,u3:0}
> -23:[NODE_LIT],0xb7f35cd4,u1:7,u2:0,u3:0}
> -13:[NODE_ARRAY],0xb7f35c0c,p1:-14,u2:1,u3:0}
> -14:[NODE_CALL],0xb7f35c20,p1:-17,u2:10057,p3:-15}
> -17:[NODE_CONST],0xb7f35c5c,u1:9925,u2:0,u3:0}
> -15:[NODE_ARRAY],0xb7f35c34,p1:-16,u2:1,u3:0}
> -16:[NODE_LIT],0xb7f35c48,u1:201,u2:0,u3:0}
> Modified parser:
> 0:[NODE_BLOCK],0xb7f0fae8,p1:-9,p2:1,p3:1}
> -9:[NODE_NEWLINE],0xb7f0fb9c,u1:0,u2:4,p3:-40}
> -40:[NODE_LASGN],0xb7f0fe08,u1:10473,p2:-10,u3:2}
> -10:[NODE_LIT],0xb7f0fbb0,p1:-11,u2:0,u3:0}
>
> String operation code
> s = ("hello " + "world ")*100
>
> Original parser:
> 0:[NODE_BLOCK],0xb7fa4c74,p1:-11,p2:1,p3:1}
> -11:[NODE_NEWLINE],0xb7fa4d50,u1:0,u2:2,p3:-22}
> -22:[NODE_LASGN],0xb7fa4e2c,u1:10473,p2:-12,u3:2}
> -12:[NODE_CALL],0xb7fa4d64,p1:-15,u2:42,p3:-13}
> -15:[NODE_NEWLINE],0xb7fa4da0,u1:0,u2:2,p3:-16}
> -16:[NODE_CALL],0xb7fa4db4,p1:-19,u2:43,p3:-21}
> -19:[NODE_STR],0xb7fa4df0,p1:-20,u2:0,u3:0}
> -21:[NODE_ARRAY],0xb7fa4e18,p1:-17,u2:1,u3:0}
> -17:[NODE_STR],0xb7fa4dc8,p1:-18,u2:0,u3:0}
> -13:[NODE_ARRAY],0xb7fa4d78,p1:-14,u2:1,u3:0}
> -14:[NODE_LIT],0xb7fa4d8c,u1:2001,u2:0,u3:0}
>
> Modified parser:
> 0:[NODE_BLOCK],0xb7efdc6c,p1:-11,p2:1,p3:1}
> -11:[NODE_NEWLINE],0xb7efdd48,u1:0,u2:2,p3:-22}
> -22:[NODE_LASGN],0xb7efde24,u1:10473,p2:-12,u3:2}
> -12:[NODE_STR],0xb7efdd5c,p1:-13,u2:0,u3:0}
>
> In the loop it make considerable difference
> With the code
> for i in 1..10000
> s = "hello"*10000
> end
> puts s
>
> Original ruby:
> real 0m2.591s
> user 0m2.579s
> sys 0m0.013s
>
> Modified ruby:
> real 0m0.010s
> user 0m0.007s
> sys 0m0.003s
>
> What do you think of the minimum optimization?
>
> Regards,
>
> Park Heesob
>
> --
> Posted via http://www.ruby-....
>
>

James Tucker

3/28/2008 3:39:00 PM

0


On 28 Mar 2008, at 15:20, Chiyuan Zhang wrote:
> I think the problem is that you can redefine any method
> of any class at any time. If some one redefined the `*'
> method of Fixnum, your code won't pass, I guess.

More than this, it may not even be a fixnum or string or whatever
instance class. Not even constants are 'constant'.

> 2008/3/28, Heesob Park <phasis@gmail.com>:
>> Hi,
>>
>> I do not undertand why ruby doesn't do any optimization at all during
>> parsing time.

The AST defines very little, if anything, about what the code will do,
until it is considered as a whole. (Which may not be possible if there
is any eval().

>> Some optimization maybe affects debugging process.
>> Nevertheless, it seems "Constant folding" is not harmful but helpful.
>> I tried some pre-evaluation of constant or literal nodes in parsing
>> time.

As said by others, open classes means parse time != run time, at all.

>> Consider this code
>>
>> i = 320 * 200 * 32

The only time I could see this being sensible to do is if it's
actually closer to:

A = 320.freeze
B = 200.freeze
C = 32.freeze

i = A * B * C

However, the realistic implications are that freeze plus the discussed
optimization causes a pre-processor fixed definition of the methods
A.*() and B.*().

In MRI, one can unfreeze too, so this still isn't "safe", and the
source code does not resemble what is run.

This will kick people most, when reading someone else code.

>>
>> What do you think of the minimum optimization?

I think it shows up immediately in profiling if it's relevant, as if
it is relevant, you will highly likely see a large number of calls to
Fixnum#*, and in some of the given examples, this is exactly where
you'd manually unroll to optimize for speed, or alternatively:

BIG_NUMBER = 100_000 * 100
SOMETHING_THAT_SHOULD_BE_A_CONSTANT = BIG_NUMBER * 'some string'

def foo
SOMETHING_THAT_SHOULD_BE_A_CONSTANT
end

>> Regards,
>>
>> Park Heesob
>>
>> --
>> Posted via http://www.ruby-....

Park Heesob

3/28/2008 4:13:00 PM

0

SGksDQotLS0tLSBPcmlnaW5hbCBNZXNzYWdlIC0tLS0tIA0KRnJvbTogIkphc29uIFJvZWxvZnMi
IDxqYW1lc2tpbHRvbkBnbWFpbC5jb20+DQpUbzogInJ1YnktdGFsayBNTCIgPHJ1YnktdGFsa0By
dWJ5LWxhbmcub3JnPjsgPHJ1YnktY29yZUBydWJ5LWxhbmcub3JnPg0KU2VudDogRnJpZGF5LCBN
YXJjaCAyOCwgMjAwOCAxMTo1MyBQTQ0KU3ViamVjdDogUmU6IFdoeSBSdWJ5IGRvIG5vdCBvcHRp
bWl6ZSBjb2RlIGF0IGFsbD8NCg0KDQo+IE9uIEZyaSwgTWFyIDI4LCAyMDA4IGF0IDEwOjQ1IEFN
LCBKYXNvbiBSb2Vsb2ZzIDxqYW1lc2tpbHRvbkBnbWFpbC5jb20+IHdyb3RlOg0KPj4NCi4uDQo+
PiAgSSBndWVzcyB0aGUgZmlyc3QgcXVlc3Rpb24gaXMgZG9lcyBSdWJ5IHdpdGggeW91ciBwYXJz
ZXIgY2hhbmdlcyBwYXNzDQo+PiAgYWxsIHRoZSB0ZXN0cz8NCj4+DQo+PiAgU2Vjb25kLCBjb3Vs
ZCB5b3UgcG9zdCBhIHBhdGNoIGZvciBwZW9wbGUgdG8gdHJ5IG91dCBhbmQgZXZhbHVhdGU/DQo+
PiAgV2UnbGwgbmVlZCB0byBzZWUgdGhlIGFjdHVhbCBjb2RlIHRvIHJlYWxseSBldmFsdWF0ZSBp
ZiB5b3UndmUgZ290DQo+PiAgc29tZXRoaW5nIGhlcmUuDQo+Pg0KPj4gIEphc29uDQo+Pg0KPiAN
Cj4gT2gsIGFuZCB0aGlzIGJlbG9uZ3MgaW4gdGhlIFJ1YnkgQ29yZSBtYWlsaW5nIGxpc3QuDQo+
IA0KPiBKYXNvbg0KPiANCj4NCk5ldmVyIG1pbmQsIEkgZ2F2ZSBpdCB1cC4NCg0KUmVnYXJkcywN
Cg0KUGFyayBIZWVzb2INCg==


ts

3/28/2008 4:19:00 PM

0

Park Heesob wrote:
> So ruby is never fast but flexible language :)

Well I can give you another example of "premature" optimisation, but
for 1.9

[ruby-bugs:16163]


http://rubyforge.org/tracker/index.php?func=detail&aid=16163&group_id=426&...

it worked but a modification was made to ruby and the optimisation
break the code now



Guy Decoux



Robert Klemme

3/28/2008 4:24:00 PM

0

On 28.03.2008 15:38, Heesob Park wrote:
> I do not undertand why ruby doesn't do any optimization at all during
> parsing time.

Because, as others have pointed out already, at parse time it is not
known what the code will do.

> Some optimization maybe affects debugging process.
> Nevertheless, it seems "Constant folding" is not harmful but helpful.
> I tried some pre-evaluation of constant or literal nodes in parsing
> time.
>
> Consider this code
>
> i = 320 * 200 * 32
>
> Original ruby-1.8.6 parsed it like this:
>
> 0:[NODE_BLOCK],0xb7f93ce4,p1:-9,p2:12,p3:1}
> -9:[NODE_NEWLINE],0xb7f93d98,u1:0,u2:1,p3:-17}
> -17:[NODE_LASGN],0xb7f93e38,u1:10473,p2:-10,u3:2}
> -10:[NODE_CALL],0xb7f93dac,p1:-13,u2:42,p3:-11}
> -13:[NODE_CALL],0xb7f93de8,p1:-16,u2:42,p3:-14}
> -16:[NODE_LIT],0xb7f93e24,u1:641,u2:0,u3:0}
> -14:[NODE_ARRAY],0xb7f93dfc,p1:-15,u2:1,u3:0}
> -15:[NODE_LIT],0xb7f93e10,u1:401,u2:0,u3:0}
> -11:[NODE_ARRAY],0xb7f93dc0,p1:-12,u2:1,u3:0}
> -12:[NODE_LIT],0xb7f93dd4,u1:65,u2:0,u3:0}
>
> My modified ruby parsed it like this:
>
> 0:[NODE_BLOCK],0xb7f5cd0c,p1:-9,p2:12,p3:1}
> -9:[NODE_NEWLINE],0xb7f5cdc0,u1:0,u2:1,p3:-15}
> -15:[NODE_LASGN],0xb7f5ce38,u1:10473,p2:-10,u3:2}
> -10:[NODE_LIT],0xb7f5cdd4,u1:4096001,u2:0,u3:0}

$ ruby -e 'class Fixnum; def *(o) 666 end;end; puts 320 * 200 * 32'
666

Ooops!

Without fiddling:

robert@fussel ~
$ ruby -e 'puts 1/2'
0

robert@fussel ~
$ ruby -r mathn -e 'puts 1/2'
1/2

> A little more complex code
>
> c = (12-3) * Math.sin(100) + 1.300 * (2 + 3) * Math.log(100)
>
> Original parser:
> 0:[NODE_BLOCK],0xb7f35b08,p1:-9,p2:1,p3:1}
> -9:[NODE_NEWLINE],0xb7f35bbc,u1:0,u2:4,p3:-38}
> -38:[NODE_LASGN],0xb7f35e00,u1:10473,p2:-10,u3:2}
> -10:[NODE_CALL],0xb7f35bd0,p1:-27,u2:43,p3:-11}
> -27:[NODE_CALL],0xb7f35d24,p1:-33,u2:42,p3:-28}
> -33:[NODE_NEWLINE],0xb7f35d9c,u1:0,u2:4,p3:-34}
> -34:[NODE_CALL],0xb7f35db0,p1:-37,u2:45,p3:-35}
> -37:[NODE_LIT],0xb7f35dec,u1:25,u2:0,u3:0}
> -35:[NODE_ARRAY],0xb7f35dc4,p1:-36,u2:1,u3:0}
> -36:[NODE_LIT],0xb7f35dd8,u1:7,u2:0,u3:0}
> -28:[NODE_ARRAY],0xb7f35d38,p1:-29,u2:1,u3:0}
> -29:[NODE_CALL],0xb7f35d4c,p1:-32,u2:9961,p3:-30}
> -32:[NODE_CONST],0xb7f35d88,u1:9925,u2:0,u3:0}
> -30:[NODE_ARRAY],0xb7f35d60,p1:-31,u2:1,u3:0}
> -31:[NODE_LIT],0xb7f35d74,u1:201,u2:0,u3:0}
> -11:[NODE_ARRAY],0xb7f35be4,p1:-12,u2:1,u3:0}
> -12:[NODE_CALL],0xb7f35bf8,p1:-18,u2:42,p3:-13}
> -18:[NODE_CALL],0xb7f35c70,p1:-25,u2:42,p3:-19}
> -25:[NODE_LIT],0xb7f35cfc,p1:-26,u2:0,u3:0}
> -19:[NODE_ARRAY],0xb7f35c84,p1:-20,u2:1,u3:0}
> -20:[NODE_NEWLINE],0xb7f35c98,u1:0,u2:4,p3:-21}
> -21:[NODE_CALL],0xb7f35cac,p1:-24,u2:43,p3:-22}
> -24:[NODE_LIT],0xb7f35ce8,u1:5,u2:0,u3:0}
> -22:[NODE_ARRAY],0xb7f35cc0,p1:-23,u2:1,u3:0}
> -23:[NODE_LIT],0xb7f35cd4,u1:7,u2:0,u3:0}
> -13:[NODE_ARRAY],0xb7f35c0c,p1:-14,u2:1,u3:0}
> -14:[NODE_CALL],0xb7f35c20,p1:-17,u2:10057,p3:-15}
> -17:[NODE_CONST],0xb7f35c5c,u1:9925,u2:0,u3:0}
> -15:[NODE_ARRAY],0xb7f35c34,p1:-16,u2:1,u3:0}
> -16:[NODE_LIT],0xb7f35c48,u1:201,u2:0,u3:0}
> Modified parser:
> 0:[NODE_BLOCK],0xb7f0fae8,p1:-9,p2:1,p3:1}
> -9:[NODE_NEWLINE],0xb7f0fb9c,u1:0,u2:4,p3:-40}
> -40:[NODE_LASGN],0xb7f0fe08,u1:10473,p2:-10,u3:2}
> -10:[NODE_LIT],0xb7f0fbb0,p1:-11,u2:0,u3:0}

Same story as above.

> String operation code
> s = ("hello " + "world ")*100

Note that in the code above the only constant is "100". The sequence
"hello" is a String constructor - not a constant - as you can easily see:

irb(main):012:0> (1..5).map { "hello".object_id }
=> [1073415980, 1073415960, 1073415940, 1073415920, 1073415900]
irb(main):013:0> (1..5).map { "hello".object_id }.uniq
=> [1073407290, 1073407270, 1073407250, 1073407230, 1073407210]

> Original parser:
> 0:[NODE_BLOCK],0xb7fa4c74,p1:-11,p2:1,p3:1}
> -11:[NODE_NEWLINE],0xb7fa4d50,u1:0,u2:2,p3:-22}
> -22:[NODE_LASGN],0xb7fa4e2c,u1:10473,p2:-12,u3:2}
> -12:[NODE_CALL],0xb7fa4d64,p1:-15,u2:42,p3:-13}
> -15:[NODE_NEWLINE],0xb7fa4da0,u1:0,u2:2,p3:-16}
> -16:[NODE_CALL],0xb7fa4db4,p1:-19,u2:43,p3:-21}
> -19:[NODE_STR],0xb7fa4df0,p1:-20,u2:0,u3:0}
> -21:[NODE_ARRAY],0xb7fa4e18,p1:-17,u2:1,u3:0}
> -17:[NODE_STR],0xb7fa4dc8,p1:-18,u2:0,u3:0}
> -13:[NODE_ARRAY],0xb7fa4d78,p1:-14,u2:1,u3:0}
> -14:[NODE_LIT],0xb7fa4d8c,u1:2001,u2:0,u3:0}
>
> Modified parser:
> 0:[NODE_BLOCK],0xb7efdc6c,p1:-11,p2:1,p3:1}
> -11:[NODE_NEWLINE],0xb7efdd48,u1:0,u2:2,p3:-22}
> -22:[NODE_LASGN],0xb7efde24,u1:10473,p2:-12,u3:2}
> -12:[NODE_STR],0xb7efdd5c,p1:-13,u2:0,u3:0}
>
> In the loop it make considerable difference
> With the code
> for i in 1..10000
> s = "hello"*10000
> end
> puts s
>
> Original ruby:
> real 0m2.591s
> user 0m2.579s
> sys 0m0.013s
>
> Modified ruby:
> real 0m0.010s
> user 0m0.007s
> sys 0m0.003s
>
> What do you think of the minimum optimization?

I think: if it was that easy, Matz would have done it already. But it
ain't that easy and if you want to have constant expressions simply
assign them to a constant and use that value.

I = 320 * 200 * 32

Kind regards

robert

Steve Ross

3/28/2008 5:21:00 PM

0

On Mar 28, 2008, at 9:19 AM, ts wrote:

> Park Heesob wrote:
>> So ruby is never fast but flexible language :)
>
> Well I can give you another example of "premature" optimisation, but
> for 1.9
>
> [ruby-bugs:16163]
>
>
> http://rubyforge.org/tracker/index.php?func=detail&aid=16163&group_id=426&...
>
> it worked but a modification was made to ruby and the optimisation
> break the code now

Before this question is relegated to the heap of "premature
optimization" ideas, I think the value of some level of programmer-
controller optimizations would be useful in the future. Optimizations
can break code so they are always "caveat programmer." Even in C,
where lots is known about the code, there are code-breaking
optimizations. Again, not a recommendation to do this; just a
recommendation not to dismiss it.

Just my $.02

Daniel Berger

3/28/2008 9:07:00 PM

0



On Mar 28, 11:21=A0am, "s.ross" <cwdi...@gmail.com> wrote:
> On Mar 28, 2008, at 9:19 AM, ts wrote:
>
> > Park Heesob wrote:
> >> So ruby is never fast but flexible language :)
>
> > Well I can give you another example of "premature" optimisation, but
> > for 1.9
>
> > [ruby-bugs:16163]
>
> >http://rubyforge.org/tracker/index.php?func=3Ddetail&aid=3D16163&...
...
>
> > it worked but a modification was made to ruby and the optimisation
> > break the code now
>
> Before this question is relegated to the heap of "premature =A0
> optimization" ideas, I think the value of some level of programmer-
> controller optimizations would be useful in the future. Optimizations =A0
> can break code so they are always "caveat programmer." Even in C, =A0
> where lots is known about the code, there are code-breaking =A0
> optimizations. Again, not a recommendation to do this; just a =A0
> recommendation not to dismiss it.
>
> Just my $.02

Hm, couldn't you use method_added behind the scenes somehow? Perhaps
use the opimized parse tree unless method_added is invoked? Or cache
the parse tree?

Or am I talking nonsense?

Regards,

Dan