CPU上下文切换

  CPU上下文切换包括进程上下文切换、线程上下文切换及中断上下文切换,当任务进行io或发生时间片事件及发生中断(如硬件读取完成)时,就会进入内核态,发生CPU上下文切换。

  1. 进程上下文切换,进程的上下文信息包括, 指向可执行文件的指针, 栈, 内存(数据段和堆), 进程状态, 优先级, 程序I/O的状态, 授予权限, 调度信息, 审计信息, 有关资源的信息(文件描述符和读/写指针), 关事件和信号的信息, 寄存器组(栈指针, 指令计数器)等等,当发生进程切换时,这些保存在寄存器或高速缓存的信息需要记录到内存,以便下次恢复进程的运行。
  2. 线程上下文切换,同一个进程的线程切换,只需保存线程独有的信息,比如栈和寄存器,而共享的虚拟内存和全局变量则无需切换,因此切换开销比进程小。
  3. 中断上下文切换,中断会打断一个正常执行的进程而运行中断处理程序,因为中断处理程序是内核态进程,而不涉及到用户态进程之间的切换,当被中断的是用户态进程时,不需保存和恢复这个进程的虚拟内存和全局变量,中断上下文只包括中断服务程序所需要的状态,比如CPU寄存器、内核堆栈、硬件中断等参数。

  过多的上下文切换会导致将大量CPU时间浪费在寄存器、内核栈以及虚拟内存的保存和恢复上,导致系统整体性能下降。可以用vmstat查看系统的整体上下文切换情况,如下图1,空闲系统的上下文切换次数cs(context switch)为100多,中断次数in(interrupt)为100多,在运行态r(running or runable)的进程数为2,在阻塞态的进程数b为0。

图1 空闲系统上下文切换和中断情况

  案例:我们用sysbench来模拟多线程频繁上下文切换的场景,并用vmstat、pidstat和/proc/interrupts来分析定位具体的线程。

  用sysbench模拟10个线程,运行300s来观察线程切换的频繁场景,如下图2所示。

图2 大量线程切换场景模拟

 

   用vmstat查看系统整体的上下文切换和中断情况,如下图3,可看到cs和in的数目和空闲的时候比增加了很多。

 图3 系统整体上下文切换情况

  发现系统切换情况比较频繁,可以用pidstat查看具体切换比较频繁的线程,命令:pidstat -w -t 1,含义如下,

-w Report task switching activity (kernels 2.6.23 and later only). The following values may be displayed:

cswch/s
Total number of voluntary context switches the task made per second. A voluntary context switch occurs when a task blocks because it requires a resource that is unavailable.

每秒自愿上下文切换次数,如等待io等。

nvcswch/s
Total number of non voluntary context switches the task made per second. A involuntary context switch takes place when a task executes for the duration of its time slice and then is
forced to relinquish the processor.

每秒非自愿上下文切换次数,如时间片用完切换。

 -t展示具体的线程情况。

结果如下图4所示,可以看到,切换频繁的线程是sysbench

图4 线程切换情况

posted @ 2018-12-02 15:34  golang架构师k哥  阅读(1377)  评论(0编辑  收藏  举报