热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

mysql上下文切换高_系统性能分析之CPU上下文切换

多任务的实施依赖于CPU上下文的切换,其中就要理解CPU寄存器(CPURegister)和程序计数器(ProgramCounter)。前者是CPU内置的容量小、速度极

多任务的实施依赖于CPU上下文的切换,其中就要理解CPU寄存器(CPU Register)和程序计数器(Program Counter)。前者是CPU内置的容量小、速度极快的内存;程序计数器保存正在执行的指令位置,或即将执行的下一条指令的位置,它们都是CPU运行任何任务前,必须的依赖环境,因此被叫做CPU上下文切换。过程大致如下:

首先,保存前一任务的CPU上下文(CPU寄存器和程序计数器)

然后,加载更新新任务的CPU上下文到CPU寄存器和程序计数器

最后,跳到程序计数器所指的新位置,运行新的任务

根据任务不同,可以分为进程上下文切换、线程上下文切换、中断上下文切换

进程上下文切换,是指从一个进程切换到另一个进程,进程由内核管理和调度,进程切换只能发生在内核态。进程在用户态运行称为进程的用户态,陷入内核运行时,称为进程的内核态。但是从用户态转变为内核态,需要系统调用(system call ).一次系统调用发生两次CPU上下文的切换:

CPU寄存器和程序计数器先保存用户态的CPU上下文,接着为了执行内核态代码,更新加载内核态指令的位置,之后跳到内核态执行内核任务;

系统调用结束后,CPU寄存器需要恢复到原来保存的用户态,之后切换到用户空间,继续执行进程。

注意的是,系统调用不涉及到虚拟内存等用户态的资源,也不切换进程。

触发进程上下文切换的场景:

(a)CPU时间分为一段段的时间片,公平分配给各进程,当某进程的时间片耗尽,就会被系统挂起,切换到另一进程

(b)进程在资源不足时(内存不足),要等到资源满足时才能运行,这时进程也会被挂起,并由系统调度其他进程运行

(c)当进程遇到睡眠函数sleep这样的方法时,会主动挂起,切换到其他进程

(d)当遇到高优先级进程时,为保证高优先级的进程运行,当前进程会被挂起,由高优先级进程运行

(e)发生硬件中断时,CPU上的进程会被中断挂起,转而执行内核中的中断服务程序

线程上下文切换

线程是任务调度的最小单位,进程是资源分配的最小单位,实质是:内核中的任务调度,实际上的调度对象是线程;进程则是为线程提供虚拟内存、全局变量等资源。也可以这样理解进程和线程:

(1)当进程只有一个线程时,可以认为进程就等于线程

(2)当进程有多个线程时,这些线程共享相同的虚拟内存、全局变量等资源,这些资源在上下文切换时不需要修改

(3)线程也有自己私有数据,如栈和寄存器等,这些私有数据在上下文切换时是需要保存的

线程上下文切换分为两种情况:(1)前后两个线程属于不同的进程,由于资源不共享,此时的线程切换就和进程切换一样

(2)前后两个线程属于相同的进程,由于虚拟内存等资源共享,切换时,只切换线程的私有数据等不共享数据。

可以看到同进程的不同线程切换消耗的资源较小,效率高

中断上下文切换

为了快速响应硬件事件,中断处理会打断进程的正常调度和执行,转而调用中断服务程序,响应设备事件。

和进程上下文切换不同,中断上下文切换不涉及进程的用户态,它只包括内核态中断服务程序执行所必需的状态,包括CPU寄存器、内核堆栈、硬件中断参数等。

对同一CPU来说,中断处理比进程拥有更高的优先级;和进程切换一样,中断切换也消耗CPU,切换次数过多也消耗大量的CPU,甚至会影响系统的整体性能。

小结

不管哪种场景导致的上下文切换,我们都应该知道:

(1)CPU上下文切换,是保证Linux系统多任务处理的核心功能之一,一般情况下不用我们关注

(2)过多的上下文切换,会把CPU时间消耗在寄存器、虚拟内存等数据的保存和恢复上,缩短了进程真正运行时间,导致系统整体性能下降。

案例分析:

vmstat主要用来分析系统的内存情况,也常用来分析CPU上下文切换和中断的次数

root@andy:~# vmstat 1 1

