现阶段操作系统可同时执行多个任务,但这些任务并不是同时执行,系统在很短的时间内将cpu轮流分配给每个任务,由于任务轮流执行依赖于cpu寄存器和程序计数器,通过它们暂存指令,数据和地址,以及程序运行的下一条地址,因此也被称为cpu上下文。
cpu上下文切换就是把上一个任务的cpu上下文保存起来,然后加载新任务的上下文到寄存器与程序计数器,加载完成后跳转到程序计数器所指的新位置,运行新任务。被保运起来的上下文会存储在系统内核中,并在任务执行时再次加载进来。
每次上下文切换需要几十纳秒到数微秒的时间,频繁上下文会导致cpu将大量时间耗费在寄存器,内核栈及虚拟内存等资源保存恢复上,缩短真正运行时间。当上下文次数超过1万次或出现爆发式增涨时,系统会出现性能问题。
cpu上下文切换包括进程上下文切换,线程上下文切换,中断上下文切换。
一、进程上下文切换
进程调度时会触发上下文切换,linux 为每个 cpu维护一个队列,将活跃进程按照优先级和等待 cpu的时间排序,然后选择优先级最高或等待 cpu时间最长的进程来运行。
比如有几种常见情况会触发进程上下文切换:
1.进程正常执行完,从队列中取出新进程执行。
2.进程分配的cpu时间片用完了,但仍未执行完任务。
3.系统资源不足时,要等到资源满足后才可以运行,此时进程被挂起。
4.调用sleep函数。
5.有更高优先级进程运行。
二、线程上下文切换
线程是系统调度的基本单位,进程是资源拥有的基本单位,为线程提供虚拟内存,全局变量等资源。线程上下文切换分为两种情况:
1.两个线程属于不同进程,此时进程资源不共享,线程上下文切换等于进程上下文切换
2.两个线程属于同个进程,此时进程资源共享,在线程切换时进程资源不变,只切换线程私有数据,此时线程上下文切换消耗资源比进程少。
三、中断上下文切换
由于硬件(鼠标、键盘)优先级高于进程优先级,收到硬件指令后会打断正在执行的进程,转而执行硬件指令,这种情况被称为中断上下文切换。
中断上下文切换不涉及进程用户态,发生中断上下文切换时不用保存和恢复进程的虚拟内存,全局变量等,性能消耗会比进程上下文切换低。
四、查看上下文切换
可使用vmstat查看系统总体cpu上下文切换和中断次数。
vmstat 2 2 表示每两秒统计一次,统计两次。
对于上下文切换主要观察以下指标:
cs:每秒上下文切换次数。
i n:每秒中断次数。
当发现系统总体上下文切换次数过高时,可使用pidstat -w查看进程上下文切换次数,或使用pidstat -wt查看线程上下文切换次数。
cswch/s:每秒自愿上下文切换次数,自愿上下文切换指进程无法获取所需自愿,导致的上下文切换,当自愿上下文切换次数增加时表明进程都在等待资源,此时磁盘io可能发生问题。
nvcswch/s :每秒非自愿上下文切换次数,非自愿上下文切换指进程时间片用完了,被强制调度,当非自愿上下文切换次数增加表明进程间竞争cpu严重,此时cpu是系统瓶颈。
pidstat只能分析性能,无法查看中断的详细信息,可通过watch -d cat /proc/interrupts查看详细信息。