Linux性能优化--性能工具:特定进程CPU-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

4.0 概述

在用系统级性能工具找出是哪个进程降低了系统速度之后你需要用特定进程性能工具来发现这个进程的行为。对此Linux提供了丰富的工具用于追踪一个进程和应用程序性能的重要统计信息。

阅读本章后你将能够

  1. 确定应用程序的运行时间是花费在内核上还是在应用程序上。
  2. 确定应用程序有哪些库调用和系统调用以及它们花费的时间。
  3. 分析应用程序找出哪些源代码行和函数的完成时间最长。

4.1进程性能统计信息

分析应用程序性能的工具多种多样并且从UNIX早期就以各种形式存在了。要了解一个应用程序的性能至关重要的一点就是理解它与操作系统、CPU和存储系统是怎样进行交互的。大多数应用程序不是独立的因此需要一些对Linux内核和不同的函数库的调用。这些对Linux内核的调用(或系统调用)可能是简单的如“我的PID是什么?”也可能是复杂的如“从磁盘读取12个数据块”。不同的系统调用会产生不同的性能影响。相应的库调用也可以简单如内存分配复杂如创建图形窗口。这些库调用也有不同的性能特点。

4.1.1内核时间vs.用户时间

一个应用程序所耗时间最基本的划分是内核时间与用户时间。内核时间是消耗在Linux内核上的时间而用户时间则是消耗在应用程序或库代码上的时间。Linux有工具如time 和ps可以(大致)表明应用程序将其时间是花在了应用程序代码上还是花在了内核代码上。同时还有如oprofile和strace这样的命令使你能跟踪哪些内核调用是代表该进程发起的以及每个调用完成需要多少时间。

4.1.2库时间vs.应用程序时间

任何应用程序即便其复杂性非常低也需要依赖系统库才能执行复杂的操作。这些库可能会导致性能问题因此能够查看应用程序在某个库中花费了多少时间就很重要了。虽然为了解决一个问题而去修改库的源代码并不总是实用但是可以改变应用程序代码来调用不同的库函数或者是调用更少的库函数。在库被应用程序使用时ltrace命令和oprofile工具包提供了分析库性能的途径。Linux加载器ld的内置工具帮助你确定使用多个库是否会减慢应用程序的启动时间。

4.1.3细分应用程序时间

当已经知道某应用程序是瓶颈后Linux可以向你提供工具来分析这个应用程序以找出在这个程序中时间都花在了哪里。工具gprof和oprofile可以生成应用程序的配置文件确定是哪些源代码行花费了大量的时间。

4.2工具

Linux有各种各样的工具来帮助你确定应用程序的哪些部分是CPU的主要消费者。本节就对这些工具进行说明。

4.2.1 time

time命令完成一项基本功能当需要测试一条命令的性能时通常会首先运行它。time 命令如同秒表一样可以测量命令执行的时间。它测量的时间有三种类型第一种测量的.是真正的或经过的时间即程序开始到结束执行之间的时间第二种测量的是用户时间即CPU代表该程序执行应用代码所花费的时间第三种测量的是系统时间即CPU代表该程序执行系统或内核代码所花费的时间。

4.2.1.1CPU性能相关的选项

time命令(参见表4-1)调用方式如下
time [-v] application
对application程序计时在其完成后在标准输出上显示它的CPU使用情况。
在这里插入图片描述
表4-2对time命令提供的有效输出统计信息进行了解释。其他项不进行测量且总是显示为零。
在这里插入图片描述
这个命令是启动调查的良好开端。它显示了应用程序执行了多长时间其中多少时间花费在Linux内核上多少时间花费在你的应用程序上。

4.2.1.2 用法示例

