关于服务器:性能优化之OnCPU

43次阅读

共计 12829 个字符,预计需要花费 33 分钟才能阅读完成。

CPU Flame Graphs

确定 CPU 忙的起因是性能剖析的惯例工作,这通常波及剖析堆栈跟踪。以固定速率采样剖析是查看哪些代码门路是热门代码(On-CPU)的毛糙但无效的办法。它通常通过创立一个工夫中断来收集以后程序计数器、函数地址或整个堆栈回溯,并将这些中断转换为可读的摘要报告。

剖析数据可能长数千行,难以了解。火焰图是采样堆栈跟踪的可视化成果,可疾速辨认热代码门路。无关 CPU 剖析以外的此可视化成果的应用,请参阅 Flame Graphs 主页。

火焰图可与任何操作系统上的任何 CPU 探查器一起应用。我的示例应用 Linux perf_events、DTrace、SystemTap 和 ktap。无关其余探查器示例,请参阅 Updates 列表; 无关火焰图软件,请参阅 github。

在此页面上,我将介绍和解释 CPU 火焰图,列出创立它们的通用阐明,而后探讨特定语言的生成。

目录:

  1. Problem
  2. Flame Graph
  3. Description
  4. Instructions
  5. Examples
  6. C
  7. C++
  8. Java
  9. Node.js
  10. Other Languages
  11. Other Uses
  12. Background
  13. References
  1. Problem

在这里,我应用 Linux perf_events(又名 “perf” 命令)来剖析正在耗费 Cpu 的 bash 程序:

perf record 命令以 99 赫兹(-F 99)采样,在咱们的指标 PID(-p 13204)上采样,并捕捉堆栈跟踪(-g –),用于调用图形信息。

perf report 命令在将数百个堆栈跟踪样本汇总为文本。相似的代码门路是一起,摘要显示为树形图,每个叶上都有百分比。从左上到右下读取门路,该门路遵循代码门路的先人(及其堆栈跟踪示例)。百分比必须相乘,以确定残缺堆栈跟踪的相对频率。

