简介:本文以系统为中心,结合日常工作和用例,由浅入深地介绍了性能分析的一些方法和体会,希望对想了解系统性能分析的同学有所帮助。

作者|勿非

本文以系统为中心,结合日常工作和用例,由浅入深地介绍了性能分析的一些方法和体会,希望对想了解系统性能分析的同学有所帮助。

入门篇

资源角度

USE

产品跑在系统的各种资源上面,从系统资源的角度入门性能分析是个不错的选择,我们以业界知名大牛BranGregg的USE方法开始,USE特点就是简单有效适合入门,用Bran的话描述USE的效果:

Ifinditsolvesabout80%ofserverissueswith5%oftheeffort.

Utilization(U):,"onediskisrunningat90%utilization".大多数情况可以合理推测利用率高可能会影响性能

Saturation(S):,"theCPUshaveanaveragerunqueuelengthoffour".资源竞争的激烈程度

Errors(E).,"thisnetworkinterfacehashadfiftylatecollisions".Errors相对直观

CPU

的利用率

Saturation.可以是loadaverage,runqueuelength,schedlatency等

CPU利用率用top看下:

top-17:13:49up83days,23:10,1user,loadaverage:433.52,422.54,438.70Tasks:2765total,23running,1621sleeping,0stopped,34zombie%Cpu(s):23.4us,9.5sy,0.0ni,65.5id,0.7wa,0.0hi,1.0si,0.0st

CPU利用率拆分成了更细粒度的几部分:

us,sys,ni-对应un-niceduser,kernel,niceduser的CPU利用率

id,wa-对应到idle,iowait的比例,iowait本质上也是一种idle,区别在于对应cpu上有等待io的任务

hi,si-对应hardirq,softirq的比例

st-因为超卖等原因,hypervisor从该vm偷走的时间(todo:docker)

继续看loadaverage,3个数值分别对应到系统1/5/15分钟内的系统平均load,load是个比较模糊的概念,可以简单认为是对资源有需求的任务数,包括oncpu,runnable的任务,也包括等待IO及任意D状态的任务.load使用采样的方式,每隔5秒采样一样,越近的采样权重越大,这样从1/5/15的趋势可以看出系统压力的变化。

loadaverage:433.52,422.54,438.70

在这台128个CPU的机器上,loadavg看起来有些偏高,但是具体影响目前不得而知,性能低是相对具体目标而言的,load高只是现象,它可能相关也可能无关,但至少是值得注意的。

再看下dstat关于任务状态的统计:

run-对应到/proc/stat里面的procs_running,也就是runnable任务数

blk-对应到/proc/stat里面的procs_blocked,阻塞在I/O的任务数

实际上和loadavg没有本质区别,只是load模糊了runnable和D状态,同时load使用1/5/15分钟的力度,而dstat可以使用更细粒度,如果只看某一时间点用load,如果要观察长时间的变化使用dstat(/proc/stat)。

free-gtotalusedfreesharedbuff/cacheavailableMem:50319372301301Swap:000

更详细的信息可以直接去读/proc/meminfo:

sar-B111:00:16AMpgscank/spgscand/spgsteal/s%vmeff11:00:17:00:18:00:19

I/O

存储I/O的USE模型:

Utilization.存储设备的利用率,单位时间内设备在处理I/O请求的时间

Saturation.队列长度

%util-利用率.注意即使达到100%的util,也不代表设备没有性能余量了,特别地现在的SSD盘内部都支持并发.打个比方,一家旅馆有10间房,每天只要有1个房间入住,util就是100%。

svctm-新版iostat已经删掉

await/r_await/w_await-I/O延迟,包括排队时间

avgrq-sz-平均requestsize,请求处理时间和大小有一定关系,不一定线性

argqu-sz-评估queuesize,可以用来判断是否有积压

rMB/s,wMB/s,r/s,w/s-基本语义

资源粒度

当我们判断资源是否是瓶颈的时候,只看系统级别的资源是不够的,比如可以用htop看下每个CPU的利用率,目标任务运行在不同CPU上的性能可能相差很大。


​内存也有类似情况,运行numastat-m

Node0Node1Node2Node3------------------------------------------------------------(anon)6.630.932.085.64Inactive(anon)12635.7525560.5312754.299053.80Active(file)7573.95418.879595.375775.00Inactive(file)4445.521283.757052.704450.98
echo0-1/sys/fs/cgroup/cpuset/$uptime14:10:54up6days,18:52,10users,loadaverage:920.92,411.61,166.95

应用角度

系统资源和应用的性能可能会有某种关联,但是也可以更直接地从应用的角度出发定位问题:

应用能使用多少资源,而不是系统提供了多少资源,这里面可能会有gap,系统是个模糊的概念,而应用本身却相对具体.以上面cpuset为例,物理机是个系统,cpuset管理的资源也可以成为系统,但是应用在cpuset里面还是外面是确定的。

应用对资源的需求,即使系统资源再多,应用用不上性能也上不去,也就是系统可能没问题,而是应用本身的原因。

以下面的myserv为例,它的4个线程%cpu都达到了100,这个时候再去分析整个系统的load什么用处不大,系统有再多的空闲cpu对myserv来说已经没有意义。

perflist|grepHardwarebranch-misses[Hardwareevent]bus-cycles[Hardwareevent]cache-misses[Hardwareevent]cache-references[Hardwareevent]cpu-cyclesORcycles[Hardwareevent]instructions[Hardwareevent]L1-dcache-load-misses[Hardwarecacheevent]L1-dcache-loads[Hardwarecacheevent]L1-dcache-store-misses[Hardwarecacheevent]L1-dcache-stores[Hardwarecacheevent]L1-icache-load-misses[Hardwarecacheevent]L1-icache-loads[Hardwarecacheevent]branch-load-misses[Hardwarecacheevent]branch-loads[Hardwarecacheevent]dTLB-load-misses[Hardwarecacheevent]iTLB-load-misses[Hardwarecacheevent]mem:addr[/len][:access][Hardwarebreakpoint]