包含在Linux中的time命令是跨平台GNU工具的一部分。默认命令输出会打印命令运行的大量统计信息即使Linux不支持它们。如果数据不可用那么time就只打印一个零。下面的命令是对time的一个简单调用。你可以在清单4.1中看到经过的时间(约3 秒)远大于用户时间(0.9秒)和系统时间(0.13秒)的总和这是因为应用程序的大部分时间是用来等待输入的而少量的时间是用于处理器的。
在这里插入图片描述
清单4.2是time显示详细信息的例子。如同你看到的这个输出比time的典型输出显示了更多的信息。遗憾的是大部分统计数据都是零因为Linux不支持它们。大多数情况下详细模式下提供的信息与标准模式下提供的信息是一样的但其统计信息的标签更具有描述性。在这个例子中我们可以看到进程运行时使用了15%的CPU运行用户代码的时间为1.15秒运行内核代码的时间为0.12秒。它累计有2087个主缺页故障或需要访问磁盘的内存故障有371个不需要访问磁盘的缺页故障。大量的主缺页故障表明在应用程序试图使用内存时操作系统在不断的访问磁盘这极有可能意味着进行了大量的交换。
在这里插入图片描述
请注意bash shell有内置time命令因此如果你运行bash并在没有指定执行路径的情况下执行time,你将得到如下输出
在这里插入图片描述
bash内置的time命令是很有用的但是它提供的是进程执行信息的子集。

4.2.2 strace

strace是当程序执行时追踪其发起的系统调用的工具。系统调用是由或代表一个应用程序进行的Linux内核函数调用。strace可以展示准确的系统调用它在确定应用程序是如何使用Linux内核的方面是相当有用的。在分析大型程序或你完全不懂的程序时跟踪系统调用的频率和长度是特别有价值的。通过查看strace的输出你可以了解应用程序如何使用内核以及它依赖于什么类型的函数。

如果你完全理解了一个应用程序但是它有向系统库(如libc或GTK)发起了调用那么此时strace也是很有用的。在这种情况下即使你知道应用程序是如何进行每一个系统调用的库也可能会代表你的应用程序进行更多的系统调用。strace可以迅速告诉你这些库都进行了哪些调用。

虽然strace主要用于跟踪进程与内核之间的交互显示应用程序的每个系统调用的参数和结果但是strace也可以提供不那么令人生畏的汇总信息。应用程序运行之后strace会给出一个表格显示每个系统调用的频率和该类型调用所花费的总的时间。这个表格可以作为理解你的程序与Linux内核之间交互的首个关键信息。

4.2.2.1CPU性能相关的选项

如下的strace调用对性能测试是最有用的
strace [-c] [-p pid] [o file] [-help] [ command [ arg … ] ]
如果strace不带任何选项运行它将在标准错误输出上显示给定命令的所有的系统调用。在试图发现为什么应用程序在内核中花费了大量时间时这是很有帮助的。表4-3说明了一些strace选项它们在跟踪性能问题时也是有用的。
在这里插入图片描述
表4-4解释了strace汇总选项输出的统计信息。每一行输出都说明了特定系统调用的一组统计数据。尽管上述说明的选项是与性能调查最相关的但是strace也可以对其跟踪的系统调用进行类型过滤。strace说明页和–help选项详细解释了用于选择要跟踪哪些系统调用的选项。对一般的性能优化通常没有必要使用它们不过如果需要的话它们也是存在可用的。
在这里插入图片描述

4.2.2.2 用法示例

清单4.3是用strace收集一个应用程序的系统调用统计信息的例子。如你所见strace 提供了对系统调用非常好的分析这些调用是代表应用程序执行的在这里这个应用程序就是oowriter。本例中我们查看oowriter是如何使用read系统调用的。我们看到read 占用了20%的时间共消耗了0.44秒。它被调用了2427次平均下来一次调用的时间为184微秒。在这些调用中有26次返回了错误。
在这里插入图片描述
在这里插入图片描述
strace善于跟踪进程但是它在一个应用程序上运行时会产生一些开销。其结果就是strace报告的调用次数可能会比它报告的每个调用的时间要更加可靠一些。应使用strace提供的次数作为调查的起点而不是每个调用所花费时间的高度精确的测量值。