procs -----------memory----------------------------- ---swap-- -----------io-------- -system-- ------cpu-----

r  b    swpd   free     buff  cache    si   so    bi    bo   in   cs   us  sy  id   wa  st

0  0      0   2437540  97108 956224   0    0   161    72   54   58  1   2  92   5   0

注释

Procs

r: The number of runnable processes (running or waiting for run time).

b: The number of processes in uninterruptible sleep.

IO

bi: Blocks received from a block device (blocks/s).

bo: Blocks sent to a block device (blocks/s).

System

in: The number of interrupts per second, including the clock.

cs: The number of context switches per second.

从上面的例子可以看到系统上下文切换为58次,系统中断为54次;运行或等待运行的进程r为0,不可中断的睡眠进程b为0

vmstat只能看到系统总体上下文切换情况,查看各进程的详细情况,需要前面使用的pidstat命令-w就能详细查看

root@andy:~# pidstat  -w

Linux 4.18.0-12-generic (andy)  05/20/20        _x86_64_        (4 CPU)

14:32:52      UID       PID   cswch/s  nvcswch/s  Command

14:32:52        0         1      5.15      5.67  systemd

14:32:52        0         2      0.64      0.00  kthreadd

14:32:52        0         3      0.00      0.00  rcu_gp

14:32:52        0         9      1.37      0.02  ksoftirqd/0

14:32:52        0        10     33.00      0.03  rcu_sched

....................................

-w     Report  task  switching activity (kernels 2.6.23 and later only)

cswch/s

Total number of voluntary context switches the task made per second.

A voluntarycontext switch occurs whenatask blocks because it requires a resource that isunavailable.

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 timeslice and then is forced to relinquish the processor.

输出结果中重点关注cswch/s和nvcswch/s的次数,因为它们意味着不同的性能问题。

自愿上下文切换(cswch):当进程无法获得所需要的资源时,就会导致上下文切换,比如I/O、内存资源不足。

非自愿上下文切换(nvcswch):进程由于时间片已到等原因,被强制调度,发生上下文切换,比如大量进程争夺CPU。

在进行案例模拟前,首先看下空闲系统的上下文切换

root@andy:~# vmstat  1 3

procs -----------memory---------------------------- ---swap-- ----------io--------- -system-- ------cpu-----

r  bswpdfreebuff  cachesi   so    bi    boin  csussy idwa st

1  0      0 2484140  95048 919748    0    0    45    1117200  0 98  1  0

0  0      0 2484148  95048 919748    0    0     0     027230  0 100  0  0

0  0      0 2484148  95048 919748    0    0     0     029300  0 100  0  0

机器提前准备安装好sysbench和sysstat

在第一个终端里,执行sysbench模拟系统多线程调度的瓶颈

root@andy:~# sysbench --threads=5 --max-time=60 threads run

以5个线程运行60秒为基准测试,模拟多线程切换的问题

第二个终端,执行vmstat观察上下文切换

root@andy:~# vmstat  1

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----

r  b 交换 空闲 缓冲 缓存si   so    bi    bo   in   cs us sy id wa st

1  0    780 218488 112644 981264    0    0   111    50   41   49  1  1 95  3  0

0  0    780 218448 112644 981264    0    0     0     0   71   94  0  0 100  0  0

0  0    780 218448 112644 981264    0    0     0     0   64   90  0  0 100  0  0

5  0    780 215968 112644 982552    0    0  1224     0 2649 129107  7 19 70  4  0

5  0    780 215960 112644 982488    0    0     0     0 10481 367900 32 61  7  0  0

5  0    780 215960 112644 982488    0    0     0     0 11893 347654 35 58  6  0  0

5  0    780 215960 112644 982488    0    0     0     0 10051 335603 30 63  7  0  0

能明显看到cs切换飙升到三十多万,中断in飙升到一万多,这明显影响系统性能;r为5,系统逻辑CPU为4,存在使用CPU的竞争,在CPU中us与sy相加为93左右,且sy在六十上下,说明内核占用CPU较多。

综合可以得出:运行或等待运行的系统就绪队列(进程)过多,导致上下文切换的飙升,上下文的切换又导致CPU的使用率上升。

第三个终端,用pidstat查看CPU和进程上下文切换的情况

