【问题标题】:Profiling Ruby Code分析 Ruby 代码
【发布时间】:2011-05-04 19:21:17
【问题描述】:

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

我知道 ruby​​-prof 提供了这个,但坦率地说,输出非常令人困惑,并且不容易找出您自己代码的哪些实际块是问题的根源(它告诉您哪些方法调用采取了虽然最多)。所以我并没有真正从中得到我想要的那么多,也没有真正能够利用它。

也许我做错了?有替代品吗?谷歌搜索没有为我带来任何东西。

【问题讨论】:

标签: ruby profiling profiler ruby-prof


【解决方案1】:

要真正深入了解您的代码,请尝试stackprof

以下是有关如何使用它的快速解决方案: 安装 gem:gem install stackprof。在您的代码中添加:require 'stackprof' 并围绕您要检查的部分:

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

运行您的 ruby​​ 脚本后,使用 stackprof stackprof.dump 检查终端中的输出:

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 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 graphviz) dot -T pdf -o stackprof.pdf stackprof.dot 获得漂亮的 PDF 输出,其中突出显示需要长时间运行的方法。

【讨论】:

    【解决方案2】:

    很多分析器都是这样的。 您需要知道的不是程序在哪里花费时间,而是为什么Any references on Dynamic Code Analysis?

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

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

    实际上,查找和测量不是同一个问题。需要进行测量以查看您发现(并修复)的内容是否有所作为。对我来说,找到要修复的内容更像是调试而不是测量。

    解释它的最简单方法是从无限或几乎无限循环开始。你是怎么找到它的?你暂停它并查看堆栈,对吗?因为你知道问题出在堆栈的某个地方。你只需要暂停一次,然后你就需要研究堆栈上的代码。如果您想确定已找到,请暂停几次。

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

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

    附:完成此操作后,可能仍有加速的机会。例如,优化算法可能依赖于数值稳定性。消息驱动的架构会使跟踪代码执行的原因变得更加困难。在实时软件中,性能问题可能只是偶尔发生,并且不太容易采样。这需要更多的聪明才智。仅仅依靠测量是行不通的。

    【讨论】:

    【解决方案3】:

    这是我自己的问题,但我发现了一个非常棒的分析工具,我必须在此处添加它:

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

    相对于查看回溯,火焰图使性能问题的根源惊人地显而易见

    【讨论】:

    • 我承认看回溯既乏味又丑陋,火焰图很性感,但与火焰图相比,回溯会发现加速的超集。 Here's why.
    【解决方案4】:

    还有 ruby -rprofile 或来自 Ruby 源代码的等价物 require 'profile'

    文档:

    https://ruby-doc.org/stdlib-2.1.0/libdoc/profiler/rdoc/Profiler__.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-27
      • 2011-08-14
      • 2015-02-15
      • 2010-09-24
      • 1970-01-01
      相关资源
      最近更新 更多