Linux 性能分析 | 上下文切换

引言

计算机科学中上下文指执行某个操作所需的相关状态。操作系统中的上下文切换是一种用于支持多任务处理的基本功能,允许单个处理器在多个进程或线程之间高效地切换,从而使计算机可以同时运行多个程序。上下文切换是必需的和有成本的,因此如何合理减少上下文切换和降低上下文切换的成本,是需要操作系统和开发者共同面对的问题。本文使用了vmstat工具,分别分析了进程、线程和协程上下文切换的成本。

上下文切换概述

进程上下文

进程是操作系统分配资源和调度的基本单位,拥有独立的地址空间和系统资源。一个进程的上下文包括:

  • 寄存器状态:包括程序计数器、堆栈指针、通用寄存器等。
  • 内存管理信息:如虚拟地址空间、页表等。
  • I/O状态信息:包括文件描述符、网络连接状态等。
  • 进程控制块 (PCB) :包含进程ID、进程状态(就绪、等待、运行)、调度优先级等。

线程上下文

线程是进程中的执行单元,线程间共享进程的地址空间和系统资源,但拥有自己的执行栈和寄存器集合。线程的上下文通常包括:

  • 寄存器状态:每个线程都有自己的寄存器集,包括程序计数器和堆栈指针。
  • 线程栈:每个线程都有自己的栈空间,用于存储执行过程中的局部变量、函数参数和返回地址。
  • 线程控制块 (TCB) :包含线程ID、线程状态、调度信息等。

协程上下文

协程是用户态的轻量级“线程”,由程序自行管理,不由操作系统内核调度。协程相比线程更加轻量,切换开销较小。协程的上下文包括:

  • 寄存器状态:程序计数器、通用寄存器等。协程通常使用的是线程的栈。
  • 协程栈:协程可能有自己的栈,尽管这个栈通常比线程栈要小。
  • 当前协程状态:记录了协程的当前状态,如运行、挂起等。
  • 调度器指针:指向管理这个协程的调度器或协程管理器。

使用多种工具分析上下文切换

vmstat(Virtual Memory Statistic)是一个监测虚拟内存、进程、CPU活动等系统性能的工具,在这里用来分析 CPU 上下文切换,在空闲状态下的使用示例如下

 

css

复制代码

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 1792 3176396 1219380 19831540 0 0 0 0 1245 2580 0 0 100 0 0

  • procs (进程)

    • r: 运行队列中的进程数(即正在运行或等待CPU的进程数)
    • b: 不可中断睡眠状态的进程数(等待资源的进程)
  • memory (内存)

    • swpd: 交换空间总量
    • free: 空闲内存总量
    • buff: 作为缓冲使用的内存总量(磁盘级别)
    • cache: 作为缓存使用的内存总量(文件级别)
  • swap (交换区)

    • si: 每秒从磁盘交换进内存的内存量(swap in)
    • so: 每秒从内存交换到磁盘的内存量(swap out)
  • io (输入/输出)

    • bi: 每秒从块设备(如磁盘)读取的数据量
    • bo: 每秒向块设备(如磁盘)写入的数据量
  • system (系统)

    • in: 每秒的中断次数,包括时钟中断
    • cs: 每秒的上下文切换次数
  • cpu (处理器)

    • us: 用户态(user space)的CPU使用时间百分比
    • sy: 系统态(kernel space)的CPU使用时间百分比
    • id: CPU空闲时间百分比
    • wa: 等待I/O的CPU时间百分比
    • st: 虚拟机的CPU时间百分比(通常在虚拟化环境中看到)

分析进程上下文

stress 是一种用于生成计算机系统的负载的简易工具,可以生成 CPU,内存,磁盘等不同类型的负载,这里用于模拟多进程。

测试环境为 Ubuntu 22.04.3,13th Intel i7-13700KF 16核。

首先测试大于核数的进程数,使用stress --cpu 24生成负载

 

yaml

复制代码

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 29 0 1792 2825936 1219512 19963496 0 0 0 4 0 0 0 0 100 0 0 25 0 1792 2827972 1219512 19963496 0 0 0 100 8026 6308 100 0 0 0 0 24 0 1792 2820320 1219512 19963496 0 0 0 0 6844 3576 100 0 0 0 0 24 0 1792 2818556 1219512 19964264 0 0 0 0 6531 1645 100 0 0 0 0 24 0 1792 2817308 1219512 19964200 0 0 0 0 6401 1490 100 0 0 0 0 27 0 1792 2811288 1219512 19969296 0 0 0 0 6758 2553 100 0 0 0 0 27 0 1792 2811064 1219512 19969564 0 0 0 176 7413 5142 100 0 0 0 0 24 0 1792 2810308 1219512 19969576 0 0 0 0 6805 3572 100 0 0 0 0

与空闲状态相比,首先是 us 占比上升至100,表明 CPU 被大量用户级任务占用,同时中断和上下文切换也显著增加,初步分析是进程时间片耗尽导致时钟中断并进行上下文切换。

使用 pidstat 进一步分析,输出结果如下

 

bash

复制代码