root@andy:~# pidstat -w -u  1 #-w表示进程切换指标-u表示CPU使用指标1表示每个1秒输出1次(需Ctrl+c结束)

Linux 4.18.0-12-generic (andy)  2020年05月20日_x86_64_        (4 CPU)

22时04分20秒UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command

22时04分21秒0      3142    0.00    1.00    0.00    0.00    1.00     0  sshd

22时04分21秒0      4181  100.00  100.00    0.00    0.00100.003sysbench

22时04分21秒0      4188    1.00    2.00    0.00    0.00    3.00     0  pidstat

22时04分20秒UID       PID   cswch/s nvcswch/s  Command

22时04分21秒0         9      2.00      0.00  ksoftirqd/0

22时04分21秒0        1020.000.00rcu_sched

22时04分21秒0        30      2.00      0.00  ksoftirqd/3

22时04分21秒0        37      1.00      0.00  kworker/0:1-mpt_poll_0

22时04分21秒0      309952.000.00kworker/u256:0-events_freezable_power_

22时04分21秒0      314247.000.00sshd

22时04分21秒0      412848.000.00kworker/u256:2-events_unbound

22时04分21秒0      4180      1.00      0.00  vmstat

22时04分21秒0      4188      1.0037.00pidstat

.............

可以看出CPU使用率升高是sysbench导致的,但上下文切换是由其他进程导致的,比如自愿上下文切换的rcu_sched、kworker等,非自愿上下文切换的pidstat.

我们看到这些切换总共加起来也就两百左右,怎么cs能飙到三十多万,中断飙到一万多呢?使用pidstat -wt 1显示线程指标,如下:

root@andy:~# pidstat -wt  1  #-wt参数输出线程的上下文切换指标

Linux 4.18.0-12-generic (andy)  2020年05月20日_x86_64_        (4 CPU)

22时51分58秒UID      TGID       TID   cswch/s nvcswch/s  Command

22时51分59秒0         9         -      8.00      0.00  ksoftirqd/0

22时51分59秒0         -         9      8.00      0.00  |__ksoftirqd/0

22时51分59秒0        10         -     20.00      0.00  rcu_sched

22时51分59秒0         -        10     20.00      0.00  |__rcu_sched

22时51分59秒0        18         -      1.00      0.00  ksoftirqd/1

22时51分59秒0         -        18      1.00      0.00  |__ksoftirqd/1

22时51分59秒0        37         -      2.00      0.00  kworker/0:1-events

22时51分59秒0         -        37      2.00      0.00  |__kworker/0:1-events

22时51分59秒0        39         -      1.00      0.00  kworker/1:1-mm_percpu_wq

22时51分59秒0         -        39      1.00      0.00  |__kworker/1:1-mm_percpu_wq

22时51分59秒0        55         -      1.00      0.00  kworker/2:1-mm_percpu_wq

22时51分59秒0         -        55      1.00      0.00  |__kworker/2:1-mm_percpu_wq

22时51分59秒0         -      1298      1.00      0.00  |__gmain

22时51分59秒125         -      1606      2.00      0.00  |__mysqld

22时51分59秒125         -      1607      2.00      0.00  |__mysqld

22时51分59秒125         -      1608      2.00      0.00  |__mysqld

22时51分59秒125         -      1609      2.00      0.00  |__mysqld

22时51分59秒125         -      1610      2.00      0.00  |__mysqld

22时51分59秒125         -      1611      2.00      0.00  |__mysqld

22时51分59秒125         -      1612      2.00      0.00  |__mysqld

22时51分59秒125         -      1613      2.00      0.00  |__mysqld

22时51分59秒125         -      1614      2.00      0.00  |__mysqld

22时51分59秒125         -      1615      2.00      0.00  |__mysqld

22时51分59秒125         -      1616      1.00      0.00  |__mysqld

22时51分59秒125         -      1848      1.00      0.00  |__mysqld

22时51分59秒125         -      1849      1.00      0.00  |__mysqld

22时51分59秒125         -      1851      1.00      0.00  |__mysqld

22时51分59秒110         -      2100      1.00      0.00  |__rtkit-daemon

22时51分59秒110         -      2101      1.00      0.00  |__rtkit-daemon

22时51分59秒0      3142         -     18.00      3.00  sshd

