searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

TeleDB中有关时间的信息

2024-09-10 09:23:10
22
0

问题引入

Redo done的部分会有一个时间统计
WX20240909-093611@2x.png

WX20240909-093645@2x.png

WX20240909-093707@2x.png

对应含义

CPU: user: 用户CPU时间 s, system: 系统CPU时间 s, elapsed: 实际运行时间 s

usage.ru_utime: 用户空间进程所消耗的CPU时间。这个时间指进程花费在运行用户程序(代码)上的时间,如果程序在执行系统调用等操作时被阻塞了,则其在这段时间内消耗的CPU时间是不计入ru_utime中的。

usage.ru_stime:内核空间进程所消耗的CPU时间。这个时间指进程花费在运行内核程序(操作系统代码)上的时间,比如进程运行时要进行系统调用,会调用内核程序,这段时间的CPU时间会被计入ru_stime中。

现实时间/用户CPU时间/系统CPU时间

现实时间

时钟时间(墙上时钟时间wall clock time):从进程从开始运行到结束,时钟走过的时间,这其中包含了进程在阻塞和等待状态的时间。

用户CPU时间

用户CPU时间:就是用户的进程获得了CPU资源以后,在用户态执行的时间。

系统CPU时间

系统CPU时间:用户进程获得了CPU资源以后,在内核态的执行时间。

内核态与用户态

操作系统的核心功能就是管理硬件资源,因此不可避免会使用到一些直接操作硬件的CPU指令,这类指令我们称之为** 特权指令** **​。特权指令如果使用不当,将会导致整个系统的崩溃,因此操作系统提供了一组特殊的资源访问代码 —— **内核 **** kernel ****来负责执行这些指令。

操作系统将虚拟地址空间划分为两部分:

  • 内核空间** **kernel memotry ****:存放内核代码和数据(进程间共享)
  • 用户空间** **user memotry ****:存放用户程序的代码和数据(相互隔离)
    WX20240909-093721@2x.png

通过区分内核空间和用户空间的设计,隔离了操作系统代码与应用程序代码。

即便是单个应用程序出现错误也不会影响到操作系统的稳定性,这样其它的程序还可以正常地运行。

应用程序通过内核提供的接口,访问 CPU、内存、I/O 等硬件资源,我们将该过程称为** **系统调用 **** system call ****。系统调用是操作系统的最小功能单位。

每个进程处于活动状态时,可能处于以下两种状态之一:

  • 执行用户空间的代码时,处于** **用户态
  • 执行内核空间的代码时(系统调用),处于** **内核态

每次执行系统调用时,都需要经历以下变化:

  • CPU** **保存用户态指令,切换为内核态
  • 在内核态下访问系统资源
  • CPU** **恢复用户态指令,切换回用户态

而之前的** **user time ** **system time ****分别就是对应 CPU 在用户态与内核态的运行时间。
WX20240909-093734@2x.png

上下文切换

当发生以下状况时, 线程 会被挂起,并由系统调度其他线程运行:

  • 等待系统资源分配
  • 调用** **sleep ****主动挂起
  • 被优先级更高的线程抢占
  • 发生硬件中断,跳转执行内核的中断服务程序

同个进程下的线程共享进程的用户态空间,因此当同个进程的线程发生切换时,都需要经历以下变化:

  • CPU** **保存线程 A 用户态指令,切换为内核态
  • 保存线程 A 私有资源(栈、 寄存器 …)/li>
  • 加载线程 B 私有资源(栈、寄存器…)
  • CPU** **恢复线程 B 用户态指令,切换回用户态

不同线程的用户态空间资源是相互隔离的,当不同进程的线程发生切换时,都需要经历以下变化:

  • CPU** **保存线程 A 用户态指令,切换为内核态
  • 保存线程 A 私有资源(栈、寄存器…)
  • 保存线程 A 用户态资源(虚拟内存、 全局变量 …)
  • 加载线程 B 用户态资源(虚拟内存、全局变量…)
  • 加载线程 B 私有资源(栈、寄存器…)
  • CPU** **恢复线程 B 用户态指令,切换回用户态

每次保存和恢复上下文的过程,都是在系统态进行的,并且需要几十纳秒到数微秒的 CPU 时间。当切换次数较多时会耗费大量的** **system time **,进而大大缩短了真正运行进程的 **user time ****。