perf使用的时候一般会传入以下参数:

通过-e指定感兴趣的一个或多个event

指定采样的范围,比如进程级别(-p),线程级别(-t),cpu级别(-C),系统级别(-a)

这里使用默认的event看下进程31925的执行情况.一个比较重要的信息是insnspercycle(IPC),也就是每个cycle能执行多少指令,其他pmuevent像cachemisses,branchmisses如果有问题最终都会反映到IPC上.虽然没有一个明确的标准,但是下面0.09的IPC是比较低的,有必要继续深入。

2.180CPUsutilized3,210/cles-back409,465,681%

除了stat外,perf另一个可能更常用的方式是采样来确定程序的热点,现在有如下程序:

voidbusy(longus){structtimevaltv1,tv2;longdelta=0;gettimeofday(tv1,NULL);do{gettimeofday(tv2,NULL);delta=(__sec)*1000000+__usec;}while(deltaus);}voidA(){busy(2000);}voidB(){busy(8000);}intmain(){while(1){A();B();}return0;}

函数A和B执行时间的比例,perf的采样结果和我们期望的2:8基本一致。

perfreportSamples:27Kofevent'cycles',Eventcount(approx.):ChildrenSelfCommandSharedObjectSymbol+99.99%0.00%[unknown][.]0x0000fffffb925137+99.99%0.00%[.]_start+99.99%0.00%[.]__libc_start_main+99.99%0.00%[.]main+99.06%25.95%[.]busy+79.98%0.00%[.]%71.31%[vdso][.]__kernel_gettimeofday__kernel_gettimeofday-busy+79.84%B+20.16%A+20.01%0.00%[.]A

strace

trace相对于采样最大的优势在于精度,trace能抓住每次操作,这给调试和理解带来很大方便.strace专门用来trace系统调用。

strace通过捕获所有的系统调用能快速帮助理解应用的某些行为,这里使用strace来看下上面提到的perf-record的实现,很容易发现系统调用perf_event_open以及它的参数,因为有128个cpu,针对每个cpu都会调用一次该系统调用。

trace-cmdrecord-pfunction--func-stack-lgeneric_make_requestddif=/dev/zeroof=filebs=4kcount=1oflag=direct

通过report来查看就一目了然了:

[69439]|main(){[69439]|A(){0.160us[69439]|busy();1.080us[69439]|}/*A*/[69439]|B(){0.050us[69439]|busy();0.240us[69439]|}/*B*/1.720us[69439]|}/*main*/

BPF

BPF(eBPF)是这几年的热点,通过BPF几乎可以看清系统的各个角落,给诊断带来了极大的方便.BPF不是一个工具,BPF是生产工具的工具,BPF工具编写是性能分析必须掌握的技能之一。

这里举个使用BPF来分析QEMUI/O延迟的例子.为了简化问题,先确保vm里面的块设备只有fio在使用,fio控制设备只有一个并发I/O,这样我们在host上选择2个观察点:

tracepoint:kvm:kvm_捕获guestmmio操作,guest里面最终通过写该mmio发送请求给host

kprobe:kvm_set_msi.因为guest里面vdb使用msi中断,中断最终通过该函数注入

vbdmmio对应的gpa,这个可以在guest里面通过lspci获得

对于kvm_set_msi,使用如下信息:

structkvm的userspace_pid,structkvm对应的qemu-kvm进程

structkvm_kernel_irq_routing_entry的,对应到pci设备id

include"kernel/sched/"kprobe:calc_global_load_tick/cpu==0/{$rq=(structrq*)arg0;@[$rq-calc_load_update]=count();}interval:s:5{print(@);clear(@);}

执行结果符合预期:

1safterupdatingloadbreak;{0..63};do./busy3sar-B111:00:16AMpgscank/spgscand/spgsteal/s%vmeff11:00:17:00:18:00:19

先看sysstat(sar)里面的实现,主要是读取分析/proc/vmstat:

pgscand:对应到pgscan_direct域

pgscank:对应到pgscan_kswapd域

pgsteal:对应到pgsteal_开头的域

greppgsteal_/proc/vmstatpgsteal_kswapd168563pgsteal_direct0pgsteal_anon0pgsteal_%Mountedoncgroup000-/sys/fs/cgroup/memory#grep-c'pgscan\|pgsteal'

这些统计信息在cgroupv1上完全没有输出,而只在v2版本有输出.在以前内核没有专门LRU_UNEVICTABLE的时候,如果有很多比如mlockpage的时候,碰到过不停扫描却不能回收内存的情况,这个统计会非常有用,即使是现在我相信这个统计还是有用的,只是大部分时候还不用看到这么细。

多上手

纸上得来终觉浅,自己动手去做带来很多好处:

回答预设问题.调试分析就是不断提出问题和验证的过程,没有上手的话就会一直停留在第一个问题上.比如我想了解某平台上物理内存是怎么编址的,没有文档的话只能自己去实验

提出新的问题.调试分析中不怕有问题,怕的是提不出问题

会有意外收获.很多时候并不是有意为之,比如准备的是分析cpu调频能否降功耗,上去却发现系统一直运行在最低频率

熟练.熟练就是效率

改进产品.可以试想下在整个云环境所有机器上扫描(类似全面体检)会发现多少潜在问题

参考资料

[1]

[2]

[3]

[4]

[5]

[6]

[7][8]TheArtofComputerSystemsPerformanceAnalysis

原文链接:301MovedPermanently

本文为阿里云原创内容,未经允许不得转载。