H
Heesob Park
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
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