当用户线程过多时,会引起大量的上下文切换,导致不必要的性能开销。

线程调度

Linux 中的线程是从父进程** **fork ****出的轻量进程,它们共享父进程的内存空间。

Linux 的调度策略是抢占式的,每个线程都有优先级** **priority 的概念,并按照优先级高低分为两种:

  • 实时进程(优先级 0~99)
  • 普通进程(优先级 100~139)

每个 CPU 都有自己的运行队列** **runqueue ****,需要运行的线程会被加入到这个队列中。WX20240909-093747@2x.png

每个队列可以进一步细分为 3 个队列以及 5 种调度策略:

  • dl_rqSCHED_DEADLINE **选择 **deadline ****距离当前时间点最近的任务执行
  • rt_rq **—— 可以互相抢占的实时任务 **SCHED_FIFO **一旦抢占到 CPU 资源,就会一直运行直到退出,除非被高优先级抢占 **SCHED_RR ****当 CPU 时间片用完,内核会把它放到队列末尾,可以被高优先级抢占
  • cfs_rq **—— 公平占用 CPU 时间的普通任务 **SCHED_NORMAL **普通进程 **SCHED_BATCH ****后台进程

Linux 内核 在选择下一个任务执行时,会按照该顺序来进行选择,也就是先从** **dl_rq **里选择任务,然后从 **rt_rq **里选择任务,最后从 **cfs_rq ****里选择任务。所以实时任务总是会比普通任务先得到执行。

实时进程的优先级总是高于普通进程,因此当系统中有实时进程运行时,普通进程几乎是无法分到时间片的。

nice 值

为了保证** **cfs_rq **队列的公平性,Linux 采用完全公平调度算法 CFS **Completely Fair Scheduler 进行调度,保证每个普通进程都尽可能被调度到。

CFS 引入了** **vruntime ****作为衡量是否公平的依据:

  • vruntime ****与任务占用的 CPU 时间成正比
  • vruntime **与任务优先级成反比(优先级越高 **vr untime ****增长越慢)

如果一个任务的** **vruntime **较小,说明它以前占用 CPU 的时间较短,受到了 **不公平 **** 对待,因此该进程会被优先调度,从而到达所谓的公平性。

为了实现可控的调度,Linux 为普通进程引入了** **nice **值的概念。其的取值其范围是 **-20 ~ +19 **,调整该值会改变进程的优先级: **prirority += nice ****。

与此同时** **vruntime ****计算也会受到影响:

进程的 nice 值越小, 优先级越高, 所能分到的运行时间也越多

当用户进程设置了一个大于 0 的 nice 值时,其用户态的运行时间将被统计为** **nice time **而不是 **user time **。简单来说, **nice time ****表示 CPU 花了多少时间用于运行低优先级的任务。

当** **nice time **占比比较高时,通常是某些定时任务调度器导致的:它们会为后台任务进程设置一个较大的 **nice ****值,避免这些进程与其他线程争抢 CPU 资源。

软中断

中断就是一种插队机制,可以让操作系统优先处理一些紧急的任务。当硬件设备(例如, 网卡 )需要向 CPU 发出信号时(例如,数据已到达),就会产生硬件中断。

CPU 接收到中断时,会切换到内核态执行特定的中断服务,并且期间不允许其他中断抢占(关中断)。

当中断服务需要执行较长时间时,可能会导致且其他的中断得不到及时的响应。

为了提高中断处理效率,操作系统在之前的基础上把中断处理分成两部分:

  • 上半部** **top half ****:在屏蔽中断的上下文中运行,用于完成关键性的处理动作
  • 下半部** **bottom half ****:不在中断服务上下文中执行,主要处理不那么急迫但耗时的任务

内核在处理完中断上半部后,可以延期执行下半部,该机制被称为 软中断 ​softirq ​。 软中断 处理的过程是不会关中断的,因此当有硬中断到来的时候,可以及时响应。