4.2.3 ltrace

ltrace与strace的概念相似但它跟踪的是应用程序对库的调用而不是对内核的调用。虽然ltrace主要用于提供对库调用的参数和返回值的精确跟踪但是你也可以用它来汇总每个调用所花的时间。这使得你既可以发现应用程序有哪些库调用又可以发现每个调用时间是多长。

使用1trace要小心因为它会产生具有误导性的结果。如果一个库函数调用了另一个函数则花费的时间要计算两次。比如如果库函数foo()调用了函数bar()则函数foo()的报告时间将是函数foo()代码运行的全部时间再加上函数bar()花费的时间。

记住了这个注意事项ltrace就还是揭示应用程序如何表现的有用的工具。

4.2.3.1CPU性能相关的选项

ltrace提供与strace相似的功能其调用方法也和strace相近
ltrace [-c] [-p pid] [-o filename] [-S] [–help] command
在上面的调用中command是你想要ltrace跟踪的命令。如果ltrace不带选项它将在标准错误输出上显示所有的库调用。表4-5解释了与性能调查最相关的ltrace选项。
在这里插入图片描述
同样的汇总模式(summarymode)提供了应用程序执行期间的库调用的性能统计信息。表4-6说明了这些统计数据的含义。
在这里插入图片描述
就像straceltrace有大量的选项可以修改其跟踪的功能。ltrace的–help命令描述了这些选项详细情况见于Itrace说明页。

4.2.3.2 用法示例

清单4.4是ltrace运行于xeyes命令的简单例子。xeyes是一个XWindow应用程序其功能是随着你的鼠标指针在屏幕上弹出一双眼睛。
在这里插入图片描述
在这里插入图片描述
在清单4.4中库函数XSetWMProtocols、hypot、XQeuryPointer分别占用了在库中所花总时间的18.65%、17.19%和12.06%。消耗时间第二多的函数hypot其调用次数为702 次而消耗时间第一多的函数XSetWMProtocols其调用次数仅为1次。除非我们的应用程序能够完全删去对XSetWMProtocols的调用否则不管它需要多少时间我们都会被这个时间所制约。我们最好将注意力转向hypot。这个函数的每次调用都是相对轻量级的因此如果我们能减少它的调用次数就有可能加快该应用程序的速度。假如xeyes应用程序是一个性能问题那么hypot也许是第一个要被调查的函数。起初我们想确定hypot是做什么的但是又不清楚它记录在什么地方。那么是否有可能我们可以找出hypot属于哪个库然后阅读这个库的文档。本例中我们不必先去找库因为hypot函数有说明页。运行man hypot就可以告诉我们hypot函数计算两点之间的距离(斜边)它是数学库libm的一部分。但是库中函数有可能是没有说明页的因此我们需要确定这些没有说明页的函数是属于哪个库的。遗憾的是ltrace不会明显地表示一个函数是来自于哪个库的。要指出这一点我们必须使用Linux工具ldd和objdump。首先ldd用于显示一个动态链接的应用程序使用了哪些库。其次objdump用于在每个库中查找给定的函数。在清单4.5中我们用ldd来查看xeyes应用程序使用了哪些库。
在这里插入图片描述
在这里插入图片描述
现在ldd命令已经显示了xeyes使用的库我们可以用objdump命令来找出这些函数来自哪个库。在清单4.6中我们在xeyes链接的每个库中查找hypot符号。objdump的选项-T列出了库依赖或提供的所有符号(主要是函数)。通过使用fgrep查看带有.text的输出行我们可以发现是哪些库输出hypot函数。本例中libm库是唯一含有hypot函数的库。
在这里插入图片描述
下一步应该浏览xeyes源代码找出hypot是在哪里被调用的如果可能的话减少其调用的次数。或者还有一种方法查看hypot的源并尝试优化库的源代码。通过调查哪个库调用需要很长的时间来完成ltrace使你能确定应用程序的每个库调用的成本。

