Linux性能优化--性能工具:特定进程CPU
4.0 概述
在用系统级性能工具找出是哪个进程降低了系统速度之后,你需要用特定进程性能工具来发现这个进程的行为。对此,Linux提供了丰富的工具用于追踪一个进程和应用程序性能的重要统计信息。
阅读本章后,你将能够:
- 确定应用程序的运行时间是花费在内核上还是在应用程序上。
- 确定应用程序有哪些库调用和系统调用,以及它们花费的时间。
- 分析应用程序,找出哪些源代码行和函数的完成时间最长。
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说明了这些统计数据的含义。
就像strace,ltrace有大量的选项可以修改其跟踪的功能。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瓶颈的工具。
相关文章:

Linux性能优化--性能工具:特定进程CPU
4.0 概述 在用系统级性能工具找出是哪个进程降低了系统速度之后,你需要用特定进程性能工具来发现这个进程的行为。对此,Linux提供了丰富的工具用于追踪一个进程和应用程序性能的重要统计信息。 阅读本章后,你将能够: 确定应用程…...

技术人员转岗产品经理,有优势吗?
产品经理是一个非技术型的岗位,但是懂一些技术相关的知识会更好的和技术部门沟通,能更好的从技术部门的角度理解需求的可行性。所以这么说来,技术转产品经理相对来说更加有优势。 任何事情不可能都是只有好处没有坏处的,同样的&a…...

使用IDEA2022.1创建Maven工程出现卡死问题
使用IDEA创建Maven工程出现卡死问题,这个是一个bug 这里是别人和官方提供这个bug,大家可以参考一下 话不多说,上教程 解决方案: 方案1:更新idea版本 方案2:关闭工程,再新建,看图...

Nuttx Syscall
在Nuttx系统中,mksyscall工具用于根据syscall/syscall.csv文件生成供用户调用的接口和内核中对应的接口。具体来说,mksyscall -p system.csv生成供用户调用的接口,而mksyscall -s system.csv生成内核中调用的接口。 在syscall/syscall.csv文…...

HTTP协议中GET请求和POST请求的区别
1. 形式上: GET请求:参数包含在URL中,意味着参数的长度是有限的,并且参数只能是ASCII码的形式。 POST请求:参数包含在请求体中,参数的长度是不受限,并且参数支持多种数据类型。 2.安全性 GET请…...

【广州华锐互动】利用VR开展施工现场安全培训,提高员工安全意识水平
随着科技的不断发展,虚拟现实(VR)技术已经逐渐渗透到各个领域,为我们带来了前所未有的沉浸式体验。在建筑施工行业,VR技术的应用也日益广泛,从设计、施工到管理,都可以看到VR技术的身影。而在这…...

Cornerstone for Mac:高效SVN管理的黄金标准
在当今的软件开发领域,版本控制系统是不可或缺的一部分。其中,Subversion(SVN)是一个广泛使用的版本控制系统,有助于团队协同工作,实现代码的版本管理和追踪。对于Mac用户来说,Cornerstone是一款…...

