一、从一个问题说起

  相信很多人在玩手机还是PC时,都曾碰到过这样一种情况,安装的软件多了系统性能就变慢了,但是去查看CPU利用率一直都低于10%,内存也很充足。我在近期的开发工作中就碰到了类似的情况,不同的是,系统此时只有一个测试程序和几个睡眠的后台进程,说明是系统,特别是驱动部分可能出现问题导致的。 从操作系统角度上分析,以下是一些比较可能的原因:

  1. 大量的中断
    可能是在不断磁盘读写,网络通讯, 也可能是模块使用不当或者硬件上出问题导致外设不断给CPU送中断;
  2. 系统负载高(注意:不是CPU利用率)
    负载高表示有很多程序等待调度运行,它会导致上下文切换频繁。
  3. 上下文切换过于频繁
    上下文切换是指CPU从一个进程切换到另一个进程,这个过程也是需要消耗一定时间的。如果说上下文切换过于频繁,说明CPU用于执行进程代码的时间少了。第2点有提到负载高会引起上下文切换频繁,但是上下文切换频繁负载不一定就高。

  在以往的排查经验中,系统性能下降主要由1引起的,在影响系统性能上表现得比较明显;而2,3则比较隐蔽,即使数值已经异常,只要应用对实时性要求不高,最多就是响应稍慢一些,看不出有什么不妥。因此,底层驱动开发人员一般不会去考虑2,3两点,更别说将它作为评价系统性能的测试指标。刚好我要测试的模块对实时性要求很高,而由于系统在空闲时的上下文切换已经很频繁,测试结果自然不佳。

二、怎么确认上下文切换频繁?

  要解决空闲时上下文切换频繁的问题,首先要了解下多频繁才不正常。/proc/stat文件包含了CPU的活动信息,上下文切换就是其中一项,下面命令输出的粗体大号字体所示,以ctxt开头,它表示系统开机到目前为止的上下文切换总数。

 ~ # cat /proc/stat
cpu
cpu0
intr
ctxt

btime
processes
procs_running
procs_blocked
softirq

  对于分析问题而言,我们更关心每秒钟的上下文切换次数,可通过以下命令计算。

 $cat /proc/stat | grep ctxt && sleep  && cat /proc/stat | grep ctxt
ctxt
ctxt

  每秒上下文切换次数=两者差值/30。针对本例,每秒有237次切换,对于一个空闲的系统,这是相当不正常的。正常数值范围一般不超过50次/秒。不过这也不是固定的,需要根据不同的系统环境决定,比如本人在嵌入式开发主要从事开发POS产品,它与作为服务器的Linux系统相比,实际运行的服务会少很多,上下文切换自然应该更少。另外,如果要求更高的实时性,则数值范围还应进一步缩小,本人分析的产品所定的数值范围就要求空闲时不超过30次/秒。 上面介绍的方法在所有Linux产品上都能支持,如果系统带 vmstat ,通过vmstat查看是一个更便捷的方法。测试结果如下图红色方框所示。

三、上下文切换频繁时怎么排查?

  仅靠总的上下文切换次数无法定位到哪个进程或者哪个驱动出的问题,这时就需要pidstat(在sysstat包里)可以查看具体到每个进程每秒的上下文切换次数,下图是执行 $pidstat -w 1的结果。

  在继续分析上图之前我们先谈一个概念:CPU密集型的进程和IO密集型的进程。CPU密集型的进程时间片总是不够用,CPU使用率必然升高,不需要查看上下文切换;而IO密集型的进程,会被频繁调度,但是每次只处理一小会,从CPU使用率是看不出异常的,这时就需要查看上下文切换。一般来讲IO密集型的进程(内核线程或用户进程)主要是处理读写磁盘,或者网络进来的数据;但是也可能有的进程没有任何IO交互但是表现得像IO密集型进程,比如使用如下方式:

  1. 创建一个内核线程,一启动就睡眠;然后创建一个10MS的timer,每次都去唤醒这个内核线程。
  2. 创建一个用户进程,通过系统调用陷入内核就睡眠,然后创建一个10MS的timer,每次都去唤醒这个进程。

当然,我们不会傻到直接干这样的事,但却可能在无意中间接做了这样的事情,特别是对第1条,比如

  1. 创建一个工作队列,创建一个10MS的timer,每次去schedule_work。

  工作队列也是由一个内核线程在管理,导致的结果就是该内核线程上下文切换将变得极为频繁。 对于上下文切换频繁的进程,我们的关注点就是确认它们是否是IO密集型的,以及在当前系统状态下是否应该表现得像IO密集型进程。 比如一个处理网络数据的进程,如果在没有数据的情况下,也表现得像IO密集型,有很高的切换上下文动作,可能这个进程或者该进程打开的设备驱动设计得不合理。

  有两个内核线程kswapd和events(新内核改为kworker),在特定情况下会表现得像IO密集型进程。其中kswapd是用于管理虚拟内存的,当物理内存不足,需要频繁交换虚拟内存,kswapd的上下文切换将明显增多;而events用来处理工作队列,当不断有work进入排队且这些work处理时间很短时,events的上下文切换会明显增多,对于这种情况,需要分析具体是由哪个驱动引起的。

  回到pidstat的输出,可以看到events/0的上下文切换很高,既然没有什么进程会导致该结果,就只可能是某个驱动文件(ko)在不断地排队work。目前我没有找到比较高效的方法可以迅速定位到每个ko文件对work的使用情况,只能通过lsmod打出已经加载的驱动,并跟以前的系统版本对比哪些做了修改以做对比。最终定位出确实存在某个驱动创建一个10MS的timer,并且每次都schedule_work。在对该驱动优化后,再次输入pidstat -w 1测试,可以看到所有进程的下下文切换都降得很低了。

