Linux Performance

    科技2025-07-28  14

    性能专家Brendan Gregg的网站。

    Linux性能

    该页面链接到我创建的各种Linux性能材料,包括右侧的工具图。它们使用大字体来适合滑盖。您也可以将它们打印出来用于办公室墙壁。它们显示:Linux可观察性工具, Linux静态性能分析工具, Linux基准测试工具, Linux调整工具和Linux sar。在图像上检查年份(右下)以查看年份。

    还有一个高分辨率图,它结合了可观察性,静态性能调整和perf-tools / bcc:png,svg(请参见讨论),但是它不如其他图完整。有关更多图表,请参见下面的幻灯片。

    2020年7月18日:我有一本新书出版:《系统性能:企业与云》第二版(2020),其中以Linux为例。

    http://www.brendangregg.com/linuxperf.html

     

    文献资料

    60,000毫秒内的Linux性能分析显示了调查中要使用的前十个命令(视频,PDF)。由我本人和Netflix的性能工程团队撰写(2015年)。我的文章《 EC2上的性能调整Linux实例》包含了我们在Netflix(2015)上使用的可调参数。关于Linux平均负载:解决奥秘的文章,解释了它们是什么以及为什么它们包括不间断的睡眠状态(2017)。一个gdb调试完整示例(教程),其中包括一些perf / debugging工具的使用(2016年)。《BPF性能工具:Linux系统和应用程序可观察性》一书概述了传统的Linux性能工具(iostat(1),perf(1)等)以及新的BPF工具。使用perf和eBPF在Linux上生成火焰图: CPU火焰图非CPU火焰图内存火焰图

     

    Java

    我在JavaOne 2016上发表的带有火焰图的Linux上的Java性能分析总结了使用Linux性能来生成混合模式火焰图的最新技术。

    背景

    为了生成火焰图,您需要一个可以对堆栈轨迹进行采样的探查器。历史上有两种类型的探查器:

    系统分析器:类似于Linux性能,它显示系统代码路径(例如JVM GC,系统调用,TCP),但不显示Java方法。JVM探查器:如hprof,LJP和商业探查器。这些显示Java方法,但通常不显示系统代码路径。

    可以如前所述执行使用(1)的火焰图。(2)取决于您要使用的探查器。火焰图软件包括stackcollapse-ljp.pl,用于处理轻量级Java Profiler(LJP)的输出。我的博客文章Java Flame Graphs总结了如何使用LJP。如果创建系统火焰图(例如,在Linux上使用perf)以及LJP火焰图,则通常可以通过同时检查所有问题来解决所有问题。

    理想情况下,我们有一个火焰图可以完成所有工作:系统和Java代码路径。除了方便之外,它还显示了Java上下文中的系统代码路径,这对于正确理解概要文件至关重要。

    问题是让系统分析器了解Java方法和堆栈跟踪。例如,如果您尝试使用Linux perf_events,您将看到十六进制数字和中断的堆栈跟踪,因为它无法将地址转换为Java符号,也无法遍历JVM堆栈。DTrace长期以来一直支持jstack()操作,但是它也存在问题,稍后将进行介绍。

    有两个特定的问题:

    JVM即时编译方法(即时:JIT),并且不公开传统的符号表供系统分析器读取。JVM还使用帧指针寄存器(x86-64上的RBP)作为通用寄存器,打破了传统的堆栈遍历。

    Linux perf_events

    解决上述两个问题的一种方法涉及:

    JVMTI代理perf-map-agent(以前在此处),可以提供Java符号表供perf读取(/tmp/perf-PID.map)。-XX:+ PreserveFramePointer JVM选项,因此perf可以遍历基于帧指针的堆栈。

    + PreserveFramePointer已添加到JDK8u60中,以方便生成性能图和火焰图(我已将原型通过电子邮件发送到热点编译器devs邮件列表,一个用于堆栈分析的热点补丁(框架指针),其变为JDK-8068945:使用RBP寄存器作为在x64上的JIT编译代码中正确的帧指针)。我在Netflix Tech博客上总结了最后的步骤:Java in Flames。以下是更新的步骤:

    1.安装perf-map-agent:

    须藤bash apt-get install cmake 导出JAVA_HOME = /您的新jdk8路径 cd / destination-for-perf-map-agent#我使用/ usr / lib / jvm git clone --depth = 1 https://github.com/jvm-profiling-tools/perf-map-agent cd perf-map-agent cmake。 使

    2.轮廓分析和火焰图生成:

    git clone --depth = 1 https://github.com/brendangregg/FlameGraph 须藤bash 性能记录-F 49 -a -g-睡眠30; ./FlameGraph/jmaps 性能脚本> out.stacks01 猫out.stacks01 | ./FlameGraph/stackcollapse-perf.pl | grep -v cpu_idle | \ ./FlameGraph/flamegraph.pl --color = java --hash> out.stacks01.svg

    请注意,jmaps(调用perf-map-agent进行符号转储的帮助程序脚本)在perf记录后立即运行,以最大程度地减少符号流失。

    生成的火焰图示例为(SVG,支持单击缩放):

     

    当运行flamegraph.pl时,我使用了--color = java,它对不同类型的帧使用不同的色调。绿色是Java,黄色是C ++,橙色是内核,红色是其余部分(本机用户级别或内核模块)。

    当前这是一个概念证明,并且不支持该修补程序。有关讨论和状态,请参阅邮件列表,有关此方法的注意事项。返回帧指针的确会花费一些性能(取决于工作量,它可以忽略不计),并且Flame图未显示内联方法。我希望该修补程序作为可调选项包括在内,例如-XX:+ NoOmitFramePointer。

    DTrace

    DTrace使用其jstack()操作,可以对用户级堆栈以及Java方法和类进行概要分析。(理论上:请参见下面列出的错误。)其使用的功能称为“ DTrace ustack助手”(搜索该术语以了解更多信息)。因此,要为Java程序生成CPU火焰图,可以使用以下命令收集堆栈:

    #dtrace将-n“轮廓-97 / execname == “Java”的/ {@ [jstack(100,8000)] =计数(); } tick-30s {exit(0); }'-o out.javastacks_01

    然后可以将输出文件输入到stackcollapse.pl和flamegraph.pl中,如前面的部分所示。

    ustack helper动作是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版本中根本不起作用。有关列表,请参见错误JDK-7187999。幸运的是,对于第一个问题,有一个解决方法,请参见Adam的电子邮件和illumos问题3123中所述,并且最终用法(自他的原始建议以来已更改)涉及在启动Java程序时设置环境变量,从而确保了ustack帮助器已加载。例如:

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

    请注意,这可能会增加60秒钟以上的启动时间。(这本身需要性能分析。)

    看到的火焰图为SVG或PNG。工作负载为ttcp(测试TCP),这是用Java编写的TCP基准测试。火焰图显示,大多数CPU时间都用在socketWrite()中,而9.2%用在releaseFD()中。

    第二个问题是jstack()可能由于2005年提交的JDK-6276264错误而无法正确遍历堆栈,而自2014年以来尚未修复。对于我的生产工作负载,由于此错误,几乎所有采样的堆栈都损坏了。jstack()不可用。

     

    常用的性能优化的工具图

    参考:https://www.yuque.com/buermuzi/qz84xg/eltckw

     

    Processed: 0.008, SQL: 8