linux系统单线程工作耗时性能解析

背景

工作中常常要解决大量的Linux系统下的性能问题。这些性能问题要想高效分析解决好,其中一个基础是要对单线程工作性能有个详细完善地分析思路,能部署一个详细地性能检查check list。

单线程性能影响因素分析

拿手机上用户执行zip解压缩操作为例,具体做zip解压缩工作的正好是文件管理器app的AsyncTask线程。该线程的工作耗时性能直接关系到手机解压缩的性能好坏。

而该线程的工作耗时分为oncputime + offcputime, 具体工作性能会受cpu ,内存和存储3大模块的影响,进行性能分析时,要考虑多方面的因素。

oncputime分析

oncputime分为user态和sys态,sys态耗时的话,跟系统调用次数过多,或者某次调用过于频繁有关。oncputime会有些无效运行时间,比如自旋锁需要注意。

影响oncputime的因素有:

1) cpu频率

手机里面有大小核,每个核的频率都不一样。并且在实际运行过程中,Android系统也会进行自动调频操作。cpu频率不一样,oncputime也会发生变化,所以要关注单线程整个on cpu阶段的实际频率变化状况。

2) task自身上下文switch次数

从内核态来看,task的switch动作会导致tlb被重新刷新,刚切换成功时,新task的页表和代码数据的cache miss也会增多。这些也都会影响到oncpu运行时间。

3) task运行时的cpu cache miss次数

cpu cache miss增加时,程序就会多花时间进行内存的读操作了。

举个例子:比如slab内存区域碎片增多时,那么如果该区域存放有程序需要遍历的链表数据,那么进行大量的链表遍历操作时,cpu cache miss就会增多,链表遍历就会耗时了。

offcputime分析

offcputime其实也是影响单线程工作性能的主要因素。

排除程序中需要主动睡眠的时间外,下来这个offcpu分析其实就是延迟分析了。延迟分析包括两类:程序自身因素导致的延迟和系统因素导致的延迟。

程序自身因素导致的延迟有:

1) IOwait导致的延迟

程序中如果涉及到读写磁盘操作时,就会有IOwait时间出来。该部分时间目前是不会算到cpu idle状态里面的。

IOwait耗时除了跟存储硬件自身的处理性能有关外,也跟系统的存储软件栈有关,比如内核文件系统或者块设备层某方面架构设计有缺陷,导致实际发往存储硬件的IO请求狂多,

也会导致IO wait时间增大。

2) 一些任务同步锁导致的延迟

比如内核里面的一些睡眠锁的调用,也会导致off cputime增加。

系统因素导致的延迟:

1) 系统内R状态的进程数目多以及待测试线程的优先级低

系统内如果R状态进程数目多的话,会导致系统的cpu资源成为瓶颈。这样单线程的非主动上下文切换(nonvoluntary context switch)就会比较频繁,同时task在cpu队列里面的runable排队待运行时间也会增多。

如果待测试线程的进程优先级本来就比较低的话,前面两个性能指标会更加恶化。

2) cpu调度算法

这个cpu调度算法不好的话,也会导致task在cpu队列里面的runable时间增多。

3) 系统内处于D状态 IOwait的进程数目多

这个会导致磁盘工作繁忙,如果系统用的是cfq或者bfq调度器的话,平均到每个task的IO 服务时间就会变少。

4) 系统的内存回收和内存压力状况

系统有内存压力时,具体表现为可用内存不足,内存回收线程kswapd0会比较活跃。此时task申请不到可用内存页时,就会被迫睡眠等待,增加了task的睡眠时间。

系统内存回收方面,如果内存回收过于激进或者频繁,那么task在进行读文件操作时,会发现大部分文件页都不在pagecache中(已经被回收掉了),所以导致读磁盘文件页次数增多,

这样也会带来offcputime增大。

单线程性能问题解决效率提升

分析完上面影响性能的一些因素后,下来开始解决实际性能问题了。

性能问题的影响因素是很多,而且每次复测时,影响因素都不一样,从而导致每次复测,所产生的性能数据也会有些波动变化,进而使得性能问题并不是每次复测都会出现的。

