为什么 NYTProf 的逐行统计数据与总数不匹配?
我有一个 Perl 脚本,需要大约 30 分钟才能运行,所以我当然运行 Devel::NYTProf。很棒的分析器。对于我的许多潜艇来说,我得到了一些对我来说没有意义的数据。
我使用默认的 NYTProf 设置在 Linux 上运行 perl 5.10.0。
在 HTML 输出中,每个子进程都有一个摘要部分,说明子进程及其子进程花费了多少时间,然后继续提供行信息。
行统计数据不等于该函数的总花费。什么给?
例如,我有一个函数,据报告使用 233s (57+166)。逐行数字报告有一行使用了 20 秒,另一行使用了 4 秒,另一行使用了 2 秒。其他行都 <1 秒,函数也没有那么长。
我可以采取什么措施来解决这种不匹配问题?
我可以迁移到 Perl 5.12,但这需要一些工作来安装依赖项。我很高兴以较慢的模式运行它。有没有办法提高采样频率?在较慢的机器上运行?
单击此处获取示例:我的 NYTProf 输出。在本例中,据报告该子系统使用了 225 秒,但将所有数字相加得出 56 秒。此运行已关闭优化:
setenv NYTPROF optimize=0:file=nytprof.optout
更新 我已按照建议使用 findcaller=1 选项标志使用 Perl 5.12 重新运行,结果或多或少相同。 (我在不同的数据集上运行)
更新 Tim B 是对的。我已经更改了一些关键子程序来自行缓存,而不是使用 memoize,并且 NYTProf 结果再次有用。谢谢蒂姆。
I have a Perl script that takes about 30 minutes to run, so of course I run Devel::NYTProf. Great profiler. For many of my subs, I'm getting some data that doesn't make sense to me.
I'm running with perl 5.10.0 on Linux using the default NYTProf settings.
In the HTML output, each of the subs has a summary section stating how much time is spent in the sub and its children and then goes on to give me line information.
The line statistics don't add up to the total spent in the function. What gives?
For example, I have a function that's reported to use 233s (57+166). The line-by-line number report has one line that uses 20s, another that uses 4 and one that uses 2. The other lines are <1s and the function is not that long.
What can I do to resolve this mismatch?
I could move to Perl 5.12 but that would take some work to install the dependencies. I'm happy to run it in a slower mode. Is there a way to increase the sampling frequency? Run on a slower machine?
Click here for a sample: my NYTProf output. In this case, the sub is reported to use 225 seconds, but adding all of the numbers yields 56 seconds. This run had optimization turned off:
setenv NYTPROF optimize=0:file=nytprof.optout
Update I've rerun with Perl 5.12 using the findcaller=1 option flag as suggested with more or less the same results. (I ran on a different dataset)
Update Tim B is right. I have changed some of my key subs to do caching themselves instead of using memoize and the NYTProf results are useful again. Thank you Tim.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我刚刚将其添加到 NYTProf 文档中:
这可能解释了语句时间列的总和(31.7 秒)与为子例程报告的独占时间(57.2 秒)之间的差异。每次调用的差异约为 100 微秒(这似乎有点高,但并非不合理)。
语句分析器跟踪开销上花费了多少时间,例如将语句分析数据写入磁盘。子例程分析器减去进入和离开子例程之间的开销差异,以便给出更准确的分析。
语句探查器通常非常快,因为大多数写入都会为 zip 压缩进行缓冲,因此每个语句的探查器开销往往非常小,通常是单个“滴答”。结果是累积的开销相当嘈杂。对于频繁调用且速度很快的子例程(在本例中,每次调用 899μs 调用 250303 个),这一点变得更加重要。因此,我怀疑这是造成语句时间和独占时间之间差异的另一个较小的原因。
更重要的是,我还添加了这一部分:
Memoize 模块是报告中出现差异的主要原因。对
Memoize::__ANON__[...]
的调用执行由 Memoize 生成的子函数,如下所示sub { unshift @_, $cref;转到&_memoizer; }
。 goto &_memoizer 是由 perl 实现的,作为一种返回给调用者,然后调用指定的子函数,这就是 NYTProf 对其进行分析的方式。造成混乱的原因是,尽管
add_bit_to_map
被记录为_memoizer
的调用者,因此调用时间会添加到add_bit_to_map
,调用的文件和行号位置被记录为goto
的位置。在未来的版本中可能会改进这一点。
感谢您促使我调查此问题并改进文档。
蒂姆·邦斯.
ps 我建议在邮件列表上询问有关 NYTProf 的问题。
I've just added this to the NYTProf documentation:
That probably explains the difference between the sum of the statement time column (31.7s) and the exclusive time reported for the subroutine (57.2s). The difference amounts to approximately 100 microseconds per call (which seems a little high, but not unreasonably so).
The statement profiler keeps track of how much time was spent on overheads, like writing statement profile data to disk. The subroutine profiler subtracts the difference in overheads between entering and leaving the subroutine in order to give a more accurate profile.
The statement profiler is generally very fast because most writes get buffered for zip compression so the profiler overhead per statement tends to be very small, often a single 'tick'. The result is that the accumulated overhead is quite noisy. This becomes more significant for subroutines that are called frequently and are also fast (in this case 250303 calls at 899µs/call). So I suspect this is another, smaller, contribution to the discrepancy between statement time and exclusive times.
More importantly, I've also added this section:
The Memoize module is primary the cause of the discrepancy in your report. The calls to
Memoize::__ANON__[...]
execute a sub generated by Memoize that looks likesub { unshift @_, $cref; goto &_memoizer; }
. Thatgoto &_memoizer
is implemented by perl as a kind of return to the caller followed by a call to the specified sub, and that's the way NYTProf profiles it.The confusion is caused by the fact that, although
add_bit_to_map
is being recorded as the caller of_memoizer
so the time in the call gets added toadd_bit_to_map
, the file and line number location of the call is recorded as the location of thegoto
.It may be possible to improve this in a future release.
Thank you for prompting me to investigate this and improve the documentation.
Tim Bunce.
p.s. I recommend asking questions about NYTProf on the mailing list.
尝试禁用 Perl 的优化器。来自 CPAN 的 Devel::NYTProf 文档:
Try disabling perl's optimizer. From CPAN's Devel::NYTProf docs: