Why Ruby do not optimize code at all?

M

Marcin Mielżyński

ts pisze:
Park said:
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&atid=1698

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

It's not a premature optimisation, just unimplemented yet fallback with
/* TODO: if some === method is overrided */ comment in the source
(insns.def) for opt_case_dispatch specialized instruction (very easy to
accomplish having vm_opt_method_table and ruby_vm_redefined_flag).

For some time there's been similar issue though for case:

a = 0
10.times do |i|
class Fixnum
private :+
end
a+=i
end

Where private didn't record redefined bit in ruby_vm_redefined_flag
(vm.c). Now it's fixed and checked against in rb_export_method
(eval_method.c) and rb_vm_check_redefinition_opt_method (vm.c).

So all standard ruby semantics is still obeyed without sacrificing 1.9
performance.

lopex
 
T

ts

Marcin said:
It's not a premature optimisation, just unimplemented yet fallback with
/* TODO: if some === method is overrided */ comment in the source
(insns.def) for opt_case_dispatch specialized instruction (very easy to
accomplish having vm_opt_method_table and ruby_vm_redefined_flag).

it's a premature optimisation and even worth, in this case, a bug
because it's known, at *compile time*, that the method #=== is
defined for Symbol, this mean that this optimisation must not exist
for Symbol#===


Guy Decoux
 
M

Marcin Mielżyński

ts said:
it's a premature optimisation and even worth, in this case, a bug
because it's known, at *compile time*, that the method #=== is
defined for Symbol, this mean that this optimisation must not exist
for Symbol#===

Not true. The instruction itself is responsible for the fallback (just
not implemented yet).

lopex
 
T

ts

Marcin said:
Not true. The instruction itself is responsible for the fallback (just
not implemented yet).

vgs% ./ruby -ve 'case "a"; when :a; p :eek:k; end'
ruby 1.9.0 (2008-04-01 revision 15881) [i686-linux]
vgs%

It's a bug : it's useless to add an optimisation which *break*
some code and in this case the fallback is *precisely* to call
Symbol#===, i.e. to bypass the optimisation.

Why you don't do the same optimisation with Regexp#===,
Range#===, ... to break more scripts ?



Guy Decoux
 
M

Marcin Mielżyński

ts said:
Marcin said:
Not true. The instruction itself is responsible for the fallback (just
not implemented yet).

vgs% ./ruby -ve 'case "a"; when :a; p :eek:k; end'
ruby 1.9.0 (2008-04-01 revision 15881) [i686-linux]
vgs%

Actually, same happens for 1.8.6 (more Symbol#=== issue), but I'm aware
of your point.
It's a bug : it's useless to add an optimisation which *break*
some code and in this case the fallback is *precisely* to call
Symbol#===, i.e. to bypass the optimisation.

Well, that's why I'd rather call it temporary breakage since the sources
say the author's been aware of it from very beginning (chance the TODO:
comment). Just, opt_case_dispatch impl is not complete _yet_, still
being faster by default by not using funcall dispatch.

Actually a bug (but different) I'd call a compiler issue generating
opt_case_dispatch even with specialized_instruction option turned off, so:

opts = VM::InstructionSequence.compile_option
opts[:specialized_instruction] = false
VM::InstructionSequence.compile_option = opts

s = VM::InstructionSequence.new %{
class Symbol
def === other
puts "foo"
end
end
case :s
when :s
end
}

s.eval


s.disam:

0000 putnil ( 2)
0001 putnil
0002 defineclass :Symbol, <class:Symbol>, 0
0006 pop
0007 putobject :s ( 7)
0009 dup
0010 opt_case_dispatch <cdhash>, 25
0013 putobject :s ( 8)
0015 topn 1
0017 send :===, 1, nil, 0, <ic>
0023 branchif 29
0025 pop ( 7)
0026 putnil
0027 leave
0028 pop
0029 pop ( 9)
0030 putnil
0031 leave ( 8)
== disasm: <ISeq:<class:Symbol>@<compiled>>=============================
0000 putnil ( 3)
0001 definemethod :===, ===, 0
0005 putnil
0006 leave
== disasm: <ISeq:===@<compiled>>========================================
local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] other<Arg>
0000 putnil ( 4)
0001 putstring "foo"
0003 send :puts, 1, nil, 8, <ic>
0009 leave


lopex
 
T

ts

Marcin said:
Well, that's why I'd rather call it temporary breakage since the sources
say the author's been aware of it from very beginning (chance the TODO:
comment). Just, opt_case_dispatch impl is not complete _yet_, still
being faster by default by not using funcall dispatch.

