2010-11-03 75 views
19

除了ruby-prof和核心Benchmark类之外,您用什么来分析Ruby代码?特别是,你如何找到代码中的瓶颈?它几乎感觉我需要使用我自己的小工具来确定所有时间都花在我的代码中。剖析Ruby代码

我意识到ruby-prof提供了这个功能,但是输出结果非常混乱,并且很难找出你自己的代码的哪个块是问题的根源(它告诉你关于哪个方法调用尽管花了大部分时间)。所以我并没有真正想要那么多,也没有真正能够利用它。

也许我做错了吗?有替代品吗?谷歌搜索不会为我提供任何东西。

+1

你有,我不得不在同样的问题[是否有可能在profiling的时候忽略不相关的方法红宝石应用程序?](http://stackoverflow.com/questions/2241491/is-it-possible-to-ignore-irrelevant-methods-when-profiling-ruby-applications)。我发现了关于ruby-prof的方法消除选项。 – 2010-11-04 02:44:30

回答

6

很多轮廓仪都是这样的。 你需要知道的不是其中该程序花费的时间,但为什么Any references on Dynamic Code Analysis?

ADDED:Here's how我在代码中发现“瓶颈”。 (我讨厌这个词。) Here's a list的原因。

假设要找到“瓶颈”,你必须以某种方式进行大量测量是非常自然的。 几乎所有的剖析器都基于它,这是很自然的。

实际上,查找和测量不是同一个问题。测量是需要看看你发现(和固定)是否有所不同。对我而言,寻找解决办法更像调试而非测量。

解释它最简单的方法是从无限循环或接近无限循环开始。你是怎么找到它的?你暂停它,看看堆栈,对吧?因为你知道问题在堆栈中的某处。您只需暂停一次,然后您需要研究堆栈中的代码。如果你想确定你找到它,暂停几次。

假设代码只需要两倍的时间。这意味着当你暂停时,有50%的机会会看到它做不必要的事情。如果你暂停一下并观察它10次,你会在大约5次的动作中捕捉到它。事实上,只要你看到它做了一些你可以优化的样本少至2个,你就发现了一个“瓶颈”。修复它,测量加速,显示它并重复。

即使你最大的问题不是很大,这个方法最终会找到它。 此外,还有一个放大现象,在删除较大问题后,小问题变得更容易找到。这可以让你继续下去,直到代码接近最佳。

P.S.完成此操作后,可能仍有机会加速。例如,优化算法可能取决于数值稳定性。消息驱动体系结构可能会使跟踪代码执行的原因变得更加困难。在实时软件中,性能问题可能只是偶尔发生,并且不太容易采样。这需要更聪明。重新开始测量并没有做到这一点。

+1

谢谢你,我会尝试这种方法。我刚刚也发现了perftools,它是一个采样分析器,并生成如下图所示的调用图:http://perftools-rb.rubyforge.org/examples/rubygems.gif - 您是否认为要手动完成一些额外的信息真的提供了很多优势吗? – ehsanul 2010-11-04 18:19:58

+0

@ehsanul:绝对如Gprof替代方法链接的第3点所述。但不要只听到我的话:http://stackoverflow.com/questions/2624667/whats-a-very-easy-c-profiler-vc/2624725#2624725 http://stackoverflow.com/questions/ 2473666/tips-for-optimize-c-net-programs/2474118#2474118这就像比较华丽的汽车到一架丑陋的飞机。一个看起来不错,但另一个让你在那里。 – 2010-11-04 20:25:34

+0

@MikeDunlavey:一个tyro的问题:你如何中断一个ruby应用并获得回溯?你可以捕获SIGINT进入ruby调试器吗?或者你在gdb下做了什么? – 2013-03-07 16:03:15

2

这是我自己的问题,但我发现了一个工具,它是如此惊人的分析,我要在这里添加:

http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler

Flamegraphs使性能问题的根源惊人明显,相对看回溯。

+1

我承认看回溯是乏味和丑陋的,火焰图是性感的,但与火焰图相比,回溯会找到加速的超集。 [*这是为什么。*](http://stackoverflow.com/a/27867426/23771) – 2015-06-30 13:33:44

5

要深入了解您的代码,请尝试使用stackprof

下面是如何使用它的快速解决方案: 安装gem:gem install stackprof。在你的代码添加:require 'stackprof'和环绕要检查这个部分:

Mode: cpu(1000) 
Samples: 9145 (1.25% miss rate) 
GC: 448 (4.90%) 

TOTAL (pct)  SAMPLES (pct)  FRAME 
    236 (2.6%)   231 (2.5%)  String#blank? 
    546 (6.0%)   216 (2.4%)  ActiveRecord::ConnectionAdapters::Mysql2Adapter#select 
    212 (2.3%)   199 (2.2%)  Mysql2::Client#query_with_timing 
    190 (2.1%)   155 (1.7%)  ERB::Util#html_escape`` 

这里:

StackProf.run(mode: :cpu, out: 'stackprof-output.dump') do {YOUR_CODE} end

运行你的Ruby脚本去检查终端的输出与stackprof stackprof.dump后你可以看到你需要很多时间的所有方法。现在真棒部分:钻只是做stackprof stackprof.dump --method String#blank?,你会得到具体方法的输出:

String#blank? (lib/active_support/core_ext/object/blank.rb:80) 
    samples: 231 self (2.5%)/ 236 total (2.6%) 
    callers: 
    112 ( 47.5%) Object#present? 
    code: 
            | 80 | def blank? 
    187 (2.0%)/ 187 (2.0%) | 81 |  self !~ /[^[:space:]]/ 
            | 82 | end 

而且你可以很容易地计算出你的代码的一部分,需要大量的时间来运行。

如果你想获得一个视觉输出做stackprof stackprof.dump --graphviz >> stackprof.dot和使用的graphviz(brew install graphvizdot- T pdf -o stackprof.pdf stackprof.dot得到一个漂亮的PDF输出,这强调了需要很长的时间来运行的方法。