火焰图追踪项目报告
1. 项目概述:
通过Linux火焰图来检测程序占用CPU过高的实际具体问题。
通过Linux火焰图来找出占用CPU过高的具体线程使用的函数。并加以分析,交给开发人员,进行具体函数优化,数据结构优化。
适用于系统CPU占用率过高,系统出现问题,运维人员进行具体进程、线程、函数分析。
2. 项目人员及分工:
项目负责人:金X
项目开发人员:周x、迟xx
运维人员:金x、陈xx
- 技术实现
1.由开发人员进行编写源代码
2.有开发人员实现在Linux系统上运行源代码程序
3.由运维人员对进程实施监控追踪,查询有问题进程的具体函数,并生成火焰图
4.由运维人员对火焰图进行分析,对出现问题函数进行具体汇报
- 项目报告
一、技术实现报告:源代码生成部分
通过LINUX火焰图检测程序占用CPU占用率过高的问题代码思路:
源代码展示
设计构想
使用for循环创建一个非常大的二维整数数组(理论构想数组大小为1000000000*10000000000 但是大了会造成系统瘫痪 ,无法进行数据分析,太小cpu占用率无法具体显现,所以需要具体尝试找到一个合适的区间值),并尝试在控制台上打印出数组的内容。最后确定数组的大小为14595x14595,这是一个非常大的数组,从而占用大量的内存空间。
Ps:虽然别看他是一个简单的利用for循环的数组代码,但是他是简单高效的占用大量CPU 内存的方法
为何不把他转换为exe应用程序而是直接使用java代码
1、首先文件格式不同,Windows下的EXE是PE格式(64位版本叫PE32+),而Linux下的可执行程序是ELF32或ELF64格式的。在Linux下面运行EXE,系统会尝试以ELF格式解析PE文件,显然不会成功。
2、除此之外,系统调用的接口也不同。32位的Linux使用0x80软中断,64位的Linux采用汇编指令syscall,同时还定义了一套专门的调用约定(calling convention)。Windows没有公开NT内核的系统调用规范,而是用WIN32 API进一步封装,用户程序通过系统的DLL访问系统功能。在不同版本的NT内核之间,系统调用接口可能都是不一致的,更不要说NT和Linux之间的区别了。
3、除了文件格式以及系统调用,还有一个关键区别就是共享库。Linux下称作shared object,Windows下简称DLL。一个可执行文件可能需要很多共享库才能运行,例如Windows下的msvcrt.dll。共享库是操作系统提供的,动态链接也是操作系统负责,不同系统的行为各不相同。
如果你就是想在Linux上运行.exe文件提供以下方法:
在Linux下运行EXE,最有名的解决方案是wine(Wine Is Not an Emulator)。既然Windows不公开系统调用,完全通过win32 API访问内核功能,那么只要使用Linux的系统调用提供一套新的win32 API实现,就能让EXE跑在Linux中了,毕竟接口都定义好了。wine另一个任务就是解析PE格式的文件,既然Linux不认识PE,那么就要添加一个内核模块,让内核能够识别并加载EXE,同时提供一套替代的系统DLL。
- 在Linux系统上运行源代码程序
由于java代码转换成exe文件无法在linux系统中运行,所以需要直接在linux系统中运行java代码。
首先把java代码文件上传到linux系统中,但是由于linux系统自带的java环境无法运行所以我重新配置了一个java环境,然后通过配置好环境自带的jps命令可以检测出系统能否正常执行Java进程。
其次通过javac这个指令来编译后缀名是 .Java的文件,会在当前目录下生成后缀名为.class的文件,执行javac这条命令后在当前的目录下有.class文件证明系统已经编译成功,反之javac命令执行有误。还需要我们进行一些配置上的更改。
最后通过java指令后加文件名(注意文件名不加任何文件后缀名)来执行java文件,Linux显示执行后的程序,证明我们的目的实现了,Java程序成功在Linux上运行了。但由于源代码程序过庞大无法运行,向系统征集调用的内存过多,会使系统直接报错,需要经过我们不断地调试并找到一个合适的临界值。通过这个临界值来修改源程序代码后进行查询追踪。
- 对进程实施监控追踪,查询有问题进程的具体函数,并生成火焰图
首先准备工作我们先将生成火焰图采集信息所需的perf工具安装到Linux系统。
指令为:yum install perf
Brendan D. Gregg 的 Flame Graph 工程实现了一套生成火焰图的脚本。Flame Graph 项目位于 GitHub上,但是GitHub网站在中国网络不太稳定,我们通过国内网站码云的链接实现了对工具的下载。
指令为:git clone Gitee 极速下载/FlameGraph
先将项目组内编写的Java源代码程序通过远程传输的方式将项目成员调试好的代码文件上传到Linux系统,通过javac来编译,通过java来执行项目源程序。
通过top命令来检测当前系统的各个进程,通过M来查看当前系统CPU过高的进程。运行项目代码后我们可以明显看到我们的java进程很吃CPU。
我们可以具体的看到我们java的进程号为37201.
之后我们通过已安装的perf来采集数据,它会返回 CPU 正在执行的函数名以及调用栈(stack)。
指令为:perf record -F 99 -p 37201 -g -- sleep 30
perf record 表示采集系统事件, 没有使用 -e 指定采集事件, 则默认采集 cycles(即 CPU clock 周期), -F 99 表示每秒 99 次, -p 37201 是进程号, 即对哪个进程进行分析, -g 表示记录调用栈, sleep 30 则是持续 30 秒。
为了便于阅读, perf record 命令可以统计每个调用栈出现的百分比, 然后从高到低排列。
指令为:sudo perf report -n --stdio
我们用 perf script 工具对自动生成文件 perf.data 进行解析,将解析出来的信息存下来, 供生成火焰图。
指令为:perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > process.svg
最后我们生成的.svg文件,便是我们的火焰图,可以通过浏览器进行打开。
- 对火焰图进行分析,对出现问题函数进行具体汇报
关于运行项目组内程序的火焰图分析查看到以下进程和函数可能出现问题:
do-futex进程表示一个正在执行的进程。do-futex是一个内核线程,主要负责处理进程间的同步操作
writeBytes进程表示一个正在写入数据的进程。writeBytes是操作系统中的一个内核线程,主要负责将数据从用户空间写入到内核空间的缓冲区或其他存储设备中。在火焰图中,writeBytes进程的出现通常意味着系统正在处理磁盘I/O操作,
libpthread-2.17.so进程表示系统正在调用该库中的线程相关函数。libpthread是一个共享库,提供了线程编程所需的基本功能,如线程创建、同步、互斥等。在火焰图中看到libpthread-2.17.so进程时,意味着有进程正在使用线程编程功能
Sysret_audit进程表示系统审计进程。Sysret_audit是Linux内核中负责审计功能的一个子系统,它主要用于记录和跟踪系统中的各种事件,如文件访问、进程创建和网络连接等。这些事件记录对于系统安全分析和故障排查具有重要意义。
VM_Periodic_Task进程表示系统中的定期任务进程。VM_Periodic_Task主要负责执行周期性的任务,如内存管理、文件系统整理等。这些任务通常在系统后台自动运行,对系统性能的影响较小。
- 项目总结
项目以达到预期成果,并超出预期成果,整体较为圆满。
由衷感谢项目内所有有实力且出色的组员,使得项目出色顺利得完成。