上下文切换

vmstat cs:每秒上下文切换次数 的疑惑

in:每秒cpu中断次数

从Java视角理解系统结构连载, 关注我的微博(链接)了解最新动态 

在高性能编程时,经常接触到多线程. 起初我们的理解是, 多个线程并行地执行总比单个线程要快, 就像多个人一起干活总比一个人干要快. 然而实际情况是, 多线程之间需要竞争IO设备, 或者竞争锁资源,导致往往执行速度还不如单个线程. 在这里有一个经常提及的概念就是: 上下文切换(Context Switch). 

上下文切换的精确定义可以参考: http://www.linfo.org/context_switch.html. 下面做个简单的介绍. 多任务系统往往需要同时执行多道作业.作业数往往大于机器的CPU数, 然而一颗CPU同时只能执行一项任务, 如何让用户感觉这些任务正在同时进行呢? 操作系统的设计者巧妙地利用了时间片轮转的方式, CPU给每个任务都服务一定的时间, 然后把当前任务的状态保存下来, 在加载下一任务的状态后, 继续服务下一任务. 任务的状态保存及再加载, 这段过程就叫做上下文切换. 时间片轮转的方式使多个任务在同一颗CPU上执行变成了可能, 但同时也带来了保存现场和加载现场的直接消耗. 
(Note. 更精确地说, 上下文切换会带来直接和间接两种因素影响程序性能的消耗. 直接消耗包括: CPU寄存器需要保存和加载, 系统调度器的代码需要执行, TLB实例需要重新加载, CPU 的pipeline需要刷掉; 间接消耗指的是多核的cache之间得共享数据, 间接消耗对于程序的影响要看线程工作区操作数据的大小). 


在linux中可以使用vmstat观察上下文切换的次数. 执行命令如下: 

Shell代码  收藏代码
  1. $ vmstat 1  
  2. procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----  
  3.  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa  
  4.  1  0      4593944 453560 1118192    0    0    14    12  238   30  6  92  1  
  5.  0  0      4593212 453568 1118816    0    0     0    96  958 1108  4  94  2  
  6.  0  0      4593360 453568 1118456    0    0     0     0  895 1044  3  95  0  
  7.  1  0      4593408 453568 1118456    0    0     0     0  929 1073  4  95  0  
  8.  0  0      4593496 453568 1118456    0    0     0     1133 1363  6  93  0  
  9.  0  0      4593568 453568 1118476    0    0     0     0  992 1190  4  95  0  


vmstat 1指每秒统计一次, 其中cs列就是指上下文切换的数目. 一般情况下, 空闲系统的上下文切换每秒大概在1500以下. 

对于我们经常使用的抢占式操作系统来说, 引起上下文切换的原因大概有以下几种: 1. 当前执行任务的时间片用完之后, 系统CPU正常调度下一个任务 2. 当前执行任务碰到IO阻塞, 调度器将挂起此任务, 继续下一任务 3. 多个任务抢占锁资源, 当前任务没有抢到,被调度器挂起, 继续下一任务 4. 用户代码挂起当前任务, 让出CPU时间 5. 硬件中断. 前段时间发现有人在使用futex的WAIT和WAKE来测试context switch的直接消耗(链接), 也有人使用阻塞IO来测试context switch的消耗(链接).

原文地址:https://www.cnblogs.com/heygirl/p/4933412.html