显示的第一个堆栈 do_redirection_internal())仅占样本的 2%。下一个堆栈跟踪(execute_builtin_or_function(),1%。因而,在浏览了这个文本屏幕后,咱们只能占到样本的 3%。为了理解 CPU 的大部分工夫破费在哪里,咱们心愿理解超过 50% 的代码门路。咱们可能须要做更多的浏览。

Too Much Data

上述输入已被截断,仅显示超过 8,000 行输入中的 45 行。可视化的残缺输入如下所示:

你能看到后面两个堆栈吗?他们在左上角。(Other versions: text, larger JPG.)

有时,CPU 工夫的大部分位于单个代码门路中,perf 报表在单个屏幕上轻松汇总此内容。然而,您通常须要浏览许多屏幕全文能力理解配置文件,这既耗时又乏味。

  1. The Flame Graph

当初,咱们用火焰图显示雷同数据:

如果您的浏览器中遇到问题,请尝试间接 SVG 或 PNG 版本。

应用火焰图时,所有数据都同时在屏幕上,最热的代码门路作为最宽的函数立刻不言而喻。

  1. Description

我会认真解释这一点:它可能看起来相似于来自探查器的其余可视化成果,但它是不同的。

  • 每个框示意堆栈中的函数(a “stack frame”)。
  • y 轴显示堆栈深度(number of frames on the stack)。顶部框显示 on-CPU 的函数。上面是先人函数。函数下方的函数是它的父函数,就像后面显示的堆栈跟踪一样。(某些火焰图实现偏向于反转程序并应用 ” 冰柱布局 ”,因而火焰看起来颠倒过去。
  • x 轴逾越样本总体。它不显示工夫从左到右的传递 ,就像大多数图形一样。 从左到右排序没有意义(按字母程序排序以最大化帧合并)。
  • 框的宽度显示它在 On-CPU 或 On-CPU 的先人的一部分的总工夫(基于样本计数)。具备宽框的函数在执行时可能比应用窄框的函数耗费更多的 CPU,或者,它们可能只是被调用更频繁。未显示呼叫计数(或通过采样已知)。
  • 如果多个线程同时运行和采样,样本计数可能会超过已用工夫。

火焰图色彩不固定,通常随机筛选为寒色(反对其余有意义的调色板)。此可视化成果称为 ” 火焰图 ”,因为它首次用于显示 CPU 上的热内容,并且,它看起来像火焰。它也是交互式的:鼠标悬停在 SVG 上以显示细节,而后单击以缩放。

./flamegraph.pl –color=io –title=”Off-CPU Time Flame Graph” –countname=us

  1. Instructions

火焰图 FlameGraph tool 工具和阐明的代码在 github 上。这是一个简略的 Perl 程序,输入 SVG。它们分三个步骤生成:

1.  Capture stacks
2.  Fold stacks
3.  flamegraph.pl

第一步是应用您抉择的探查器。无关应用 perf、DTrace、SystemTap 和 ktap 的一些示例,请参阅下文。

第二步生成基于行的输入文件便于 flamegraph.pl 读取,也能够进行 grep’d 以筛选感兴趣的函数。有一组简略的 Perl 程序来做到这一点,名为 stackcollapse*.pl,用于解决来自不同探查器的输入。

perf

Linux perf_events 具备多种性能,包含 CPU 采样。应用它来采样所有 CPU 并生成火焰图:

# git clone https://github.com/brendangregg/FlameGraph  # or download it from github
# cd FlameGraph
# perf record -F 99 -a -g -- sleep 60
# perf script | ./stackcollapse-perf.pl > out.perf-folded
# ./flamegraph.pl out.perf-folded > perf-kernel.svg

perf record 命令在所有 CPU(-a)上以 99 赫兹(-F 99)的速度采样,捕捉堆栈跟踪,以便当前能够生成函数先人的调用图(-g)。示例保留在 perf.data 文件中,由 perf script 读取。

我创立两头文件 perf-folded,使其在从同一数据创立多个过滤火焰图时速度更快一些。例如:

# perf script | ./stackcollapse-perf.pl > out.perf-folded
# grep -v cpu_idle out.perf-folded | ./flamegraph.pl > nonidle.svg
# grep ext4 out.perf-folded | ./flamegraph.pl > ext4internals.svg
# egrep 'system_call.*sys_(read|write)' out.perf-folded | ./flamegraph.pl > rw.svg

解决 perf report 的后果会更有效率一点; 更好的是,perf report 能够有一个报表款式(例如,“- g 折叠 ”),间接输入折叠堆栈,无需 stackcollapse-perf.pl。甚至有一个间接输入火焰图 SVG 的 perf 模式,不过,这将错过可能批改折叠堆栈的价值。

For more details, see my perf_events Flame Graphs page.

DTrace

DTrace 可用于在反对它(Solaris、BSD)的零碎上对 CPU 上堆栈跟踪进行配置文件。上面的示例应用 DTrace 为名为 ”mysqld” 的过程以 99 赫兹对用户级堆栈进行采样,而后生成火焰图(请参阅稍后的 MySQL 示例):

# git clone https://github.com/brendangregg/FlameGraph  # or download it from github
# cd FlameGraph
# dtrace -x ustackframes=100 -n 'profile-99 /execname =="mysqld" && arg1/ {@[ustack()] = count();} tick-60s {exit(0); }' -o out.stacks
# ./stackcollapse.pl out.stacks > out.folded
# ./flamegraph.pl out.folded > out.svg

两头文件 out.folded 是没有必要的,因为 stackcollapse.pl 的输入能够间接通过管道传递给 flamegraph.pl。然而,有些状况下,如果想应用 vi 编辑文件(例如,在采样内核时,要查找和删除闲暇线程)就很不便。

要解释 ”arg1″ 查看:arg1 是 user-land 程序计数器,因而确认它是非零的;arg0 是内核。以下是用于测试内核的 DTrace 命令示例:

# dtrace -x stackframes=100 -n 'profile-199 /arg0/ {@[stack()] = count();} tick-60s {exit(0); }' -o out.stacks

这一次,所有线程都进行采样,因而输入将蕴含许多闲暇线程样本(您能够应用 DTrace 筛选它们,也能够应用 grep/vi 筛选折叠的输入)。速率也减少到 199 赫兹,因为捕捉内核堆栈比用户级堆栈便宜得多。奇数编号的速率 99 和 199 用于防止与其余流动统一采样并产生误导性后果。

SystemTap

SystemTap 还能够通过 timer.profile 探测器对堆栈跟踪进行采样,该探测器以零碎时钟速率(CONFIG_HZ)。与将示例转储到文件以进行当前聚合和报表的 perf 不同,SystemTap 能够在内核中执行聚合,并把小得多报告传递给 user-land。收集的数据和生成的输入能够通过其脚本语言进一步自定义。

在 Fedora 16 上应用 SystemTap v1.7 生成火焰图:

 # stap -s 32 -D MAXBACKTRACE=100 -D MAXSTRINGLEN=4096 -D MAXMAPENTRIES=10240 \
   -D MAXACTION=10000 -D STP_OVERLOAD_THRESHOLD=5000000000 --all-modules \
   -ve 'global s; probe timer.profile {s[backtrace()] <<< 1; } 
   probe end {foreach (i in s+) {print_stack(i);
   printf("\t%d\n", @count(s[i])); } } probe timer.s(60) {exit(); }' \
   > out.stap-stacks
 # ./stackcollapse-stap.pl out.stap-stacks > out.stap-folded
 # cat out.stap-folded | ./flamegraph.pl > stap-kernel.svg

下面应用了六个选项(-s 32,-D…)减少了各种 SystemTap 限度。火焰图惟一真正须要的是 ”-D MAXBACKTRACE=100 -D MAXSTRINGLEN=4096″,这样堆栈轨迹不会截断; 在忙碌工作负载上长时间采样(本例中为 60 秒)时,须要其余采样,以防止各种阈值和溢出谬误。

应用 timer.profile 探针,以 100 赫兹对所有 CPU 进行采样:有点毛糙,并冒着 lockstep 采样的危险。上次我查看时,计时器.hz(997)探头以正确的速率发射,但无奈读取堆栈回溯。

ktap

ktap 曾经通过 ktap 的 scripts/profiling/stack_profile.kp 脚本反对 CPU 火焰图,该脚本捕捉示例数据。上面是应用 ktap one-liner 而不是该脚本的步骤:

# ktap -e 's = ptable(); profile-1ms { s[backtrace(12, -1)] <<< 1 }
  trace_end {for (k, v in pairs(s)) {print(k, count(v), "\n") } }
  tick-30s {exit(0) }' -o out.kstacks
# sed 's/    //g' out.kstacks | stackcollapse.pl > out.kstacks.folded
# ./flamegraph.pl out.kstacks.folded > out.kstacks.svg

sed(1)命令删除制表符(这是制表符,而不是一系列空格),stackcollapse.pl 解决文本。一 stackcollapse-ktap.pl 能够轻松地编写到间接解决 ktap 输入,并防止对 sed(1)的须要。

This full example is on my ktap page under ktap Flame Graphs.

Other Profilers

无关其余探查器,请参阅 Flame Graphs 主页上的更新链接。其中包含戴夫·帕切科的 node.js functions,马克·普罗布斯特的 OS X 上的 Flame Graphs for Instruments,以及布鲁斯·道森在微软 Windows 上的 Summarizing Xperf CPU Usage with Flame Graphs。

  1. Examples

下一个示例应用 DTrace 剖析 MySQL,而后应用 DTrace 剖析 Linux 内核的两个 CPU perf_events。这些是不反对单击缩放的旧示例(您依然能够按鼠标悬停查看详细信息)。

Linux 示例是在 KVM(Ubuntu 主机)下运行的 3.2.9(Fedora 16 来宾)上生成的,并配有一个虚构 CPU。某些代码门路和采样比率在裸机上会大不相同:例如,网络不会通过 virtio-net 驱动程序进行解决。

MySQL

这是导致我创立火焰图的原始性能问题。这是一个生产 MySQL 数据库,耗费的 CPU 比心愿的要多。可用的探查器是 DTrace,我应用它频率计数 CPU 用户级堆栈:

# dtrace -x ustackframes=100 -n 'profile-997 /execname =="mysqld"/ {@[ustack()] = count();} tick-60s {exit(0); }'dtrace: description'profile-997 ' matched 2 probes
CPU     ID                    FUNCTION:NAME
  1  75195                        :tick-60s 
[...]
              libc.so.1`__priocntlset+0xa
              libc.so.1`getparam+0x83
              libc.so.1`pthread_getschedparam+0x3c
              libc.so.1`pthread_setschedprio+0x1f
              mysqld`_Z16dispatch_command19enum_server_commandP3THDPcj+0x9ab
              mysqld`_Z10do_commandP3THD+0x198
              mysqld`handle_one_connection+0x1a6
              libc.so.1`_thrp_setup+0x8d
              libc.so.1`_lwp_start
             4884

              mysqld`_Z13add_to_statusP17system_status_varS0_+0x47
              mysqld`_Z22calc_sum_of_all_statusP17system_status_var+0x67
              mysqld`_Z16dispatch_command19enum_server_commandP3THDPcj+0x1222
              mysqld`_Z10do_commandP3THD+0x198
              mysqld`handle_one_connection+0x1a6
              libc.so.1`_thrp_setup+0x8d
              libc.so.1`_lwp_start
             5530

此处显示了最初两个最常见的堆栈。最初一次是在 CPU 上采样 5,530 次,看起来是 MySQL 在做一些零碎状态内务治理。如果这是最热的,咱们晓得咱们有一个 Cpu 问题,兴许我应该去寻找可调性来禁用零碎统计数据。

问题是,大部分输入都从此屏幕截图中截断(”[…]”),并且(与 Linux perf 不同),DTrace 不打印百分比,因而您不确定这些堆栈真正重要多少。我依据样本总数(即 348,427)手动计算百分比,后果令我丧气的是,这两个堆栈仅代表不到 3% 的 CPU 样本。

雷同的 MySQL 配置文件数据,出现为火焰图:

您能够对元素进行鼠标悬停以查看百分比(但无奈单击缩放,因为这是旧版本),显示剖析数据中元素的频繁存在。您还能够独自查看 SVG 或 PNG 版本。

较早截断的文本输入将 MySQL 状态堆栈标识为最热。火焰图显示了事实:大多数时候真的是在 JOIN::exec。这指出了考察的方向:JOIN::exec,以及下面的性能,并导致问题失去解决。

File Systems

作为不同工作负载的示例,这显示了在存档 ext4 文件系统时 Linux 内核 CPU 工夫(SVG, PNG):

这显示了文件系统的读取以及内核 CPU 工夫破费的工夫。大多数内核工夫是在 sys_newfstatat() 和 sys_getdents():元数据工作作为文件系统的步行。sys_openat() 在右侧,因为关上文件要读取,而后是 mmap()d(查看 sys_getdents(),这些是按字母顺序排列的),最初页面有故障进入用户空间(请参阅左侧的 page_fault())。

而后,挪动字节的理论工作将用 user-land 中的 mmap’d 段的上(内核火焰图中未显示)。如果归档程序应用 read()零碎调用代替,此火焰图将看起来十分不同,并且具备较大的 sys_read()组件。

Short Lived Processes

对于此火焰图,我执行了短期过程工作负载,以查看内核工夫在创立中破费的工夫(SVG, PNG):

除了性能剖析之外,这也是学习 Linux 内核外部性能的一个很好的工具。

User+Kernel Flame Graph

此示例显示 illumos 内核虚拟机管理程序主机上的用户和内核堆栈(SVG, PNG):

您还能够查看独立的 SVG 和 PNG 版本。这显示了 qemu 线程 3 的 CPU 应用状况,即 KVM 虚构 CPU。包含用户和内核堆栈(DTrace 能够同时拜访这两个堆栈),零碎调用介于黑白灰色之间。

零碎(vcpu_enter_guest)是该虚构 CPU 在虚拟机内执行代码的中央。我更感兴趣的是左边的山,来查看 KVM 进口代码门路的性能。

  1. C

易于剖析,请参阅步骤阐明 Instructions。一个陷阱是,许多编译器(包含 gcc)不将帧指针寄存器作为编译器优化,这突破了基于帧指针的堆栈步走。这通常产生在通过 Linux 存储库装置的软件中,并且您的火焰图将失落塔。修复程序包含:

  • Recompile with -fno-omit-frame-pointer.
  • On Linux: install debuginfo for the software with DWARF data and use perf’s DWARF stack walker.
  1. C++

易于剖析,但可能会因为与 C 雷同的起因而蒙受堆栈跟踪损坏:请参阅 profiling C 局部。

  1. Java

我的 JavaOne 2016 应用火焰图在 Linux 上探讨 Java 性能剖析,总结了应用 Linux perf 生成混合模式火焰图的最新技术。

Background

为了生成火焰图,您须要一个能够采样堆栈轨迹的探查器。历史上有两种类型的探查器:

  1. System profilers: like Linux perf, which shows system code paths (eg, JVM GC, syscalls, TCP), but not Java methods.
  2. JVM profilers: like hprof, LJP, and commercial profilers. These show Java methods, but usually not system code paths.

能够应用(1)执行火焰图,具体方法如前所述。(2)取决于要应用的探查器。火焰图软件包含 stackcollapse-ljp.pl,用于解决 Lightweight Java Profiler (LJP)的输入。我的博客文章 Java Flame Graphs 总结了如何应用 LJP。如果创立零碎火焰图(例如,在 Linux 上应用 perf)以及 LJP 火焰图,通常能够通过查看两者来解决所有问题。

现实状况下,咱们有一个火焰图能够实现这所有:零碎和 Java 代码门路。除了不便之外,它还在 Java 上下文中显示零碎代码门路,这对正确理解配置文件至关重要。

问题是让零碎探查器理解 Java 办法和堆栈跟踪。例如,如果您应用 Linux 的 perf_events,你会看到十六进制数字和断开的堆栈跟踪,因为它无奈将地址转换为 Java 符号,并且无奈跟踪 JVM 堆栈。DTrace 长期以来始终反对 jstack()操作,但该操作也有问题,稍后将介绍。

有两个具体问题:

  1. The JVM compiles methods on the fly (just-in-time: JIT), and doesn’t expose a traditional symbol table for system profilers to read.
  2. The JVM also uses the frame pointer register (RBP on x86-64) as a general purpose register, breaking traditional stack walking.

Linux perf_events

解决上述两个问题的一种办法:

  1. A JVMTI agent, perf-map-agent (previously here), which can provide a Java symbol table for perf to read (/tmp/perf-PID.map).
  2. The -XX:+PreserveFramePointer JVM option, so that perf can walk frame pointer-based stacks.

将 PreserveFramePointer 增加到 JDK8u60 中,以不便 perf 和火焰图生成(我通过电子邮件发送了一个原型到热点编译器开发人员邮件列表,[A hotspot patch for stack profiling (frame pointer),该修补程序成为 JDK-8068945: Use RBP register as proper frame pointer in JIT compiled code on x64。我在 Netflix Tech 博客上总结了最初一步:Java in Flames。以下是更新的步骤:

  1. install perf-map-agent:

    sudo bash
    apt-get install cmake
    export JAVA_HOME=/path-to-your-new-jdk8
    cd /destination-for-perf-map-agent # I use /usr/lib/jvm
    git clone –depth=1 https://github.com/jvm-profil…
    erf-map-agent
    cmake .
    make

  2. profiling and flame graph generation:

    git clone –depth=1 https://github.com/brendangre…
    sudo bash
    perf record -F 49 -a -g — sleep 30; ./FlameGraph/jmaps
    perf script > out.stacks01
    cat out.stacks01 | ./FlameGraph/stackcollapse-perf.pl | grep -v cpu_idle | \
    /FlameGraph/flamegraph.pl –color=java –hash > out.stacks01.sv

请留神,jmap(调用 perf 映射代理执行符号转储的帮忙程序脚本)要在 perf 记录后立刻运行,以最大限度地缩小符号改变。

产生火焰图的示例是(SVG,反对点击缩放):

运行 flamegraph.pl 应用 –color=java,它应用不同的帧类型应用不同的色调。绿色为 Java,黄色 C ++,橙色为内核,红色为残余(本机用户级别或内核模块)。

这是目前的概念证实,并且不反对该修补程序。无关探讨和状态,请参阅邮件列表,以及无关此办法的注意事项。返回帧指针的确会破费一些性能(取决于工作负载,可能能够忽略不计),并且火焰图不显示内线办法。我心愿修补程序作为可调选项蕴含在内,例如 -XX:NoOmitFramePointer。

DTrace

DTrace 应用 jstack()操作能够剖析用户级堆栈以及 Java 办法和类。(In theory: see the bugs listed below.)它应用的性能称为 ”DTrace ustack helper”(搜寻该术语以理解无关它们理解更多信息)。因而,要为 Java 程序生成 CPU 火焰图,能够应用以下办法收集堆栈:

# dtrace -n 'profile-97 /execname =="java"/ {@[jstack(100, 8000)] = count();}
    tick-30s {exit(0); }' -o out.javastacks_01

而后,能够将输入文件 stackcollapse.pl 和 flamegraph.pl,如后面各节所示。

ustack 帮忙器操作是 jstack(),如果工作,您将有看起来像这样的堆栈:

libjvm.so`jni_GetObjectField+0x10f
libnet.so`Java_java_net_PlainSocketImpl_socketAvailable+0x39
java/net/PlainSocketImpl.socketAvailable()I*
java/net/PlainSocketImpl.available()I*
java/lang/Thread.run()V
0xfb60035e
libjvm.so`__1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHa...
libjvm.so`__1cCosUos_exception_wrapper6FpFpnJJavaValue_pnMmeth...
libjvm.so`__1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_n...
libjvm.so`__1cMthread_entry6FpnKJavaThread_pnGThread__v_+0x113
libjvm.so`__1cKJavaThreadDrun6M_v_+0x2c6
libjvm.so`java_start+0x1f2
libc.so.1`_thrp_setup+0x88
libc.so.1`_lwp_start
  9

请留神,它包含 libjvm 帧和类 / 办法:java/net/PlainSocketImpl.available()等。如果没有可见的类 / 办法,只有十六进制数字,则须要让 jstack()先工作。

可怜的是,这个办法有多个问题。首先,jstack()在许多 JVM 版本中都不起作用。无关列表,请参阅 bug JDK-7187999。侥幸的是,第一个问题有解决办法,在 Adam’s email 和 illumos issue 3123 中形容,最终的用法(自从他最后的倡议以来已更改)波及在启动 Java 程序时设置一个环境变量,以确保加载 ustack 帮忙程序。例如:

illumos# LD_AUDIT_32=/usr/lib/dtrace/libdtrace_forceload.so java myprog

请留神,这可能会减少超过 60 秒的启动工夫。(这自身须要性能剖析。)

将生成的火焰图视为 SVG 或 PNG。工作负载是 ttcp(测试 TCP),这是用 Java 编写的 TCP 基准。火焰图显示,大多数 CPU 工夫都花在套接字写入()中,9.2% 的工夫用于 releaseFD()。

第二个问题,jstack()可能无奈正确走堆栈,因为谬误 JDK-6276264,在 2005 年提交,截至 2014 年未修复。对于我的生产工作负载,简直所有采样堆栈都因为此 Bug 而损坏。jstack()无奈应用。

  1. Node.js

v8 与 Java 有相似的问题。现实状况下,咱们心愿应用一些探查器来采样系统代码门路和 v8 JavaScript 代码门路。

Linux perf_events

应用 perf_events(v8 选项 –perf_basic_prof 或 perf_basic_prof_only_functions)能够剖析 JavaScript 堆栈。请参阅我的博客 Node Flame Graphs on Linux。还有特雷弗·诺里斯的原始阐明 instructions,还有他的 example。

Here is an example Linux perf CPU flame graph (SVG):


这应用 –color=js 应用不同的色调:green == JS, aqua == built-ins, yellow == C++, red == system(本机用户级别和内核)。

My example here is little more than hello world, so there’s very little JavaScript (green frames) to be seen. Here’s a more interesting example.

DTrace

与 Java 一样,DTrace 采纳不同的办法,应用 ”ustack helper”。见戴夫·帕切科的 post,在那里他也演示火焰图。

  1. Other Languages

请参阅 Flame Graphs Updates 局部,并搜寻您感兴趣的语言。

  1. Other Uses

火焰图可视化实用于任何堆栈跟踪和值组合,而不仅仅是重叠具备 CPU 样本计数的跟踪,如上述值。例如,您能够跟踪设施 I/O、零碎调用、CPU 外事件、特定函数调用和内存调配。对于其中任何一个,能够收集堆栈跟踪以及相干值:计数、字节或提早。请参阅 Flame Graphs 页面上的其余类型的类型。

  1. Background & Acknowledgements

我出于必要而创立此可视化成果:我从各种不同的性能问题中提供了大量堆栈示例数据,须要疾速开掘这些数据。我首先尝试创立一些基于文本的工具来汇总数据,但收效甚微。而后,我想起了 Neelakanth Nadgir(另一个 Roch Bourbonnais 创立了并给我看)创立的定时可视化成果,并认为堆栈示例能够以相似的形式出现。Neel 的可视化成果看起来很棒,但跟踪每个函数条目和返回我的工作负载的过程对性能的影响太大。在我的状况下,更重要的是要有精确的百分比来量化代码门路,而不是工夫排序。这意味着我能够对堆栈(低开销)进行采样,而不是跟踪函数(高开销)。

第一个可视化工作,并立刻确定了 KVM 代码的性能改良(一些增加的性能比预期的老本更高)。从那以后,我屡次应用它进行内核和应用程序剖析,其他人也始终在宽泛的指标上应用它,包含节点.js 剖析。狩猎高兴!

  1. References

  • The Flame Graph page, and github repo
  • Linux perf_events wiki
  • The Unofficial Linux Perf Events Web-Page
  • The SystemTap homepage
  • My Linux Performance Checklist, which includes perf_events, SystemTap and other tools

See the Flame Graph: Updates section for other articles, examples, and instructions for using flame graphs on many other targets, including Ruby, OS X, Lua, Erlang, node.js, and Oracle.

正文完
 0