为了减少复测次数,尽量缩短性能问题的定位时间,针对工作中常碰到的手机zip解压缩性能问题,我做了如下性能问题解决方法总结,正好zip解压缩性能问题正是上面我说的单线程(文件管理器app的AsyncTask线程)工作性能问题。

单线程工作性能问题解决分成两步:

1:首先要对性能测试产生的trace信息进行详细分析。

在进行性能测试时,要给足对应的trace信息。这样进行一次测试,便能根据trace信息,来定位出性能问题是受上面我列出的哪些因素影响的。

以解压缩性能问题定位为例,

做解压缩测试时,要提供测试现场对应的systrace信息和bugreport信息,还要提供解压缩前后的解压缩工作线程的taskstat信息。

systrace信息

通过systrace,可以看到如下影响性能的因素:

1) 解压缩线程的cpu大小核切换状况,task上下文切换频繁程度。

2) 具体解压缩执行时对应的cpu 频率变化状况,整体上on  cputime和off cputime分布,offcputime中由于IO因素导致的耗时分布,进入D状态睡眠的原因都有哪些。

3) 块设备层的IO特性,比如发往存储芯片的每个IO请求大小,总的请求数目及存储芯片处理耗时。

4) 文件系统层的文件页读写特点,比如读的所有文件页中冷页数目和热页数目各自是多少。冷页pagecache中没有,需要花费从磁盘读数据的操作,这样会影响性能。热页直接从pagecache中读即可。

5) 解压缩工作对应的oncputime和offcputime耗时数据。

bugreport信息

通过bugreport,可以看到如下影响性能的因素:

1) 大概知道做性能测试时的手机存储老化状况。

2) 做性能测试时内存压力, cpu压力状况。

3) 做性能测试时,后台有无app在跑,有多少这样app在跑。

4) zip解压缩log中对应的实际耗时信息。

taskstat信息

通过Android代码包里面的system/extras/taskstats工具(该工具可以实时地显示出内核里面task的运行详细状况),可以精确地抓到如下影响性能的因素。

1) 解压缩线程对应的oncputime和offcputime耗时数据,user态和sys态各自耗时。

2) 解压缩线程的io wait时间统计,由于内存回收导致的睡眠时间统计,在cpu队列runable时间统计,。

3) 解压缩线程的nonvoluntary context switch和voluntary context switch各自次数统计。

4) 解压缩线程的cpu 调度优先级。

5) 内存占用状况和缺页异常次数。

这样通过上面trace信息的分析,就可以知道影响单线程工作性能的因素到底在哪里了。

2:进一步的复杂性能问题定位

如果排查到是单线程的on cputime或者off cputime耗时,但是是代码级别的耗时,这种情况下,就要分析是哪个地方的代码造成的耗时。

这个时候,就要对单线程程序进行profile分析了。

oncpu的profile

可以用simpleperf工具,也可以用bcc工具集里面的profile工具,两个都可以做oncputime的profile分析。

区分是simpleperf Android代码包集成的就有,可以直接拿来用,但是perf工具有个传统的缺陷问题,实际运行时产生的overhead高,对待测试线程的性能有一定影响。

而bcc里面的profile工具是在内核态进行性能数据记录和统计的,所以产生的overhead低,对待测试线程的性能影响小,不过缺点是现有的Android代码包里面没有,需要花时间做这个工具集成。

不过这个profile工具也是可以跟simpleperf工具一样,能够进行随后的生成性能火焰图,方便对单线程的性能排查分析工作。

offcpu的profile

这个offcpu的profile用simpleperf工具就不行了,就算能用,估计产生的overhead是很高的,会严重影响到性能测试程序运行。

这个得必须用bcc里面的offcputime进行profile分析的。这个profile分析产生的log能够使工程师看出单线程的offcputime中究竟是什么样的内核栈场景会导致offcpu耗时长。

offtime下来也会搭配现有的perl脚本生成offcputime的火焰图,方便对单线程的性能排查分析工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值