UID PID cswch/s nvcswch/s Command 0 1285221 0.00 170.00 stress 0 1285222 0.00 16.00 stress 0 1285223 0.00 910.00 stress 0 1285224 0.00 30.00 stress 0 1285225 0.00 13.00 stress 0 1285226 0.00 104.00 stress 0 1285227 0.00 117.00 stress 0 1285228 0.00 205.00 stress 0 1285229 0.00 12.00 stress 0 1285230 0.00 15.00 stress 0 1285231 0.00 31.00 stress 0 1285232 0.00 66.00 stress 0 1285233 0.00 29.00 stress 0 1285234 0.00 58.00 stress 0 1285235 0.00 17.00 stress 0 1285236 0.00 49.00 stress 0 1285237 0.00 90.00 stress 0 1285238 0.00 1.00 stress 0 1285239 0.00 27.00 stress 0 1285240 0.00 8.00 stress 0 1285241 0.00 19.00 stress 0 1285242 0.00 15.00 stress 0 1285243 0.00 21.00 stress 0 1285244 0.00 2.00 stress

可以发现 stress 进程每秒均发生1到910不等的非自愿上下文切换。

进一步使用小于硬件线程数的 stress --cpu 16 测试

 

yaml

复制代码

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 16 0 1792 3388348 1220360 19523672 0 0 0 4 0 0 0 0 100 0 0 18 0 1792 3386372 1220360 19523672 0 0 0 0 6182 6361 67 0 33 0 0 16 0 1792 3400048 1220360 19523672 0 0 0 416 6222 4952 67 0 33 0 0 16 0 1792 3405616 1220360 19518212 0 0 0 0 5809 3554 67 0 33 0 0 16 0 1792 3406320 1220360 19517928 0 0 0 0 5565 3400 67 0 33 0 0 16 0 1792 3404624 1220360 19517928 0 0 0 8 5433 2477 67 0 33 0 0 16 0 1792 3407340 1220360 19518192 0 0 0 0 6403 7397 67 0 33 0 0 16 0 1792 3404348 1220360 19518340 0 0 0 276 5467 2384 67 0 33 0 0

 

bash

复制代码

UID PID cswch/s nvcswch/s Command 0 1298009 0.00 0.50 stress 0 1298010 0.00 0.25 stress 0 1298011 0.00 0.75 stress 0 1298012 0.00 1.99 stress 0 1298013 0.00 1.00 stress 0 1298014 0.00 2.74 stress 0 1298015 0.00 1.24 stress 0 1298016 0.00 0.25 stress 0 1298017 0.00 0.75 stress 0 1298018 0.00 2.99 stress 0 1298019 0.00 0.50 stress 0 1298020 0.00 0.25 stress 0 1298021 0.00 1.49 stress 0 1298022 0.00 2.49 stress 0 1298023 0.00 6.72 stress 0 1298024 0.00 1.00 stress

CPU 的占用率下降到 67%,同时非自愿上下文切换也大幅回落,证明在 16 进程的工作负载下 CPU 不是瓶颈。

分析协程上下文

编写一个死循环程序用于模拟计算密集型协程,与进程相同选择24和16作为并发协程数进行测试,测试结果如下:

24 协程:

 

yaml

复制代码

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 24 0 1792 3794916 1220428 19425956 0 0 0 4 0 0 0 0 100 0 0 25 0 1792 3793408 1220428 19426308 0 0 0 96 7891 2697 100 0 0 0 0 24 0 1792 3789436 1220428 19430148 0 0 0 8 8030 3639 100 0 0 0 0 24 0 1792 3789084 1220428 19430152 0 0 0 12 8235 4478 100 0 0 0 0 24 0 1792 3792836 1220428 19430152 0 0 0 0 7769 1902 100 0 0 0 0 24 0 1792 3793128 1220428 19430152 0 0 0 48 7742 1932 100 0 0 0 0 24 0 1792 3792664 1220428 19429960 0 0 0 0 8009 3012 100 0 0 0 0 24 0 1792 3792664 1220428 19429924 0 0 0 296 7750 1971 100 0 0 0 0

16 协程:

 

yaml

复制代码

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 16 0 1792 3717260 1220420 19518996 0 0 0 4 0 0 0 0 100 0 0 16 0 1792 3705428 1220420 19519044 0 0 0 0 6443 2831 67 0 33 0 0 16 0 1792 3701440 1220420 19521092 0 0 0 40 8615 8233 68 0 32 0 0 16 0 1792 3703652 1220420 19521092 0 0 0 44 6601 2933 67 0 33 0 0 16 0 1792 3713864 1220420 19521092 0 0 0 44 6559 3068 67 0 33 0 0 16 0 1792 3712604 1220420 19521092 0 0 0 0 6300 2314 67 0 33 0 0 16 0 1792 3710336 1220420 19521028 0 0 0 40 6448 2508 67 0 33 0 0 16 0 1792 3713736 1220420 19518468 0 0 0 136 6637 3801 67 0 33 0 0

可以看出虽然协程降低了上下文切换成本,但是并不是软件工程的银弹,在面对计算密集型任务时的表现与进程相同。


原文链接:https://juejin.cn/post/7379058697618948096
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值