上下文切换(二)
上下文切换
线程切换,同一进程中的两个线程之间的切换
进程切换,两个进程之间的切换
模式切换,在给定线程中,用户模式和内核模式的切换
地址空间切换,将虚拟内存切换到物理内存
线程上下文切换会有什么问题呢?
上下文切换会导致额外的开销,常常表现为高并发执行时速度会慢串行,因此减少上下文切换次数便可以提高多线程程序的运行效率。
直接消耗:指的是CPU寄存器需要保存和加载, 系统调度器的代码需要执行, TLB实例需要重新加载, CPU 的pipeline需要刷掉
间接消耗:指的是多核的cache之间得共享数据, 间接消耗对于程序的影响要看线程工作区操作数据的大小
切换查看
Linux系统下可以使用vmstat命令来查看上下文切换的次数, 其中cs列就是指上下文切换的数目
vmstat 1(watch vmstat -s)
R列,就绪队列的长度远远超过CPU个数,所以肯定会有大量的CPU竞争
us和sy,这两列的CPU使用率,其中系统CPU使用率很高,说明CPU主要被内核占用
in列:中断次数很高,说明中断处理也是个潜在的问题
cs (centext switch) 每秒的上下文切换次数
综合这几个指标,可以知道,系统的就绪队列过长,也就是正在运行和等待CPU的进程数过多,导致了大量的上下文切换,而上下文切换又导致了系统CPU使用率升高。
继续分析,用pidstat来看一下,CPU和进程上下文切换的情况:
-wt 参数表示输出线程的上下文切换指标
pidstat -wt 1(pidstat ,这里需要加上 -t 参数,显示线程,要不不带参数,看不到sysbench。)
pidstat的输出中,可以看到是哪个线程上下文切换过多。
cswch (voluntary context switches) 自愿上下文切换,指的是进程无法获得所需的资源导致的上下文切换。比如I/O不足,内存不足。
nvcswch (non voluntary context switches) 非自愿上下文切换,指的是 进程由于时间片已到等原因,被系统强制调度,进而发生上下文切换。比如大量进程在争抢CPU
一、接下来,继续分析中断次数上升的根源(中断只发生在内核态)
从/proc/interrupts这个只读文件读取,提供了一个只读的中断使用情况
watch -d cat /proc/interrupts(动态显示)
总结:
上下文切换指标:
(1).上下文切换次数取决于系统本身的CPU性能,如果系统的上下文切换次数比较稳定,那么从数百到1万以内都是正常的
(2).当上下文切换次数超过1万次,或者切换次数出现数量级增长时,就很可能已经出现了性能问题
同一个进程下线程上下文切换,因为共享虚拟内存,切换过程中,虚拟内存这些资源保持不变,只需要切换线程的私有数据,寄存器等不共享的数据。(多线程代替多进程)
自愿上下文切换变多了,说明进程都在等待资源,有可能发生IO等其他问题
非自愿上下文切换变多了,说明进程都在被强制调度,都在争抢CPU,说明CPU的确成了瓶颈
中断上下文切换变多了,说明CPU被中断处理程序占用,需要通过查看 /proc/interrupts文件分析具体的中断类型
线程让出cpu的情况
当前运行线程主动放弃CPU,JVM暂时放弃CPU操作(基于时间片轮转调度的JVM操作系统不会让线程永久放弃CPU,或者说放弃本次时间片的执行权),例如调用yield()方法。
当前运行线程因为某些原因进入阻塞状态,例如阻塞在I/O上
当前运行线程结束,即运行完run()方法里面的任务
引起线程上下文切换的因素
当前执行任务(线程)的时间片用完之后,系统CPU正常调度下一个任务
中断处理,在中断处理中,其他程序”打断”了当前正在运行的程序。当CPU接收到中断请求时,会在正在运行的程序和发起中断请求的程序之间进行一次上下文切换。中断分为硬件中断和软件中断,软件中断包括因为IO阻塞、未抢到资源或者用户代码等原因,线程被挂起。
用户态切换,对于一些操作系统,当进行用户态切换时也会进行一次上下文切换,虽然这不是必须的。
多个任务抢占锁资源,在多任务处理中,CPU会在不同程序之间来回切换,每个程序都有相应的处理时间片,CPU在两个时间片的间隔中进行上下文切换
合理设置线程数目既可以最大化利用CPU,又可以减少线程切换的开销。
高并发,低耗时的情况,建议少线程。
低并发,高耗时的情况:建议多线程。
高并发高耗时,要分析任务类型、增加排队、加大线程数
一般上下文切换在数百到一万之内上下文切换超过1万,很可能遇到性能问题。需要具体看看了。
资源上下文切换时说明进程在等待资源,有可能发生了I/O等问题;
非自愿上下文切换,说明进程在被强制调度,也就是在争抢CPU;
中断次数多了,说明CPU在被中断处理程序占用。可以通过/proc/interrupts 查看。