4.2.4 ps(进程状态)

ps是极好的跟踪运行进程的命令。它给出正在运行进程的详细的静态和动态统计信息。ps提供的静态信息包括命令名和PID,动态信息包括内存和CPU的当前使用情况。

4.2.4.1CPU性能相关的选项

ps有许多不同的选项能检索正在运行中的应用程序的各种统计信息。下面的调用给出了与CPU性能最相关的选项并将显示给定PID的信息
ps [-o etime, time, pcpu, command] [-u user] [-U user] [PID]
ps命令是出现最早的、功能丰富的用于提取性能信息的命令之一因此绝大多数人都会选择使用它。若只看全部功能的一个子集它就更易于管理。表4-7包含了与CPU性能最相关的选项。
在这里插入图片描述
除了CPU统计信息之外ps还提供了数量庞大的各种统计信息其中的一些比如进程的内存使用情况将在后续章节中讨论。

4.2.4.2 用法示例

这个例子是一个测试程序它使用了88%的CPU运行了6秒但是消耗的CPU时间只有5秒
在这里插入图片描述
清单4.7中我们没有调查具体进程的CPU性能而是查看了特定用户运行的全部进程。这可能会揭示特定用户消耗的资源量的信息。本例中我们查看用户netdump运行的所有进程。幸运的是netdump是一个很单调的用户它只运行了bash和top,其中bash 不占用任何CPU,而top只占用了0.5%的CPU。与time不同ps使我们能监控当前正在运行的进程的信息。对于运行时间较长的工作你可以用ps定期检查进程的状态(而不是在程序已经执行完后用它来提供该程序执行的统计信息)。
在这里插入图片描述

4.2.5 ld.so(动态加载器)

执行一个动态链接应用程序时首先运行的是Linux加载器ld.so。ld.so加载该应用程序所有的库并将它使用的符号与库提供的函数关联起来。因为不同的库最初被链接到内存中的不同位置这些位置还可能是重叠的链接器需要对所有的符号进行排序以确保每个符号都位于内存中的不同位置。一个符号从一个虚拟地址移动到另一个虚拟地址就被称为重定位(relocation)。加载器做这项工作是需要时间的如果它完全不用去做那就更好了。预链接应用程序的目标就是通过重排整个系统的系统库来完成这项工作以保证它们不会相互重叠。需要进行大量重定位的应用程序可能没有被预链接过。

Linux加载器的运行不需要用户进行任何干预只需执行一个动态程序即可它是自动运行的。虽然加载器的执行对用户来说是隐藏的但是它的执行仍然要花时间这就有可能会延长应用程序的启动时间。当你要了解加载器的统计信息时加载器展示的是其工作量以便你能弄清楚它是否是瓶颈。

4.2.5.1CPU性能相关的选项

对使用共享库的每一个Linux应用程序来说ld命令的运行是不可见的。通过设置合适的环境变量我们可以要求它显示其执行的信息。下面的调用会影响ld的执行
env LD_DEBUG=statistics, help LD_DEBUG_OUTPUT=filename
加载器的调试能力完全用环境变量控制。表4-8是对这些变量的说明。
在这里插入图片描述
表4-9解释了一些ld.so可以提供的统计信息。时间为时钟周期要将它转换为墙钟时间就必须除以处理器的时钟速度。(该信息见于cat/proc/cpuinfo。)ld能提供的信息有助于确定应用程序开始执行之前设置动态库花费了多少时间。
在这里插入图片描述

4.2.5.2用法示例