22时51分59秒0         -      3142     18.00      3.00  |__sshd

22时51分59秒0      3162         -      2.00      0.00  kworker/3:1-mm_percpu_wq

22时51分59秒0         -      3162      2.00      0.00  |__kworker/3:1-mm_percpu_wq

22时51分59秒0      4196         -     16.00      0.00  kworker/u256:2-events_unbound

22时51分59秒0         -      4196     16.00      0.00  |__kworker/u256:2-events_unbound

22时51分59秒0      4259         -     21.00      0.00  kworker/u256:1-events_unbound

22时51分59秒0         -      4259     21.00      0.00  |__kworker/u256:1-events_unbound

22时51分59秒0         -      4269   9886.00  41982.00  |__sysbench

22时51分59秒0         -      4270  10853.00  85926.00  |__sysbench

22时51分59秒0         -      4271   9830.00  41249.00  |__sysbench

22时51分59秒0         -      4272   9130.00  48229.00  |__sysbench

22时51分59秒0         -      4273   9306.00  58599.00  |__sysbench

22时51分59秒0      4274         -      1.00      9.00  pidstat

22时51分59秒0         -      4274      1.00      9.00  |__pidstat

.............

可以看到虽然sysbench进程(也就是主线程)的上下文切换不多,但是它的子线程切换较多,结论就是上下文切换的罪魁祸首就是sysbench的子线程。

中断的类型可以通过cat /proc/interrupts查看,如下:root@andy:~# watch -d cat /proc/interrupts

Every 2.0s: cat /proc/interrupts                                                         andy: Wed May 20 23:08:42 2020

CPU0       CPU1       CPU2       CPU3

0:         17          0          0          0   IO-APIC    2-edge      timer

1:          0          0          0          9   IO-APIC    1-edge      i8042

8:          1          0          0          0   IO-APIC    8-edge      rtc0

9:          0          0          0          0   IO-APIC    9-fasteoi   acpi

12:        125          0         16          0   IO-APIC   12-edge      i8042

14:          0          0          0          0   IO-APIC   14-edge      ata_piix

15:          0          0          0          0   IO-APIC   15-edge      ata_piix

16:         46          0          0      17031   IO-APIC   16-fasteoi   vmwgfx, snd_ens1371, ens38

17:       5202      37960          0          0   IO-APIC   17-fasteoi   ehci_hcd:usb1, ioc0, ens39

18:          0        217          0          0   IO-APIC   18-fasteoi   uhci_hcd:usb2

24:          0          0          0          0   PCI-MSI 344064-edge      PCIe PME, pciehp

25:          0          0          0          0   PCI-MSI 346112-edge      PCIe PME, pciehp

通过这个案例可以看到多工具、多个指标对比的好处,可以发现进程内部的变化及细节。

再回到CPU上下文切换多少才算正常?这个值其实取决于CPU本身的性能,从数百到一万都可以算正常,但是当上下文切换超多一万的时候,就可能要分析系统,特别是当切换次数出现数量级的增长,就很可能出现性能问题。

可以根据上下文切换的类型,做进一步的分析

自愿上下文切换增多,说明进程等待资源,有可能出现内存、IO等其他问题

非自愿上下文切换增多,说明进程被强制调度,也就是在争夺CPU资源,CPU成了系统性能瓶颈

中断次数变多,说明CPU被中断处理程序占用,可以通过cat /proc/interrupts文件,查看中断类型



推荐阅读
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 本文介绍了如何在Azure应用服务实例上获取.NetCore 3.0+的支持。作者分享了自己在将代码升级为使用.NET Core 3.0时遇到的问题,并提供了解决方法。文章还介绍了在部署过程中使用Kudu构建的方法,并指出了可能出现的错误。此外,还介绍了开发者应用服务计划和免费产品应用服务计划在不同地区的运行情况。最后,文章指出了当前的.NET SDK不支持目标为.NET Core 3.0的问题,并提供了解决方案。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文介绍了三种方法来实现在Win7系统中显示桌面的快捷方式,包括使用任务栏快速启动栏、运行命令和自己创建快捷方式的方法。具体操作步骤详细说明,并提供了保存图标的路径,方便以后使用。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
author-avatar
很想爱到极限
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有