如何阅读 ruby 分析器的输出

How to read ruby profiler's output

让我们从docs中举个例子:

require 'profile'

def slow_method
  5000.times do
    9999999999999999*999999999
  end
end

def fast_method
  5000.times do
    9999999999999999+999999999
  end
end

slow_method
fast_method

输出:

  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 68.42     0.13      0.13        2    65.00    95.00  Integer#times
 15.79     0.16      0.03     5000     0.01     0.01  Fixnum#*
 15.79     0.19      0.03     5000     0.01     0.01  Fixnum#+
  0.00     0.19      0.00        2     0.00     0.00  IO#set_encoding
  0.00     0.19      0.00        1     0.00   100.00  Object#slow_method
  0.00     0.19      0.00        2     0.00     0.00  Module#method_added
  0.00     0.19      0.00        1     0.00    90.00  Object#fast_method
  0.00     0.19      0.00        1     0.00   190.00  #toplevel

一个方法可能会自己花费时间,或者由于它调用的方法所花费的时间而花费时间。 self ms/call只计算前者,而total ms/call计算两者之和。代表 self seconds 是有意义的,但不是 total seconds 因为那会在整个地方累积。

tl;dr self seconds + 在调用方法中花费的时间

好吧,让我们深入source. There are two procs, gathering information there: PROFILE_CALL_PROC, PROFILE_RETURN_PROC。前者在进入方法之前被调用,后者在退出之前被调用。

@@maps[Thread.current]积累方法信息,即calls, total seconds (cost), self seconds and name in this particular order. This very information is served later to the user, in a more wordy fashion. After being aggregated.

@@stacks[Thread.current] 在堆栈中存储有关方法 运行 的信息。即 "when the method was started" 和 "how much time does called (child) methods took" (tick[1])。这更像是一个临时数据结构,旨在帮助将数据收集到 @@maps.

正如人们现在可以看到的那样,self seconds is total seconds minus cost(花在被调用方法上的时间)。也就是说,total seconds 是花在方法本身和它调用的方法上的时间。

P.S。几乎让人想起 ruby-prof.

中的 flat profiles