在清单4.8中我们运行一个应用程序并用ld调试定义的环境变量。输出的统计信息保存在lddebug文件中。请注意加载器显示了两组不同的统计数据。第一个显示了启动时发生的全部重定位后一个则显示的是程序关闭后所有的统计信息。如果应用程序使用了函数这些可以是不同的值比如使用函数dlopen,它允许共享库在程序开始执行后映射到该应用程序。本例中我们看到加载器时间的83%都用在定位上。如果该应用程序已经预链接过那么这个时间会下降到接近于零。
在这里插入图片描述
如果ld被确定为延长启动时间的原因那么可以通过减少应用程序依赖的库的数量或者是在系统上运行prelink的方法来缩短启动时间。

4.2.6 gprof

剖析Linux应用程序的一种强有力的方法是使用gprof分析命令。gprof可以展示应用程序的调用图并采样该应用程序的时间都花在了哪里。gprof的工作方式是首先编译你的应用程序然后运行该应用程序生成一个采样文件。gprof是非常强大的但是它需要应用源程序并且增加了编译开销。尽管gprof可以确定函数被调用的精确次数以及函数所花的大致时间但是其编译将有可能改变应用程序的时间特性延缓程序的执行。

4.2.6.1CPU性能相关的选项

要用gprof剖析一个应用程序你必须访问应用程序源。然后还需用如下所示的gcc命令编译该程序
gcc gp·g3 -o app app.c
首先你必须用gcc的-gp选项来编译应用程序开启剖析功能。须注意不要与可执行文件剥离如果用-g3选项编译开启符号会更加有用。符号信息对使用gprof的源注释特性是必须的。当你运行被编译过的应用程序时会生成一个输出文件。然后你可以用gprof命令来显示结果。gprof命令的调用如下
gprof [-p -flat -profile -q -graph -brief -A -annotated-source ] app
在这里插入图片描述
对一个特定的剖析来说并不是所有的输出统计信息都是可以得到的。哪个输出统计信息是可得的取决于应用程序是如何为了剖析而被编译的。

4.2.6.2 用法示例

用gprof剖析一个应用程序时第一步是用剖析信息编译该程序。编译器(gcc)将剖析信息插入到应用程序中该程序运行时会被保存到名为gmon.out的文件里。burn测试程序相当简单。它清除了大范围的内存然后调用了两个函数a()和b(),这两个函数都要访问此内存区域。函数a()访问内存的频繁程度是函数b()的10倍。
首先我们编译该应用程序
[ezoltewintermute test_app]$ gcc -pg -g3 -o burn_gprof burn.c
运行程序后我们可以分析输出如清单4.9所示。
在这里插入图片描述
在清单4.9中你可以看到gprof呈现的是我们已经知道的关于该应用程序的情况。程序有两个函数a()和b()。每个函数都调用了一次a()完成的时间(91%)是b()完成时间(8.99%)的10倍。函数a()花费的时间为5.06秒函数b()花费的时间为0.5秒。

清单4.10给出了测试程序的调用图。输出中列出的注释的含义如下尽管gprof没有记录main()的任何样本但它推断出main()必然已经运行因为函数a()和b()都有采样而main是代码中唯一调用它们的函数。gprof没有记录main()的任何样本很可能是因为这个函数太短了。
在这里插入图片描述
最后gprof可以对源代码进行注释以展示每个函数调用的频率。请注意清单4.11 没有显示函数消耗的时间取而代之它显示的是函数被调用的次数。在gprof前面的例子中a()实际时长是b()的10倍因此优化时需要多加小心。不要认为被多次调用的函数实际上使用CPU的时间也多而被调用次数少的函数消耗的CPU时间必然也少。
在这里插入图片描述
在这里插入图片描述
gprof提供了一个很好的总结可以显示应用程序中的函数以及源代码行运行的次数以及它们所花费的时间。

4.2.7 oprofile(Ⅱ)

第2章中讨论过你可以使用oprofile跟踪系统或应用程序中不同事件的位置。与gprof相比oprofile是一个低开销的工具。与gprof不同它在使用前不需要对应用程序进行二次编译。oprofile也可以测量gprof不支持的事件。目前oprofile只支持那些gprof用内核补丁可以生成的调用图而gprof能够在所有的Linux内核上运行。