四、附录

1、交叉编译sysstat 一般的板子都不会带pidstat,需要自己下载sysstat的包编译。好在sysstat直接使用工具链就能编译。操作步骤: 进入源码目录

 $mkdir output
$export SA_DIR=`pwd`/output/var/log/sa
$export conf_dir=`pwd`/output/etc/kksysconfig
$./configure --prefix=`pwd`/output --host=arm-none-linux-gnueabi --disable-man-group
$make
$make install

将output下的bin和lib拷到板子即可。注意交叉编译时要在configure时指名工具链名称,如果你的工具链是arm-none-linux-gnueabi-gcc,那么就传递参数--host=arm-none-linux-gnueabi,如果是arm-eabi-gcc,那么就传递参数--host=arm-eabi,按此规则修改。

2.参考文献

Linux的各种统计信息

CPU-上下文切换,运行队列和使用率

进程上下文切换-残酷的性能杀手(上)

使用pidstat查看Context Switch上下文切换

[嵌入式开发]Linux性能分析——上下文切换的更多相关文章

  1. Linux 性能分析工具汇总合集

    出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识, ...

  2. [转]Linux性能分析工具汇总合集

    出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识, ...

  3. 超全整理!Linux性能分析工具汇总合集

    转自:http://rdc.hundsun.com/portal/article/731.html?ref=myread 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章. ...

  4. (转)超全整理!Linux性能分析工具汇总合集

    超全整理!Linux性能分析工具汇总合集 原文:http://rdc.hundsun.com/portal/article/731.html 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望, ...

  5. Linux性能分析命令工具汇总

    转自:http://rdc.hundsun.com/portal/article/731.html?ref=myread 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章. ...

  6. Linux 性能分析 工具命令

    背景知识:具备背景知识是分析性能问题时需要了解的.比如硬件 cache:再比如操作系统内核.应用程序的行为细节往往是和这些东西互相牵扯的,这些底层的东西会以意想不到的方式影响应用程序的性能,比如某些程 ...

  7. 【转】一文掌握 Linux 性能分析之网络篇(续)

    [转]一文掌握 Linux 性能分析之网络篇(续) 在上篇网络篇中,我们已经介绍了几个 Linux 网络方向的性能分析工具,本文再补充几个.总结下来,余下的工具包括但不限于以下几个: sar:统计信息 ...

  8. 【转】一文掌握 Linux 性能分析之网络篇

    [转]一文掌握 Linux 性能分析之网络篇 比较宽泛地讲,网络方向的性能分析既包括主机测的网络配置查看.监控,又包括网络链路上的包转发时延.吞吐量.带宽等指标分析.包括但不限于以下分析工具: pin ...

  9. 【转】一文掌握 Linux 性能分析之 I/O 篇

    [转]一文掌握 Linux 性能分析之 I/O 篇 这是 Linux 性能分析系列的第三篇,前两篇分别讲了 CPU 和 内存,本篇来看 IO. IO 和 存储密切相关,存储可以概括为磁盘,内存,缓存, ...

随机推荐

  1. HTML特殊符号汇总

    较常用的飘黄处理了 ´ ´ © © > > µ µ ® ® & & ° ° ¡ ¡   » » ¦ ¦ ÷ ÷ ¿ ¿ ¬ ¬ § § • • ½ ½ « « ¶ ¶ ¨ ...

  2. react初始(2)

    既然我开始了react的学习,就没有停下来的理由了,我应该很幸运我还有这个时间去学习react,我不认为我聪明,但是我认为我够努力.我先在或许是一个不知道未来该是怎样的人,我们的迷茫和无知源于你不去接 ...

  3. 【原创】kafka client源代码分析

    该包下只有一个文件:ClientUtils.scala.它是一个object,里面封装了各种client(包括producer,consumer或admin)可能会用到的方法: 1. fetchTop ...

  4. [Asp.net 5] Localization-resx资源文件的管理

    上一篇博文地址:[Asp.net 5] Localization-简单易用的本地化-全球化信息 本文继续介绍asp.net 5多语言.今天重点讲的是多语言的resx文件.涉及到的工程有:Microso ...

  5. Java时间和时间戳的相互转换

    时间转换为时间戳: /* * 将时间转换为时间戳 */ public static String dateToStamp(String s) throws ParseException{ String ...

  6. SQL SERVER2012附加 (PS:开始试过sql2012直接附加失败)

    Northwind 示例数据库下载:  NORTHWND.MDF   (PS:开始试过sql2012直接附加失败) 新建查询-执行下面代码 USE [master] GO CREATE DATABAS ...

  7. uct框架数据库sql文件导入错误之 sql_mode

    uct框架在导入sql文件时可能会出现一种错误 ERROR 1101 (42000): BLOB/TEXT column 'brief' can't have a default value 这是由于 ...

  8. 【shell 大系】Linux Shell常用技巧

    在最近的日常工作中由于经常会和Linux服务器打交道,如Oracle性能优化.我们数据采集服务器的资源利用率监控,以及Debug服务器代码并解决其效率和稳定性等问题.因此这段时间总结的有关Linux ...

  9. WebAPI生成可导入到PostMan的数据

    一.前言 现在使用WebAPI来作为实现企业服务化的需求非常常见,不可否认它也是很便于使用的,基于注释可以生成对应的帮助文档(Microsoft.AspNet.WebApi.HelpPage),但是比 ...

  10. 十一个行为模式之备忘录模式(Memento Pattern)

    定义: 在不破坏原有封装的情况下,捕获一个对象的内部状态,并在对象之外保存.当对象出错或者无效是,可以根据该备忘录进行恢复. 结构图: Originator:原发类,被记录的对象,包含若干内部状态.一 ...