本文是由字节跳动系统部 STE 团队出品的“kernel trace tools”系列文章之一,以介绍团队自研多类延迟问题追踪工具。
在实际工作中,会遇到由于 runqueue 太长导致调度延迟问题,我们想知道是哪些进程导致了延迟。但是,对于该类问题的定位和追踪缺乏行之有效的方案或客观依据,需要耗费大量时间和精力用于问题排查,trace-runqlat 工具便是在该背景下诞生的自研工具。
目前,trace-runqlat 已开源,如感兴趣详见 Open Source Repo (https://github.com/bytedance/trace-runqlat)
1. 问题背景
Trace_irqoff (https://github.com/bytedance/trace-irqoff/tree/master) 工具(之前已经开源)可以帮助我们排查由于中断被关闭导致的延迟抖动问题。但是这只是第一阶段可能遇到的问题。当我们将一个线程加入 runqueue 后,如果系统的负载很高,在 runqueue 中排在你前面的进程可能会由于执行很长时间(或许你会好奇怎么可能执行很长时间,难道不会抢占吗?还真可能出现这种情况。因为我们的 kernel 是不开抢占的。当然除此之外,负载很高 runqueue 长度很长,也会出问题)最终导致调度延迟很大。针对这种问题排查,我们开发一款新的排查工具Run queue latency tracer简称:trace-runqlat。 作用是记录被跟踪的进程在加入 runqueue 后,前面的每个线程执行的时间及线程 command 等信息。
2. 我们想做什么
在此之前开源工具 trace-noschedule (https://github.com/bytedance/trace-noschedule) 中,我们已经可以借助这个工具排查内核态不抢占导致的延迟问题。而 trace-runqlat 更多的是关注 runqueue 上每个进程是谁,并且 runqueue 有多长。首先,是否有现成的工具已经实现功能了呢?据我所知,bcc 存在 2 款工具 runqlen 和 runqlat。runqlen 显示的是每个 CPU 的就绪队列的长度分布柱状图。runqlat 可以针对某个特定 pid 绘制调度延迟柱状图。他们似乎很符合我们的需求。虽然我们知道了某个进程调度延迟很高。但是我们不知道是受到哪些进程的影响。你可能会有疑问,知道是谁有意义吗?当然有意义。对于混合部署来说,我们肯定希望优先保证在线业务,如果发现影响调度延迟的进程是离线业务进程,这对于我们进一步混部有一定指导意义。例如,我们是否应该考虑绑核?或者调整优先级?
3. 如何实现
我们先定义一下调度延迟。调度延迟是指从进程被加入 runqueue 到开始执行的时间差。进程挂在 runqueue 中,我们称进程处于 runnable 状态,开始执行时为 running 状态。所以调度延迟是进程从 runnable 态切换 running 状态的时间。为了计算调度延迟,我们需要知道 2 个时间