4.2.7.1CPU性能相关的选项

2.2.8节讨论的oprofile涉及的是如何用oprofile开始进行剖析。本小节介绍的则是oprofile用于分析进程级采样结果的部分。oprofile有一系列工具来显示已收集的样本。第一个工具opreport显示的是样本在可执行文件和库的函数中分布情况。其调用形式如下
opreport [-d -details -f -long-filenames -l -symbols -l] application
表4-11解释了几个命令它们能够修改由opreport提供的信息的等级。
第二个你能用来提取性能样本信息的命令是opannotate。opannotate可以将样本对应到具体的源代码行或汇编指令。其调用形式如下
opannotate[-a assembly][-s --source] application
在这里插入图片描述
表4-12说明了该调用的选项它们能让你指定opannotate提供的确切信息。这里有一个忠告由于处理器硬件计数器在源代码行和指令级上的限制样本可能不会准确对应到引发它的那一行。不过它们会很接近实际的事件。
在这里插入图片描述
使用opannotate和opreport时指明应用程序的完整路径名总是最好的做法。如果不这样做你可能会接收到一条神秘的错误信息(如果oprofile无法发现应用程序的样本)。默认情况下在显示结果时opreport只显示可执行文件名这会与系统中多个有相同名称的可执行文件或库相混淆。因此总是指定-f选项就可以让opreport显示应用程序的完整路径。

oprofile还可以提供一个命令opgprof用于输出由oprofile收集的样本其输出形式能被gprof理解。该命令的调用方式如下
opgprof application
该命令获取application的样本并生成与gprof兼容的文件。之后你就可以用gprof 命令来查看该文件了。

4.2.7.2 用法示例

鉴于我们已经在2.2.8节中了解过oprofile,这里的例子向你展示的将是如何利用oprofile来跟踪源代码特定行的性能问题。本小节假设你已经用opcontrol命令启动了剖析。下一步就是运行有性能问题的程序。本例中我们使用的是burn程序就是在gprof示例中用过的程序。我们按如下方式启动测试程序
[ezoltewintermute tmp] . / b u r n 程序完成后我们必须将 o p r o f i l e 的缓冲区转储到硬盘否则样本对 o p r e p o r t 将是不可用的。用如下命令完成这一步 [ e z o l t e w i n t e r m u t e t m p ] ./burn 程序完成后我们必须将oprofile的缓冲区转储到硬盘否则样本对opreport将是不可用的。用如下命令完成这一步 [ezoltewintermute tmp] ./burn程序完成后我们必须将oprofile的缓冲区转储到硬盘否则样本对opreport将是不可用的。用如下命令完成这一步[ezoltewintermutetmp] sudo opcontrol -d
接着在清单4.12中我们要求opreport告诉我们与测试程序/tmp/burn相关的样本。这能让我们对该应用程序消耗的周期数有个总体映像。本例中我们看到应用程序有9939 个样本。如果我们深入oprofile工具我们将了解这些样本是如何在burn程序中分布的。
在这里插入图片描述
之后在清单4.13中我们想了解所有样本是属于burn程序中的哪些函数。由于我们使用了CPU_CLK_UNHANLTED事件这大致对应于每个函数所花费的相对时间。通过查看输出我们可以看到91%的时间花在了函数a()上9%的时间花在了函数b()上。
在这里插入图片描述
在清单4.14中我们要求opreport展示哪些虚拟地址有对应的样本。本例中看上去似乎位于地址0x0804838a的指令拥有75%的样本。但是现在还不清楚这条指令是做什么的或者为什么有这么多样本。
在这里插入图片描述
在这里插入图片描述
通常对我们更加有用的是知道使用所有CPU时间的源代码行而不是使用它的指令的虚拟地址。找出一条特定指令与源代码行之间的对应关系并不总是容易的事儿。因此在清单4.15中我们要求opannotate来做这项困难的工作向我们展示相对于原始源代码的样本(而并非指令的虚拟地址)。
在这里插入图片描述
在这里插入图片描述
正如你能在清单4.15中看到的一样opannotate把大部分样本(86.59%)归因于函数a()中的for循环。可惜的是for循环中这部分的代价并不会很高。对现代处理器来说整数加上固定数的执行速度是非常快的。因此oprofile报告的样本可能被归于错误的源代码行。而下面的代码行(test[i]++;)其代价则非常高因为它要访问内存子系统。这一行才应该是这些样本所对应的。