The TODO has nothing to do with this problem. It has worked one day
on early version of 1.9, then matz has modified the class Symbol
and brutally ruby failed because the optimisation was not removed
s = VM::InstructionSequence.new %{
class Symbol
def === other
puts "foo"
end
end
case :s
when :s
end
}

vgs% cat b.rb
#!/usr/bin/ruby
class Symbol
def === other
puts "foo"
end
end
case :s
when :s
puts "s"
end
vgs%

vgs% /usr/bin/ruby -v b.rb
ruby 1.8.6 (2007-06-07 patchlevel 36) [i486-linux]
b.rb:3: warning: method redefined; discarding old ===
foo
vgs%

vgs% ./ruby -v b.rb
ruby 1.9.0 (2008-04-01 revision 15881) [i686-linux]
b.rb:3: warning: method redefined; discarding old ===
foo
vgs%


Guy Decoux
 
M

Marcin Mielżyński

ts pisze:
The TODO has nothing to do with this problem. It has worked one day
on early version of 1.9, then matz has modified the class Symbol
and brutally ruby failed because the optimisation was not removed

This case ?

ruby -ve "puts :a === 'a'"
ruby 1.8.6 (2008-02-02 patchlevel 5000) [i686-linux]
false

../ruby -ve "puts :a === 'a'"
ruby 1.9.0 (2008-04-01 revision 15368) [i686-linux]
true

I still claim opt_case_dispatch will be responsible for the fallback
like any other opt_* opcode and no optimization will be removed.
vgs% cat b.rb
#!/usr/bin/ruby
class Symbol
def === other
puts "foo"
end
end
case :s
when :s
puts "s"
end
vgs%

vgs% /usr/bin/ruby -v b.rb
ruby 1.8.6 (2007-06-07 patchlevel 36) [i486-linux]
b.rb:3: warning: method redefined; discarding old ===
foo
vgs%

vgs% ./ruby -v b.rb
ruby 1.9.0 (2008-04-01 revision 15881) [i686-linux]
b.rb:3: warning: method redefined; discarding old ===
foo
vgs%
That's a bit surprising for me:
ruby -v a.rb
ruby 1.8.6 (2008-02-02 patchlevel 5000) [i686-linux]
a.rb:2: warning: method redefined; discarding old ===
foo


../ruby -v a.rb
ruby 1.9.0 (2008-04-01 revision 15368) [i686-linux]
a.rb:2: warning: method redefined; discarding old ===
s

Since opt_case_dispatch doesn't fallback yet.

lopex
 
T

ts

Marcin said:
That's a bit surprising for me:


we don't have the same version

vgs% make test

sample/test.rb:assignment
.............................................................................................................................................................................................................................................................................................................................................
sample/test.rb:condition ..
sample/test.rb:if/unless ...
sample/test.rb:case .....
sample/test.rb:while/until ........
sample/test.rb:exception .......
sample/test.rb:array .......................................
sample/test.rb:hash ...........................
sample/test.rb:iterator
...............................................................................................................
sample/test.rb:float
................................................................................
sample/test.rb:bignum ...............................
sample/test.rb:string & char
..............................................................
sample/test.rb:assignment ..........
sample/test.rb:call ......
sample/test.rb:proc .........
sample/test.rb:signal ..
sample/test.rb:eval .............................
sample/test.rb:system .........
sample/test.rb:const .....
sample/test.rb:clone .....
sample/test.rb:marshal ....
sample/test.rb:pack ....
sample/test.rb:math ..
sample/test.rb:struct ......
sample/test.rb:variable ...........
sample/test.rb:trace ...
sample/test.rb:defined? ............
sample/test.rb:alias ......
sample/test.rb:path .......................
sample/test.rb:gc ....
test succeeded

test_load.rb .
test_method.rb
.................................................................................................................................................................................................................
test_objectspace.rb ...
test_syntax.rb
........................................................................................................................................
test_marshal.rb .
test_eval.rb .........................
test_knownbug.rb .........:0:in `class_eval': undefined local variable
or method `foo' for main:Object (NameError)
from :0:in `class_eval'
:0:in `class_eval': undefined local variable or method `foo' for
main:Object (NameError)
from :0:in `class_eval'
.....
test_flip.rb .
test_block.rb .....................................................
test_literal.rb
..................................................................................................................................................
test_exception.rb ................................
test_fork.rb .
test_massign.rb ..................................
test_proc.rb ...................
test_class.rb .........................................
test_io.rb ......
test_flow.rb ...........................................
test_thread.rb .......................
test_jump.rb ........................
test_attr.rb ..
test_struct.rb .
PASS 816 tests
vgs%


I first try to make work ruby then I try to optimise
it, not the opposite.


Guy Decoux
 

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,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top