![]() |
1
1523
如果您的目标是使用探查器,请使用建议的探查器之一。 但是,如果您很匆忙,并且可以在调试器下手动中断程序,而程序主观上运行缓慢,那么有一种简单的方法可以发现性能问题。 只需将其暂停几次,每次都查看调用堆栈。如果有一些代码浪费了一定比例的时间,20%或50%或其他什么,这就是您在每个示例的act中捕获它的概率。所以,这大概是你将看到它的样本的百分比。不需要经过教育的猜测。如果你确实对问题是什么有一个猜测,这将证明或反驳它。 您可能有多个不同大小的性能问题。如果你清除了其中的任何一个,剩下的将占据更大的百分比,并更容易发现,在随后的通行证。这 放大效应 当多个问题复合在一起时,可能会导致真正巨大的加速因素。 警告 :程序员倾向于怀疑这种技术,除非他们自己使用过。他们会说分析器提供了这些信息,但只有当他们对整个调用堆栈进行采样,然后让您检查一组随机样本时,这才是真的。(总结是失去洞察力的地方。)调用图不会提供相同的信息,因为
一旦 . 如果您在多个样本上看到问题,那么它是真实的。 附笔。 如果有一种方法可以在某个时间点收集线程池的调用堆栈样本,这也可以在多线程程序上完成,就像在Java中一样。 P.P.S 一般来说,软件中的抽象层越多,就越有可能发现这是性能问题的原因(以及加速的机会)。 :这可能不明显,但堆栈采样技术在存在递归的情况下同样有效。原因是,删除指令所节省的时间近似于包含该指令的样本的分数,而不管它在样本中出现的次数。 我经常听到的另一个反对意见是: 它将在某个地方随机停止,并将错过真正的问题 ". 这来自于对真正的问题有一个先验的概念。 性能问题的一个关键特性是它们不符合预期。 抽样告诉你有些东西是个问题,你的第一反应是不相信。 这是很自然的,但你可以肯定,如果它发现了一个问题,它是真实的,反之亦然。
补充
然后假设我们只取2个堆栈样本,我们看到指令
最后一列说,例如
假设先前的假设不同。假设我们假设
现在它说
另一种看待它的方式叫做
Rule Of Succession
.
如果你把一枚硬币掷两次,两次都是正面朝上,那么这能告诉你硬币可能的重量是多少?
最受尊重的回答是,这是一个Beta分布,具有平均值
(关键是我们看到
所以,即使是非常少的样本也能告诉我们它所看到的指令的成本。(平均而言,它将看到它们的频率与成本成比例。如果
补充
瓶颈可能是一个像这样的大斑点,也可能是许多小斑点,这没有什么区别。
抽样是垂直的。 如果有任何方法可以避免整个程序在那一刻所做的事情, 如果你在第二个样本上看到它 这就是区别所在——看看花时间的全部原因,而不仅仅是花了多少时间。 |
![]() |
2
645
你可以用 Valgrind
它将生成一个名为
|
![]() |
3
372
|
![]() |
4
283
较新的内核(例如最新的Ubuntu内核)附带了新的“perf”工具(
这些都带有经典的采样分析器( man-page )以及令人敬畏的 timechart ! 系统配置文件 而且不仅仅是进程评测—它们可以显示线程、进程和内核之间的交互,并让您了解进程之间的调度和I/O依赖关系。
|
![]() |
5
89
逃跑的答案
现在,当它工作时,我们要开始分析,我们应该在另一个窗口中运行:
这将打开分析。要关闭它并停止整个任务,我们可以使用:
现在我们在当前目录中有一些名为callgrind.out.*的文件。要查看分析结果,请使用:
我建议在下一个窗口中单击“Self”列标题,否则它会显示“main()”是最耗时的任务。“Self”表示每个函数本身花费了多少时间,而不是与依赖项一起。 |
![]() |
6
84
我将使用Valgrind和Callgrind作为分析工具套件的基础。重要的是要知道Valgrind基本上是一台虚拟机:
Callgrind是一个基于此构建的分析器。主要的好处是,您不必运行应用程序数小时才能获得可靠的结果。因为Callgrind是一个很好的工具,所以即使是一秒钟的运行也足以得到可靠的结果 非探测 剖析器。 另一个基于Valgrind的工具是Massif。我使用它来分析堆内存使用情况。它工作得很好。它所做的是为您提供内存使用情况的快照——详细信息,什么占内存的百分比,以及是谁把它放在那里的。这些信息在应用程序运行的不同时间点可用。 |
![]() |
7
65
在过去的几天里,我一直在使用Gprof,并且已经发现了三个重要的限制,其中一个是我在其他任何地方都没有看到的(至今):
这是GNU Gprof (GNU Binutils for Debian)2.18.0.20080103在64位Debian Lenny下运行,如果这对任何人都有帮助的话。 |
![]() |
8
39
C++剖析技术:GPROVS ValgRAND vs PFF与GPrSOOTHORKS
以下测试程序非常简单,可执行以下操作:
main.c
gprof
gprof内置于GCC/binutils中,所以我们所要做的就是使用
出于教育原因,我们还将在未启用优化的情况下运行。请注意,这在实践中是无用的,因为您通常只关心优化优化程序的性能:
第一
因为我们用
这里,这个
https://github.com/jrfonseca/gprof2dot
我们遵守以下规定:
这个
托多:为什么
我选择SVG输出而不是PNG,因为SVG可以用
+
文件大小可以小10倍左右。此外,对于复杂的软件和GNOME,生成的图像的宽度和高度可以达到数万像素
你能很容易地找到最关键的调用堆栈吗?所有这些细小的未排序的意大利面线都在彼此之间?也许有更好的
或者,我们也可以观察
一旦理解了数据输出格式,就可以减少冗长程度,只显示数据,而无需使用
在我们的示例中,输出用于
对于
我不确定是否有一种很好的方法可以使用gprof进行逐行分析: `gprof` time spent in particular lines of code 瓦尔格兰·卡拉格兰 Tools to get a pictorial function call graph of code callgrind是valgrind的评测代码的工具,kcachegrind是一个可以可视化cachegrind输出的KDE程序。
首先,我们必须删除
我使能
运行将生成名为的配置文件数据文件
此外,如果我们在右下角的“调用图”选项卡上,我们会看到一个调用图,我们可以通过右键单击它来导出该调用图,以获得以下带有不合理白边的图像:-)
关于复杂C++软件的toDo,我看到一些类型的条目
这为执行增加了0.2秒,因此我们在时间方面做得很好,但在扩展了
因此,我尝试对
有一件很酷的事
在一个更复杂的例子中,图形的含义变得清晰:
TODO有一个日志
另一个值得使用的perf GUI界面包括:
gperf工具 以前称为“谷歌性能工具”,来源: https://github.com/gperftools/gperftools 基于样本的。 首先使用以下工具安装gperftools:
然后,我们可以通过两种方式启用gperftools CPU探查器:在运行时或在构建时。
在运行时,我们必须通过设置
或者,我们也可以在链接时构建库,而不必经过
另见: gperftools - profile file not dumped
使用这两种方法中的任何一种运行后,我们都会得到一个
与其他工具一样,它给出了一个熟悉的调用图,但使用的是笨重的样本数单位,而不是秒数单位。 或者,我们也可以通过以下方式获得一些文本数据:
其中:
我认为这是与之相同的底层子系统
这对大多数人来说可能太过硬核了,但这很有趣。最小可运行示例位于: Quick way to count number of instructions executed in a C program 英特尔VTune https://en.wikipedia.org/wiki/VTune 这似乎是封闭源代码和x86,但据我所知,这可能是惊人的。我不确定它有多免费,但似乎可以免费下载。待评估。 在Ubuntu 18.04、gprof2dot 2019.11.30、valgrind 3.13.0、perf 4.15.18、Linux内核4.15.0、FLameGraph 1a0dc6985aad06e76857cf2a354bd5ba0c9ce96b、gperftools 2.5-2中测试。 |
![]() |
9
31
使用Valgrind、callgrind和kcachegrind:
生成callgrind.out.x。使用kcachegrind阅读它。 使用gprof(添加-pg):
(对于多线程、函数指针不太好)
使用时间采样,显示I/O和CPU瓶颈。 英特尔VTune是最好的(免费用于教育目的)。 其他: |
![]() |
10
6
对于单线程程序,您可以使用 igprof ,不光彩的剖析者: https://igprof.org/ . 这是一个采样剖面仪,沿着。。。长的Mike Dunlavey的回答,它将把结果包装在一个可浏览的调用堆栈树中,并用每个函数(累积或每个函数)花费的时间或内存进行注释。 |
![]() |
11
6
值得一提的还有
我使用过HPCToolkit和VTune,它们非常有效地找到了问题的症结所在,不需要重新编译代码(除了必须在CMake中使用-g-O或RelWithDebInfo类型的build来获得有意义的输出)。我听说TAU在能力上是相似的。 |
![]() |
12
4
以下是我用来加速代码的两种方法: 对于CPU限制的应用程序:
对于I/O绑定的应用程序:
请注意
对于CPU,在 调试 模式下,编译器将减少数学运算、向量化循环和内联函数,这些函数在汇编代码时往往会将代码整合到不可映射的混乱中。 . 如果您需要 释放
|
![]() |
13
3
|
![]() |
14
3
|
![]() |
15
3
其实有点惊讶没有多少人提到过
google/benchmark
,虽然确定代码的特定区域有点麻烦,特别是如果代码库有点大,但是我发现这在与
|
![]() |
16
2
在工作中,我们有一个非常好的工具,可以帮助我们监控我们想要的日程安排。这已经有用了很多次。
它是C++的,必须根据你的需要定制。不幸的是,我不能共享代码,只能共享概念。
你用的是“大”
您用所有数据检索所谓的大缓冲区,一个小接口解析它,并用名称(向上/向下+值)显示事件,就像示波器用颜色(在中配置)显示事件一样
您可以自定义生成的事件数量,以便只关注您想要的内容。它在调度问题上帮助了我们很多,同时根据每秒记录的事件量消耗了我们想要的CPU量。 您需要3个文件:
其概念是在
您还可以在中定义一些函数
在代码中的任何地方,您都可以使用:
这个
希望这个想法不会因为缺少示例代码而变得模糊。 |
![]() |
17
1
使用
1-平面轮廓:
2-图分析
要获得更多信息,您可以查看
https://sourceware.org/binutils/docs-2.32/gprof/
|
![]() |
18
1
如何识别代码运行缓慢的地方? 当你在运动中遇到障碍物时,它会降低你的速度 像不必要的重新分配循环、缓冲区溢出、搜索、内存泄漏等操作会消耗更多的执行能力,这将对代码的性能产生不利影响, 在分析之前,请确保将-pg添加到编译中:
我还没试过,但我听说过谷歌perftools的好东西。这绝对值得一试。
它将生成一个名为gmon.out或callgrind.out.x的文件。然后可以使用kcachegrind或调试器工具读取此文件。它会给你一个图形化的分析结果,比如哪条线花了多少钱。 我认为是这样 |
![]() |
19
0
由于没有人提到ARM图,我将把它作为个人,我已经成功地使用地图来配置C++科学程序。 ARM映射是用于并行、多线程或单线程C、C++、FORTRAN和F90代码的剖析器。它提供了对源代码行的深入分析和瓶颈定位。与大多数分析器不同,它的设计目的是能够为并行和线程代码评测pthreads、OpenMP或MPI。 地图是商业软件。 |
![]() |
KWMuller · 如何在Netbeans中访问调用计数? 7 年前 |
![]() |
Tim · 测量所有目标(包括相关目标)的xcodebuild持续时间 7 年前 |
![]() |
Bram · 如何启动和停止性能采样 7 年前 |
![]() |
GoodGoodMan · 如何测量C代码中方法的cpu和内存使用率 7 年前 |
![]() |
JumpingJezza · 读取2D矩阵的最快方法 7 年前 |
![]() |
Mayank · 作为后台服务运行的行分析python代码 7 年前 |