2015-07-20 52 views
1

我正在嘗試使用TracePoint跟蹤Ruby程序中的所有方法調用。它運行良好,直到我打了一個方法調用「優化」的方法調用。Trace Ruby調用TracePoint的「優化」方法調用

Ruby的運算符通過用專用指令替換YARV指令來「優化」,以加速方法調用,例如大於,小於。其中一個直接運行

code = <<END 
    1/1 
END 
puts RubyVM::InstructionSequence.compile(code).disasm 

# == disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== 
# 0000 trace   1            ( 1) 
# 0002 putobject_OP_INT2FIX_O_1_C_ 
# 0003 putobject_OP_INT2FIX_O_1_C_ 
# 0004 opt_div   <callinfo!mid:/, argc:1, ARGS_SIMPLE> 
# 0006 leave 

這裏你可以看到opt_div而不是使用opt_send_without_block優化

你可以看到這個使用紅寶石。

看來你不能跟蹤這些優化的方法調用。例如:

trace = TracePoint.trace(:call, :c_call) do |tp| 
    tp.disable 
    puts "calling #{tp.defined_class}##{tp.method_id}" 
    tp.enable 
end 

trace.enable 
1.div(1) 
1/1 
1.div(2) 

你可以看到,1.div被跟蹤,但不1/1

calling TracePoint#enable 
calling Fixnum#div 
calling Fixnum#div 

所以我的問題是:如何跟蹤所有的方法都在Ruby中包括「優化」方法調用( MRI)?

回答

1

從浩一,您可以使用禁用優化:

RubyVM::InstructionSequence.compile_option = { specialized_instruction: false } 

這會爲我的情況下工作,但我想它會減慢執行。

另一個警告,如果你在家裏嘗試這樣做,是因爲在執行該文件時已經編譯過了,所以你不能在同一個文件中設置compile_option。相反,您需要在加載或需要您要跟蹤的文件之前執行此代碼。

您還可以使用EVAL-d代碼此選項:

iseq = RubyVM::InstructionSequence.compile(<<EOS, nil, nil, 1, specialized_instruction: false) 
    1/1 
EOS 

trace = TracePoint.trace(:call, :c_call) do |tp| 
    tp.disable 
    puts "calling #{tp.defined_class}##{tp.method_id}" 
    tp.enable 
end 

iseq.eval