我们了解到导致平均负载,有可能是以下几种方面:
根据平均负载的解释,单位时间内的处于可运行的进程和不可中断进程的进程数,
System load averages is the average number of processes that are either in a runnable or uninterruptable state. A process in uninterruptable state is waiting for some I/O access, eg waiting for disk
所以我们会比较好了解CPU密集型,需要大量计算资源,会非常消耗cpu,I/O密集型需要等待I/O,会有大量的不可中断进程,
那么大量进程的情况下是如何导致平均负载升高的?
存在大量的进程竞争cpu,也就是存在大量的可运行进程,但是我们都知道cpu一个时间段其实只能运行一个进程,其他的进程也都只是在等待,并不会大量耗尽cpu资源的情况,而是cpu按照时间片给大量进程运行,所以可以想象在不停的切换不停的进程的情况下是不是也在消耗cpu资源能力,也就是我们今天要说的cpu上下文切换。
Linux是一个多用户用任务的操作系统,他支持远远大于cpu的进程数运行,而cpu每次却只能运行一个任务,所以其实这些任务其实并不是在同时运行,整个过程是cpu轮流运行任务,给用户带来的假象。而当一个任务需要运行前,cpu需要知道从那里加载,从哪里开始运行,也就是系统需要事先设置好cpu寄存器和程序计数器。
它们是CPU在运行任何任务前,必须依赖的,所以也被称为CPU上下文。
所以根据上下文的了解,所谓的上下文切换:
保存下来的上下文会存储在内核,并在任务重新调度时再加载进去,这样任务不受影响,任务看起来来也是连续运行的。
根据任务的不同,CPU上下文切换可以分几种不同场景:
Linux分为内核空间和用户空间:
所以根据内核空间划分,一个进程可以被称为进程的用户态和进程的内核态,
当一个系统调用发生市必然会发生CPU上下文切换的,
比如我们加载存在磁盘里的一个文件,我们触发的指令是进程的用户态,而我们需要操作磁盘就需要系统调用陷入内核态,而我们原先的用户态就需要保存起来,执行内核态的指令,加载完数据就需要恢复用户态,继续运行进程,
所以可以知道一次系统调用会发生两次CPU上下文切换。
这里说的系统调用和进程上下文切换又是不同的:
所以系统调用还是被称为特权模式调用,而不是上下文切换,但是系统调用导致的cpu上下文切换还是不可避免。
那么进程的上下文切换和系统调用存在什么关系?
进程是需要系统内核来管理和调度的,进程的上下文切换只能发生在内核态,
所以进程的上下文不仅包括虚拟内存、栈、全局变量等用户空间资源,还有内核堆栈、寄存器等内核空间状态。
所以进程的上下文切换和系统调用(软中断)多了一个保存用户空间和恢复用户空间。
进程上下文切换过程:
而保存上下文和恢复上下文过程不是免费的,大概每次上下文切换会花费几十纳秒到数微妙之间,当大量进程时,这个cpu上下文切换是相当可观的,会花费大量时间在保存和恢复cpu上下文和用户空间状态,cpu分配给进程的时间片是一定的,导致cpu实际运行进程时间大大减少,而当时间片用完,进程必须挂起,这也是导致平均负载升高的一个因素。
什么时候需要进行进程上下文切换?
Linux会为每个cpu都维护一个就绪队列,也就是进程状态为R状态的的进程,最理想状态是之前的进程完成,cpu得到释放,下一个进程得到cpu使用,但是实际情况是不同的。
线程和进程的最大区别在于,线程是调度的基本单位,而进程则是资源拥有的基本单位,说白了,内核中的任务调度,调度的对象就是线程,而进程给线程提供虚拟内存、全局变量等资源。
进程与线程的比较:
所以这里也可以看出,相对于比较多进程与多线程,
多线程间的切换会比多进程间的切换消耗更少的资源。
int
指令可以产生软中断Kernel-side: int $0x80 entry point
为了快速响应硬件事件,中断处理会打断进程的正常调度和执行,转而执行调用中断处理程序,响应设备事件。但是和进程的上下文不同的是,
中断上下文切换不会涉及到进程的用户态,只是需要内核态中断程序执行必需的状态,并且对于一个cpu来说,中断处理比进程拥有更高的优先级。
过多的cpu上下文切换会导致花费大量的时间消耗在寄存器、内核栈及虚拟内存的保存与恢复中,缩短cpu在规定时间片内真正运行的时间,导致系统性能大幅下降。
vmstat可以用来分析系统内存使用情况,也可以用来分析cpu上下文切换和中断的次数。
vmstat可以给出总体的上下文切换情况,如果想要查看每个进程的详细情况,
需要pidstat来查看:
这两种概念意味着不同的性能问题:
使用sysbench模拟多线程调度瓶颈:
查看vmstat:
cs(上下文切换)突然增大到300多万,同时观测到r增大到9,远远超过了操作系统的2核,us(user)和sy(system)这两列cpu的使用率开始突增,cpu主要被内核空间占有,in列也开始增加一倍,说明中断也是一个原因。
我们从vmstat大体可以看出cpu上下文切换和中断,并且存在多个进程竞争情况,内核空间异常繁忙,接下来我们需要分析原因,需要继续分析:
很明显看出来cpu使用率升高是sysbench导致的,而上下文切换则是其他进程,包括非自愿上下文切换最高的pidstat,但是我们会发现自愿上下文切换比vmstat来说的300多万来说小太多了,我们需要考虑线程问题。
还有我们要如何查看中断突然增大:
watch -d cat /proc/interrupts
Rescheduling interrupts are the Linux kernel's way to wake-up an idle CPU-core to schedule a thread on it. On SMP systems, this is often done by the scheduler in a effort to spread the load across multiple CPU-cores. 重新安排中断是Linux内核唤醒空闲CPU核心以在其上安排线程的方法.在SMP系统上,这通常由调度程序完成,以便将负载分散到多个CPU核心 Function call interrupts:: software-interrupts to 软中断
所以回到上下文切换多少合适,这个数值还是取决于cpu性能,如果想要系统比较稳定,这个值可以尽量控制在几百到一万之间,如果超过一万或者指数级增量,一般都是出现性能问题。
总结:
sysbench是一款开源的多线程性能测试工具,可以执行CPU/内存/线程/IO/数据库等方面的性能测试
来源:极客