构成软中断机制的核心元素包括:

  • 注册: 软中断状态寄存器** **irq _stat
  • 处理: 软中断向量表** **softirq_vec
  • 触发: 软中断守护线程** **daemon
    WX20240909-093805@2x.png
  1. 调用** **open_softirq() **将软中断服务程序注册到软中断向量表 **softirq_vec ****(可选)
  2. 调用** **raise_softirq() ****触发软中断事务
  3. 中断关闭的情况下,设置软中断状态位** **irq_stat
  4. 如果调用者不在中断上下文(普通进程调用),那么直接唤醒** **daemon ****线程
  5. daemon **线程被唤醒后会运行 **do_softirq() ****处理软中断
  6. 检查** **irq_stat ****是否存发生软中断事件
  7. 调用** **softirq_vec ****中对应的软中断服务程序
  8. 再次检查** **irq_stat **,如果发现新的软中断,就会唤醒 **ksoftrqd ****线程来处理

ksoftrqd 机制

我们知道 CPU 执行的优先级为:硬中断 > 软中断 > 普通进程。

这意味着:

  • 一个软中断不会去抢占另一个软中断,只有硬件中断才可以抢占软中断
  • 如果软中断太过频繁,用户进程可能永远无法获得 CPU 时间

为了保证公平性,内核为每个 CPU 都配置一个** **ksoftrqd **线程。如果所有的软中断在短时间内无法被处理完,内核就会唤醒 **ksoftrqd ****处理剩余的软中断。以下面这张图为例:
WX20240909-093816@2x.png

  • 网卡数据就绪,通过硬中断通知** CPU **进行处理
  • 硬中断服务程序调用** **raise_softirq() **触发软中断,唤醒 **daemon
  • 硬中断服务程序退出后,** **daemon ****被唤醒开始处理软中断
  • 遍历过一遍向量表后,** **daemon **发现仍有未处理的软中断,唤醒 **ksoftrqd
  • ksoftrqd ****获得 CPU 时间片后,继续处理未完成的软中断

由于** **ksoftrqd **其实是一个 **nice **值为 0 的普通线程,会进入 **cfs_rq ****参与调度,可以和普通进程公平地使用 CPU。

但如果** **ksoftrirqd **长时间得不到 CPU,就会致使软中断的延迟变得很大,因此 **ksoftirqd ****的实时性是很难得到保障。

典型问题是 ping 延迟:如果 ping 包无法在软中断里得到处理,就会被** **ksoftirqd ****处理,导致 ping 延迟变得很大。

中断的影响

硬中断的优先级很高,但是需要的 CPU 时间极少。当出现大量硬中断时,可能会引起较多的 CPU 用户态与内核态的切换,但是** **interrupt time ****不会显著上升。

此外,由于部分内核代码是不可重入的(例如,修改寄存器),其执行过程不能打断。因此这些代码的执行过程中,会屏蔽掉硬中断。

关中断的操作在内核里随处可见,这反过来会给硬中断带来一些影响。比如,进程关中断时间太长会导致网络报文无法及时处理,进而引起业务性能抖动。

而软中断的执行时间如果太长,就会给用户线程带来延迟,如果** **softirq time ****很大则很可能意味着用户线程会受到影响。

网络 IO 频繁的应用机器的** **softirq time ****通常会比较高,可能存在网络连接数过多,或者网络流量过大的情况,

ksoftirqd **的优先级与用户线程是一致的,因此,如果软中断处理函数是在 **ksoftirqd ****里执行的,那它可能会有一些延迟。

时间窃取

在 GNU top命令中,** **steal time **定义为 “虚拟机管理进程 **hypervisor 从 VM 窃取的时间”。 该概念是Xen,KVM, VMware 等社区或者厂商推广到Linux社区的。

当系统管理进程和 VM 尝试占用同一物理 CPU 核** **pCPU **时,会导致 VM 的虚拟 CPU **vCPU 可用的处理器时间减少,从而造成 VM 性能下降。

中虚拟化环境中,可能发生时间窃取的一些情况:

  • 多个高负载** VM vCPU 的运行在同个 **pCPU ****上(公有云的 CPU 超卖)
  • VM** vCPU 与线程绑定在了某个特定的 **pCPU **上,导致虚拟主机 **vhost **进程处理 I/O 时从这些 **vCPU ****上窃取时间
  • 虚拟机监控程序进程(例如监视,日志记录和I/O进程)与** VM 争抢 **pCPU
0条评论
0 / 1000
f****n
3文章数
0粉丝数
f****n
3 文章 | 0 粉丝
f****n
3文章数
0粉丝数
f****n
3 文章 | 0 粉丝
原创

