2015-07-20 24 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