有些超出oprofile控制的原因会导致它对样本的错误对应。首先处理器并不总是精确中断于导致事件发生的那一行。这可能会让样本被归于事件源头附近的指令而不是引发事件的那条指令。其次当源代码被编译时编译器常常为了让执行更有效率而重排指令。编译器完成优化后代码也许就不是按照其编写的顺序来执行。不同的源代码行可能被重排和组合。其结果就是特定的指令也许是多个源代码行的结果或者甚至于是编译器生成的中间代码段而这段中间代码在原始源代码中是不存在的。因此当编译器优化代码生成机器指令时原始源代码行与生成的机器指令之间可能不再有一对一的映射关系。这就使得让oprofile(和调试器)指出每条机器指令究竟对应哪一行源代码变得困难重重甚至于不可能。不过oprofile还是试图尽可能的准确因此通常你可以看看高样本计数代码行的上下几行就可以找出真正代价高的那行代码。如果需要你可以用opannotate来显示确切的汇编指令以及正在接收所有样本的虚拟地址。这有可能发现汇编指令在做什么从而手动将它映射回你的原始源代码。oprofile的样本归属并不准确但它通常是足够接近的。即使存在这些限制oprofile提供的文件显示了大致的源代码行以供调查一般说来这就足够找出应用程序的速度慢在了哪里。

4.2.8语言静态(C和C++)vs.动态(Java和Mono)

大多数Linux性能工具都支持对静态语言(如C和C++)的分析本章描述的所有工具都能运用于由这些语言编写的应用程序。工具ltrace,strace和time可运用于由动态语言编写的应用程序比如Java、Mono、Python和Perl。但是剖析工具gprof和oprofile不能用于这些类型的应用程序。幸运的是大多数动态语言提供了并不只针对Linux的剖析基础工具来生成相似类型的配置文件。

对Java应用程序而言如果运行java命令时带上了-Xrunhprof命令行选项那么-Xrunhprof将对应用程序进行剖析。更多详细信息参见http://antprof.sourceforge.net/hprof.html。对Mono应用程序而言如果mono可执行文件被传递了–profile标志那么它将剖析该应用程序。更多详细信息参见http://www.mono-project.com/docs/advanced/performance-tips/。Perl和Python也有相似的剖析功能Perl的Devel::DProf的说明见于网址http://perl.com/pub/a/2004/06/25/profiling.html,而Python的profiler的说明则见于新网址https://docs.python.org/3/library/index.html。

4.3本章小结

本章介绍了怎样跟踪单个进程的CPU性能瓶颈。学会了确定一个应用程序消耗的时间是如何分配到Linux内核、系统库甚至于该应用程序本身的。还学会了怎样找出哪些调用是对内核的哪些是对系统库的以及完成它们分别花了多少时间。最后学习了如何剖析应用程序确定源代码的哪个特定行消耗了大量的时间。掌握了这些工具之后就可以启动独占CPU的应用程序并利用这些工具准确地找出消耗了所有时间的那些函数。

后续章节将研究如何发现那些不受CPU约束的瓶颈。特别是将学习到用于发现诸如饱和磁盘或超载网络的I/O瓶颈的工具。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: linux