TeleDB中有关时间的信息

2024-09-10 09:23:10
22
0

问题引入

Redo done的部分会有一个时间统计
WX20240909-093611@2x.png

WX20240909-093645@2x.png

WX20240909-093707@2x.png

对应含义

CPU: user: 用户CPU时间 s, system: 系统CPU时间 s, elapsed: 实际运行时间 s

usage.ru_utime: 用户空间进程所消耗的CPU时间。这个时间指进程花费在运行用户程序(代码)上的时间,如果程序在执行系统调用等操作时被阻塞了,则其在这段时间内消耗的CPU时间是不计入ru_utime中的。

usage.ru_stime:内核空间进程所消耗的CPU时间。这个时间指进程花费在运行内核程序(操作系统代码)上的时间,比如进程运行时要进行系统调用,会调用内核程序,这段时间的CPU时间会被计入ru_stime中。

现实时间/用户CPU时间/系统CPU时间

现实时间

时钟时间(墙上时钟时间wall clock time):从进程从开始运行到结束,时钟走过的时间,这其中包含了进程在阻塞和等待状态的时间。

用户CPU时间

用户CPU时间:就是用户的进程获得了CPU资源以后,在用户态执行的时间。

系统CPU时间

系统CPU时间:用户进程获得了CPU资源以后,在内核态的执行时间。

内核态与用户态

操作系统的核心功能就是管理硬件资源,因此不可避免会使用到一些直接操作硬件的CPU指令,这类指令我们称之为** 特权指令** **​。特权指令如果使用不当,将会导致整个系统的崩溃,因此操作系统提供了一组特殊的资源访问代码 —— **内核 **** kernel ****来负责执行这些指令。

操作系统将虚拟地址空间划分为两部分:

  • 内核空间** **kernel memotry ****:存放内核代码和数据(进程间共享)
  • 用户空间** **user memotry ****:存放用户程序的代码和数据(相互隔离)
    WX20240909-093721@2x.png

通过区分内核空间和用户空间的设计,隔离了操作系统代码与应用程序代码。

即便是单个应用程序出现错误也不会影响到操作系统的稳定性,这样其它的程序还可以正常地运行。

应用程序通过内核提供的接口,访问 CPU、内存、I/O 等硬件资源,我们将该过程称为** **系统调用 **** system call ****。系统调用是操作系统的最小功能单位。

每个进程处于活动状态时,可能处于以下两种状态之一:

  • 执行用户空间的代码时,处于** **用户态
  • 执行内核空间的代码时(系统调用),处于** **内核态

每次执行系统调用时,都需要经历以下变化:

  • CPU** **保存用户态指令,切换为内核态
  • 在内核态下访问系统资源
  • CPU** **恢复用户态指令,切换回用户态

而之前的** **user time ** **system time ****分别就是对应 CPU 在用户态与内核态的运行时间。
WX20240909-093734@2x.png

上下文切换

当发生以下状况时, 线程 会被挂起,并由系统调度其他线程运行:

  • 等待系统资源分配
  • 调用** **sleep ****主动挂起
  • 被优先级更高的线程抢占
  • 发生硬件中断,跳转执行内核的中断服务程序

同个进程下的线程共享进程的用户态空间,因此当同个进程的线程发生切换时,都需要经历以下变化:

  • CPU** **保存线程 A 用户态指令,切换为内核态
  • 保存线程 A 私有资源(栈、 寄存器 …)/li>
  • 加载线程 B 私有资源(栈、寄存器…)
  • CPU** **恢复线程 B 用户态指令,切换回用户态

不同线程的用户态空间资源是相互隔离的,当不同进程的线程发生切换时,都需要经历以下变化:

  • CPU** **保存线程 A 用户态指令,切换为内核态
  • 保存线程 A 私有资源(栈、寄存器…)
  • 保存线程 A 用户态资源(虚拟内存、 全局变量 …)
  • 加载线程 B 用户态资源(虚拟内存、全局变量…)
  • 加载线程 B 私有资源(栈、寄存器…)
  • CPU** **恢复线程 B 用户态指令,切换回用户态

