分析 Ruby 代码

发布于 2024-09-30 09:29:49 字数 271 浏览 3 评论 0原文

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

我意识到 ruby​​-prof 提供了这个,但坦率地说,输出非常混乱,并且不容易找出您自己代码的哪些实际块是问题的根源(它告诉您哪些方法调用花费了最多时间)尽管)。所以我并没有真正从中得到我想要的那么多,也没有真正能够利用它。

也许我做错了?还有其他选择吗?谷歌搜索没有为我带来任何结果。

Besides ruby-prof and and the core Benchmark class, what do you use to profile your Ruby code? In particular, how do you find the bottlenecks in your code? It almost feels like I need to work on my own little tool just to figure out where all the time is being spent in my code.

I realize ruby-prof provides this, but the output is frankly very confusing and doesn't make it easy to find out which actual blocks of your own code are the source of the issue (it tells you about which method calls took the most time though). So I'm not really getting as much out of it as I'd like, and haven't really been able to make use of it.

Perhaps I'm doing it wrong? Are there alternatives? Google searches don't bring up anything for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甜柠檬 2024-10-07 09:29:49

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

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

StackProf.run(mode: :cpu, out: 'stackprof-output.dump')做
{您的代码}
结尾
运行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 输出,其中突出显示了需要很长时间运行的方法。

To really drill into your code try out stackprof.

Here's a quick solution on how to use it:
Install the gem: gem install stackprof. In your code add: require 'stackprof' and surround the part that you want to check with this:

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

After running your ruby script go check the output in the terminal with 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``

Here you can see all your methods that require a lot of time. Now the awesome part: To drill in just do stackprof stackprof.dump --method String#blank? and you get the output for the specific method:

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

And you can quite easily figure out which part of your code takes a lot of time to run.

If you want to get a visual output do stackprof stackprof.dump --graphviz >> stackprof.dot and using graphviz (brew install graphviz) dot -T pdf -o stackprof.pdf stackprof.dot get a beautiful PDF output, which highlights the methods that take a long time to run.

梦里人 2024-10-07 09:29:49

很多分析器都是这样的。
您需要知道的不是程序将时间花在哪里,而是为什么。 有关于动态代码分析的参考吗?

添加:这是我找到“瓶颈”的方法在我的代码中。 (我讨厌这个词。)
以下是原因列表

很自然地认为,要找到“瓶颈”,您必须以某种方式进行大量测量。
它是如此自然,以至于几乎所有分析器都基于它。

事实上,发现和测量不是同一个问题。需要进行测量来看看您发现(和修复)的内容是否产生了影响。对我来说,寻找要修复的内容更像是调试而不是测量。

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

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

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

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

Lots of profilers are like that.
What you need to know is not where the program spends its time, but why. Any references on Dynamic Code Analysis?

ADDED: Here's how I find "bottlenecks" in my code. (I hate that word.)
Here's a list of reasons why.

It is perfectly natural to assume that to find "bottlenecks" you have to somehow do a lot of measuring.
It is so natural that nearly all profilers are based on it.

Actually, finding and measuring are not the same problem. Measuring is needed to see if what you found (and fixed) made a difference. Finding what to fix, to me, is more like debugging than measuring.

The simplest way to explain it is to start from an infinite, or nearly infinite loop. How do you find it? You pause it and look at the stack, right? because you know the problem is somewhere on the stack. You only need to pause it once, and then you need to study the code on the stack. Pause it a few times if you want to be sure you've found it.

Suppose the code only takes twice as long as necessary. That means when you pause it, there is a 50% chance you will see it doing the unnecessary thing. If you pause it and look at it 10 times, you will catch it in the act roughly 5 times. In fact, as soon as you see it doing something you can optimize on as few as 2 samples, you've found a "bottleneck". Fix it, measure the speedup, show it off, and repeat.

Even if your biggest problem is not very big, this method will eventually find it.
Also, there's a magnification phenomenon, where small problems become easier to find after you've removed larger ones. That allows you to keep going until the code is nearly optimal.

P.S. After you've done this, there may still be opportunities for speedup. For example, optimization algorithms can depend on numerical stability. Message-driven architectures can make it harder to trace why code is being executed. In real-time software, a performance problem may only happen occasionally, and be less easy to sample. This requires more cleverness. Falling back on just measuring doesn't do it.

冬天旳寂寞 2024-10-07 09:29:49

这是我自己的问题,但我发现了一个非常适合分析的工具,因此我必须将其添加到此处:

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

火焰图令人惊讶地成为性能问题的根源明显,相对于查看回溯。

This is my own question, but I found a tool that's so amazing for profiling that I have to add it here:

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

Flamegraphs make the source of performance problems amazingly obvious, relative to looking at backtraces.

两人的回忆 2024-10-07 09:29:49

还有 ruby -rprofile 或等效的 Ruby 源代码中的 require 'profile'

文档:

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

There is also ruby -rprofile or equivalently from within Ruby source, require 'profile'

Documentation:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文