数据结构之顺序表的模拟实现
💕"世事犹如书籍,一页页被翻过去。人要向前看,少翻历史旧账。"💕 作者:Mylvzi 文章主要内容:数据结构之顺序表的模拟实现 /*** Created with IntelliJ IDEA.* Description:* User: 绿字* Date:…...

R6G azide, 5-isomer具有良好的水溶性,2135330-71-9
试剂 | 基础知识概述(部分): 英文名称:R6G azide, 5-isomer CAS:2135330-71-9 分子式:C30H32N6O4 分子量:540.61 规格标准:10mg,25mg,50mg,可提供mg级以…...

Canvas系列绘制图片学习:绘制图片和渐变效果
我们现在已经可以绘制好多东西了,不过在实际开发中,绘制最多的当然是图片了,这章我们就讲讲图片的绘制。 绘制图片 绘制图片的API是drawImage,它的参数有三种情况: // 将图片绘制在canvas的(dX, dY)坐标处 context.…...

AJAX为什么叫AJAX
AJAX(Asynchronous JavaScript and XML)这个名字是由美国程序员Jesse James Garrett在2005年提出的,用来描述一种用于创建交互式Web应用程序的技术组合。它之所以被称为"AJAX",有以下原因: Asynchronous&…...

自动化测试中如何编写配置文件 ? 该使用什么工具 ? 一文详解使用ConfigParser读写配置文件
1. 配置文件说明 只要是用编写项目,你就肯定离不开配置文件 。就以测试人员编写的自动化测试项目为例 ,如果你做连接数据库 、访问一些第三方接口、或者访问登录接口的用户名和密码。这些输入的信息最大特点就是都可能是变量,比如访问数据库…...

文件批量管理:轻松复制备份并删除原文件
在日常生活和工作中,我们经常需要处理大量的文件。为了确保文件的安全性和完整性,您需要一种高效的文件批量管理方法。本文将向您介绍如何一一复制备份并删除原文件里的文件,让您的文件管理变得轻松便捷。 首先,我们要进入文件批…...

Linux高性能服务器编程 学习笔记 第十七章 系统监测工具
tcpdump是一款经典的抓包工具,即使今天我们已经有了像Wireshark这样更易于使用和掌握的抓包工具,tcpdump仍是网络程序员的必备利器。 tcpdump提供了一些选项用以过滤数据包或定制输出格式,常见的选项如下: 1.-n:使用I…...

rabbitmq 消费者报错 ListenerExecutionFailedException NullPointerException
报错信息: org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Listener method private void com.xxx.service.impl.xxxServiceImpl.xxx(com.xxx.dto.XXX) threw exception at org.springframework.amqp.rabbit.listener.adapter.Mes…...

Java面试题:链表-合并两个排序的链表
描述 输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。 示例 输入: {1,3,5}, {2,4,6}返回值: {1,2,3,4,5,6}原题地址:https://www.nowcoder.com/practice/d8b6b4358f7742…...

Springboot结合Mockito写单元测试实践和原理
文章目录 前言一、使用最佳实践使用场景SpyBean失效场景解决Mock失效的问题避免FactoryBean的实现方式使用MockBean,但是要指定name 个人推荐 二、原理1. MockBean2.SpyBean方法调用 总结 前言 相信看我博客的都是javaer,工作中一般都是使用Springboot框…...

操作系统之微内核架构
宏内核相反,微内核架构提倡功能尽可能少,只提供进程调度、处理中断、内存映射、进程间通信等功能。微内核架构是不能够提供什么实际功能的,而内存管理、进程管理、设备管理和文件管理服务等,都被做成一个个服务进程,它…...

24---WPF缓存
一、什么是缓存: 1.缓存指的是将需要频繁访问的网络内容存放在离用户较近、访问速度更快的系统中,以提高内容访问速度的一种技术。缓存服务器就是存放频繁访问内容的服务器。 2.缓存就是一个临时存放区域--离用户比较近 二、作用--意义---如果系统出现故…...

vite+vue3.0 使用tailwindcss
参考资料: 安装 - TailwindCSS中文文档 | TailwindCSS中文网 npm install -D tailwindcss npm install postcss npm install autoprefixer npx tailwindcss init -p 生成/src/tailwind.config.js和/src/postcss.config.js配置文件 在/src/tailwind.config.js配置文件…...

C++QT---QT-day3
使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数将登录按钮使用qt5版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为&…...

小程序如何搭建在服务器上
小程序可以通过搭建在服务器上,来实现跨平台的访问和使用。以下是搭建小程序在服务器上的步骤: 安装Node.js:首先,你需要在服务器上安装Node.js。你可以从Node.js的官方网站下载并安装。 安装微信开发者工具:然后&…...

JavaEE初阶学习:Servlet
1.Servlet 是什么 Servlet 是一种 Java 程序,用于在 Web 服务器上处理客户端请求和响应。Servlet 可以接收来自客户端(浏览器、移动应用等)的 HTTP 请求,并生成 HTML 页面或其他格式的数据,然后将响应发送回客户端。S…...

黑白二维码不好看,那么快学习改色的方法吧
现在经常会看到很多的二维码不是黑白图案,可以是其他纯色或者渐变色等样式的,那么怎么将黑白二维码改成其他鲜艳好看的颜色呢?一般想要修改普通样式的二维码可以用二维码美化生成器来处理,只需要上传二维码图片,就可以…...

coreldraw2024版本有哪些新增功能?
有小伙伴在用电脑查找软件程序的时候,看到了一款叫cdr软件的应用,自己之前没接触过,不知道cdr是什么软件?cdr软件是干什么的?十分好奇。其实它是一款平面设计软件,下面就给大家介绍下相关的cdr软件的知识。…...

2023最新Office2021专业增强版安装使用教程
Microsoft Office专业增强版2021是一套办公软件套装,包含了Word、Excel、PowerPoint、Outlook、Access、Publisher、OneNote、Teams等应用程序。这个版本是在Office 365的基础上推出的新版本,与之前的Office版本相比,增强了许多功能。也是目前…...

实时配送跟踪功能的实现:外卖跑腿小程序的技术挑战
在当今数字化时代,外卖和跑腿服务已经成为了生活中不可或缺的一部分。为了提供更好的用户体验,外卖跑腿小程序越来越注重实时配送跟踪功能的实现。这项技术挑战旨在确保顾客可以方便地跟踪他们的订单,以及配送员可以高效地完成送货任务。本文…...

react实现一维表格、键值对数据表格key value表格
UI画的需求很抽象,直接把数据铺开,不能直接用antd组件了 上一行是name,下一行是value,总数不定,最后前端还要显示求和 class OneDimensionTable extends React.Component { render() {const { data } this.props;le…...

个人微信CRM客户管理系统怎么选?功能介绍
现在市面上有许多种类的个人微信CRM客户管理系统可供选择,因此,我们需要选择最适合自己需求的微信管理系统CRM,最重要的是根据您的需求和期望的功能来进行筛选。 如何选择适合自己的微信CRM客户管理系统? 现在市面上的系统五花八…...

Mac Intellij Idea get/set方法快捷键
Control Retrun(回车键) Command n 参考: Mac Intellij Idea get/set方法快捷键-CSDN博客...