每次保存和恢复上下文的过程,都是在系统态进行的,并且需要几十纳秒到数微秒的 CPU 时间。当切换次数较多时会耗费大量的** **system time **,进而大大缩短了真正运行进程的 **user time ****。

当用户线程过多时,会引起大量的上下文切换,导致不必要的性能开销。

线程调度

Linux 中的线程是从父进程** **fork ****出的轻量进程,它们共享父进程的内存空间。

Linux 的调度策略是抢占式的,每个线程都有优先级** **priority 的概念,并按照优先级高低分为两种:

  • 实时进程(优先级 0~99)
  • 普通进程(优先级 100~139)

每个 CPU 都有自己的运行队列** **runqueue ****,需要运行的线程会被加入到这个队列中。WX20240909-093747@2x.png

每个队列可以进一步细分为 3 个队列以及 5 种调度策略:

  • dl_rqSCHED_DEADLINE **选择 **deadline ****距离当前时间点最近的任务执行
  • rt_rq **—— 可以互相抢占的实时任务 **SCHED_FIFO **一旦抢占到 CPU 资源,就会一直运行直到退出,除非被高优先级抢占 **SCHED_RR ****当 CPU 时间片用完,内核会把它放到队列末尾,可以被高优先级抢占
  • cfs_rq **—— 公平占用 CPU 时间的普通任务 **SCHED_NORMAL **普通进程 **SCHED_BATCH ****后台进程

Linux 内核 在选择下一个任务执行时,会按照该顺序来进行选择,也就是先从** **dl_rq **里选择任务,然后从 **rt_rq **里选择任务,最后从 **cfs_rq ****里选择任务。所以实时任务总是会比普通任务先得到执行。

实时进程的优先级总是高于普通进程,因此当系统中有实时进程运行时,普通进程几乎是无法分到时间片的。

nice 值

为了保证** **cfs_rq **队列的公平性,Linux 采用完全公平调度算法 CFS **Completely Fair Scheduler 进行调度,保证每个普通进程都尽可能被调度到。

CFS 引入了** **vruntime ****作为衡量是否公平的依据:

  • vruntime ****与任务占用的 CPU 时间成正比
  • vruntime **与任务优先级成反比(优先级越高 **vr untime ****增长越慢)

如果一个任务的** **vruntime **较小,说明它以前占用 CPU 的时间较短,受到了 **不公平 **** 对待,因此该进程会被优先调度,从而到达所谓的公平性。

为了实现可控的调度,Linux 为普通进程引入了** **nice **值的概念。其的取值其范围是 **-20 ~ +19 **,调整该值会改变进程的优先级: **prirority += nice ****。

与此同时** **vruntime ****计算也会受到影响:

进程的 nice 值越小, 优先级越高, 所能分到的运行时间也越多

当用户进程设置了一个大于 0 的 nice 值时,其用户态的运行时间将被统计为** **nice time **而不是 **user time **。简单来说, **nice time ****表示 CPU 花了多少时间用于运行低优先级的任务。

当** **nice time **占比比较高时,通常是某些定时任务调度器导致的:它们会为后台任务进程设置一个较大的 **nice ****值,避免这些进程与其他线程争抢 CPU 资源。

软中断

中断就是一种插队机制,可以让操作系统优先处理一些紧急的任务。当硬件设备(例如, 网卡 )需要向 CPU 发出信号时(例如,数据已到达),就会产生硬件中断。

CPU 接收到中断时,会切换到内核态执行特定的中断服务,并且期间不允许其他中断抢占(关中断)。

当中断服务需要执行较长时间时,可能会导致且其他的中断得不到及时的响应。

为了提高中断处理效率,操作系统在之前的基础上把中断处理分成两部分:

  • 上半部** **top half ****:在屏蔽中断的上下文中运行,用于完成关键性的处理动作
  • 下半部** **bottom half ****:不在中断服务上下文中执行,主要处理不那么急迫但耗时的任务

内核在处理完中断上半部后,可以延期执行下半部,该机制被称为 软中断 ​softirq ​。 软中断 处理的过程是不会关中断的,因此当有硬中断到来的时候,可以及时响应。

构成软中断机制的核心元素包括:

  • 注册: 软中断状态寄存器** **irq _stat
  • 处理: 软中断向量表** **softirq_vec
  • 触发: 软中断守护线程** **daemon
    WX20240909-093805@2x.png
  1. 调用** **open_softirq() **将软中断服务程序注册到软中断向量表 **softirq_vec ****(可选)
  2. 调用** **raise_softirq() ****触发软中断事务
  3. 中断关闭的情况下,设置软中断状态位** **irq_stat
  4. 如果调用者不在中断上下文(普通进程调用),那么直接唤醒** **daemon ****线程
  5. daemon **线程被唤醒后会运行 **do_softirq() ****处理软中断
  6. 检查** **irq_stat ****是否存发生软中断事件
  7. 调用** **softirq_vec ****中对应的软中断服务程序
  8. 再次检查** **irq_stat **,如果发现新的软中断,就会唤醒 **ksoftrqd ****线程来处理

ksoftrqd 机制

我们知道 CPU 执行的优先级为:硬中断 > 软中断 > 普通进程。

这意味着:

  • 一个软中断不会去抢占另一个软中断,只有硬件中断才可以抢占软中断
  • 如果软中断太过频繁,用户进程可能永远无法获得 CPU 时间

为了保证公平性,内核为每个 CPU 都配置一个** **ksoftrqd **线程。如果所有的软中断在短时间内无法被处理完,内核就会唤醒 **ksoftrqd ****处理剩余的软中断。以下面这张图为例:
WX20240909-093816@2x.png

  • 网卡数据就绪,通过硬中断通知** CPU **进行处理
  • 硬中断服务程序调用** **raise_softirq() **触发软中断,唤醒 **daemon
  • 硬中断服务程序退出后,** **daemon ****被唤醒开始处理软中断
  • 遍历过一遍向量表后,** **daemon **发现仍有未处理的软中断,唤醒 **ksoftrqd
  • ksoftrqd ****获得 CPU 时间片后,继续处理未完成的软中断

由于** **ksoftrqd **其实是一个 **nice **值为 0 的普通线程,会进入 **cfs_rq ****参与调度,可以和普通进程公平地使用 CPU。

但如果** **ksoftrirqd **长时间得不到 CPU,就会致使软中断的延迟变得很大,因此 **ksoftirqd ****的实时性是很难得到保障。

典型问题是 ping 延迟:如果 ping 包无法在软中断里得到处理,就会被** **ksoftirqd ****处理,导致 ping 延迟变得很大。

中断的影响

硬中断的优先级很高,但是需要的 CPU 时间极少。当出现大量硬中断时,可能会引起较多的 CPU 用户态与内核态的切换,但是** **interrupt time ****不会显著上升。

此外,由于部分内核代码是不可重入的(例如,修改寄存器),其执行过程不能打断。因此这些代码的执行过程中,会屏蔽掉硬中断。

关中断的操作在内核里随处可见,这反过来会给硬中断带来一些影响。比如,进程关中断时间太长会导致网络报文无法及时处理,进而引起业务性能抖动。

而软中断的执行时间如果太长,就会给用户线程带来延迟,如果** **softirq time ****很大则很可能意味着用户线程会受到影响。

网络 IO 频繁的应用机器的** **softirq time ****通常会比较高,可能存在网络连接数过多,或者网络流量过大的情况,

ksoftirqd **的优先级与用户线程是一致的,因此,如果软中断处理函数是在 **ksoftirqd ****里执行的,那它可能会有一些延迟。

时间窃取

在 GNU top命令中,** **steal time **定义为 “虚拟机管理进程 **hypervisor 从 VM 窃取的时间”。 该概念是Xen,KVM, VMware 等社区或者厂商推广到Linux社区的。

当系统管理进程和 VM 尝试占用同一物理 CPU 核** **pCPU **时,会导致 VM 的虚拟 CPU **vCPU 可用的处理器时间减少,从而造成 VM 性能下降。

中虚拟化环境中,可能发生时间窃取的一些情况:

  • 多个高负载** VM vCPU 的运行在同个 **pCPU ****上(公有云的 CPU 超卖)
  • VM** vCPU 与线程绑定在了某个特定的 **pCPU **上,导致虚拟主机 **vhost **进程处理 I/O 时从这些 **vCPU ****上窃取时间
  • 虚拟机监控程序进程(例如监视,日志记录和I/O进程)与** VM 争抢 **pCPU
文章来自个人专栏
TeleDB
1 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0