在实时 Linux、工业控制和机器人运动控制系统中测试报告里经常会出现这样的结果平均延迟只有几微秒绝大多数周期都运行正常但设备偶尔还是会出现控制周期超时、伺服抖动或者通信数据更新不及时的问题。为什么平均延迟已经很低系统仍然可能不满足实时要求问题往往出在测试指标的理解上。平均值可以描述整体表现却可能掩盖少量异常样本P99 可以描述分布的尾部却不能直接证明系统满足硬实时要求最大观测延迟反映的是已经采集到的样本也不能自动等同于理论最坏情况。而“抖动”这个词在不同测试工具和工程场景中甚至可能指不同的量。如果没有明确指标的定义、测量起止点、测试时长和样本数量即使两个系统都声称“延迟只有几微秒”它们的结果也可能完全不可比较。本文从实时系统测试的角度介绍平均延迟、百分位延迟、最大观测延迟、周期抖动和截止时间违约之间的区别并结合 Linux 实时任务、EtherCAT 控制和机器人应用说明怎样建立更有意义的测试方法。一、平均延迟为什么会掩盖实时系统的问题首先需要区分两个概念延迟的平均水平以及延迟是否始终满足任务的时间要求。假设一个控制任务每隔 1 ms 运行一次。工程师使用测试程序采集了大量唤醒延迟样本结果发现平均延迟很低。这个结果可以说明在本次测试条件下任务大部分时候能够比较及时地获得 CPU但它并不能直接说明每个周期都满足要求。原因是平均值会把所有样本汇总为一个数字。少量非常大的延迟可能被大量较小的延迟稀释。例如下面是一组纯粹用于说明统计方法的假设数据并非任何产品或平台的实测结果。假设某项测试采集了 10,000 个样本样本类型数量延迟普通样本9,9905 μs长尾样本101000 μs这组数据的平均延迟为[\bar{x}\frac{9990\times510\times1000}{10000}5.995\ \mu s]从平均值看延迟不到 6 μs似乎表现不错。但在这 10,000 个样本中有 10 个样本的延迟达到了 1000 μs。如果这些样本代表一个控制任务的实际唤醒迟到而该任务要求每 1 ms 执行一次那么部分样本可能已经耗尽整个周期的时间预算。若任务还需要执行控制计算、数据交换和输出更新就更不能仅凭平均唤醒延迟判断其是否按时完成。这里还要特别注意1000 μs 的唤醒延迟并不必然等于 1000 μs 的任务响应时间也不必然意味着该周期已经错过截止时间。最终是否违约要看任务实际的释放时刻、开始执行时刻、完成时刻和截止时间定义。因此分析实时系统时第一个原则是平均延迟只能描述整体水平不能单独用于判断实时任务是否满足时间约束。1. 先明确自己测量的到底是什么实时系统中的“延迟”并不是一个统一的指标。至少需要区分以下几种情况。指标含义主要用途唤醒延迟任务预期被唤醒的时刻与实际开始运行之间的时间差分析定时唤醒和调度表现任务执行时间任务开始执行到本次执行完成所经历的时间分析算法和处理路径的执行开销任务响应时间任务释放到完成之间的时间判断任务能否在截止时间前完成端到端延迟从指定输入事件到指定输出事件之间的时间分析完整控制链路周期误差实际周期与目标周期之间的差异分析周期稳定性截止时间违约任务完成时刻超过规定截止时间判断时间约束是否被违反这些指标之间存在联系但不能相互替代。例如cyclictest主要用于测量周期定时唤醒的延迟。它可以帮助工程师了解内核和系统环境中的定时唤醒表现却不能直接代表 EtherCAT 从站的数据更新时间也不能代表机器人控制算法从读取反馈到生成输出的完整耗时。同样应用程序记录的函数执行时间也不一定等于端到端延迟。假设控制算法本身只执行了 100 μs但输入数据在进入算法前已经等待了 500 μs那么仅测量算法函数耗时就会低估整个数据处理链路的延迟。因此在讨论平均延迟之前应当先明确测量对象、起止点以及它与实际控制需求之间的关系。2. 平均值适合做什么平均值仍然有用。它适合观察整体趋势、比较常规负载下的运行开销以及分析某项优化是否改变了总体表现。例如在相同硬件、相同内核、相同测试程序和相同负载下比较优化前后的平均唤醒延迟可以帮助判断系统的常规调度表现是否发生变化。但如果优化前后分别使用了不同测试时长、不同 CPU 绑定方式或者不同统计口径那么平均值的差异就很难直接归因于某一项优化。平均值应当与样本数量、分布形态、长尾指标和截止时间违约情况结合起来看而不是作为实时系统验收的唯一依据。二、P95、P99、P99.9 和最大观测延迟分别说明什么为了理解平均值无法表达的尾部行为工程师通常会分析百分位延迟。百分位描述的是在按照延迟从小到大排序的样本中某个百分比位置对应的延迟水平。例如P99 通常表示约 99% 的样本延迟不高于该值剩余约 1% 的样本位于其上方。实际计算时不同统计软件可能采用不同的百分位插值方法因此进行严格对比时还需要明确所采用的计算方法。1. P95观察主要样本的表现P95 表示约 95% 的样本不高于该延迟值。它适合观察常规运行期间的大部分样本表现。例如系统增加普通业务负载后P95 是否明显变大可以帮助判断多数周期是否受到了持续性的干扰。但 P95 并不关注最末端的 5% 样本。对于对截止时间要求严格的系统这部分样本可能恰好包含需要重点分析的异常。2. P99观察更靠近尾部的样本P99 比 P95 更关注延迟分布的尾部。如果普通样本延迟很低但少量样本明显变大P99 往往比平均值更容易体现这种变化。不过P99 仍然是一项统计描述而不是实时保证。假设一个系统测得 P99 为 20 μs并不能由此推出每个周期都能在 20 μs 内完成也不能证明系统不会出现 500 μs 或更长的延迟。对于硬实时控制任务哪怕违约概率看起来很低只要存在不能接受的截止时间违约风险就需要进一步分析原因和控制措施。3. P99.9观察更少见的长尾样本P99.9 表示约 99.9% 的样本不高于该值剩余约 0.1% 的样本位于其上方。这一指标对样本数量尤其敏感。假设测试只采集了 1,000 个样本那么 0.1% 对应的样本数只有 1 个。不同百分位计算方法可能会让 P99.9 接近最大样本或者对其进行插值。这种情况下P99.9 的数值并不一定具有稳定的统计意义。如果希望研究更罕见的长尾事件就需要足够的样本数量、足够长的测试时间以及能够捕获异常发生条件的监测手段。4. 最大观测延迟测试期间出现过的最大值最大观测延迟是本次采样中记录到的最大延迟。它有重要价值因为某次长尾异常可能直接触发了任务截止时间违约。但最大值也容易被误解。首先测试没有捕获到某种异常不代表该异常永远不会发生。其次测试时间越长采集到罕见事件的机会通常越多因此不同测试时长下的最大值不能不加区分地比较。最后测量工具、采样方式和系统负载也可能影响实际记录到的最大值。所以工程报告中更准确的表述是“在某测试条件和测试时长下观测到的最大延迟为多少”而不是把它直接写成“系统的最坏延迟”。真正的最坏执行时间分析通常还涉及任务执行路径、资源竞争、硬件行为和调度条件等因素不能仅靠一次压力测试就获得完整证明。5. 用一组指标描述同一份数据假设两组测试具有相同的硬件、内核配置、测试程序、负载和统计口径得到以下结果。表中的数值仅为示例用于说明不同指标可能呈现的差异。指标测试 A测试 B平均延迟5 μs6 μsP958 μs9 μsP9912 μs25 μsP99.920 μs180 μs最大观测延迟35 μs900 μs如果只比较平均值测试 A 和测试 B 的差距似乎很小。但从 P99.9 和最大观测延迟来看测试 B 出现了更明显的长尾行为。这时工程师不应只问“平均值为什么增加了 1 μs”还应追问测试 B 是否出现了新的调度等待、IRQ 干扰、锁竞争、内存回收或业务过载这些异常是否与目标控制任务的截止时间发生了直接关系统计指标可以提示问题但不能单独证明根因。要确定原因还需要结合应用时间戳、调度轨迹、IRQ 事件和负载记录进行分析。三、实时系统中的抖动不能只用一个数字解释“抖动”是实时系统中非常常见的词但不同工程师所说的抖动可能指完全不同的现象。有的人用它描述周期任务的启动时刻变化有的人关注连续两次执行之间的时间间隔还有的人把最大延迟减去最小延迟作为抖动范围。若不明确口径单独报告“抖动为 10 μs”并没有足够的信息。1. 周期误差与唤醒延迟不是一回事假设某个周期任务的目标周期为 1 ms预期释放时刻分别为[t_nt_0nT]其中(T1\text{ ms})。如果实际开始执行的时刻为 (s_n)那么本次任务的启动迟到可以定义为[L_ns_n-t_n]这里的 (L_n) 描述的是相对于预期释放时刻的偏差。而连续两次实际开始执行之间的周期则是[T_ns_{n1}-s_n]周期误差可以定义为[E_nT_n-T]这两个量的含义不同。例如如果某次任务迟到 20 μs而下一次任务又迟到 5 μs那么连续两次实际开始执行的间隔可能比目标周期短 15 μs。单独查看每次启动迟到可以发现任务何时没有准时开始查看连续周期误差则更容易观察实际运行节奏的变化。在实际系统中还需要明确任务是否采用绝对时间周期、是否发生跳周期、是否存在追赶执行以及时间戳是否来自同一时钟域。2. 延迟范围不等于完整的实时性描述有些测试报告使用以下定义[J_{\text{range}}L_{\max}-L_{\min}]它表示测试样本中最大延迟与最小延迟之间的差值可以用于描述观测延迟的范围。但这种定义并不等于所有场景下唯一的抖动定义。例如某任务每次都稳定迟到 100 μs那么延迟范围可能很小但如果任务的截止时间只允许 50 μs 的响应时间这个系统仍然不满足要求。相反一个任务的延迟分布可能存在一定变化但只要在规定的系统模型和运行条件下任务仍能满足其截止时间要求就不能仅凭抖动范围较大直接判定系统不合格。因此抖动分析需要结合目标周期、截止时间、实际启动时刻和完成时刻一起进行。3. 任务启动稳定不代表端到端链路稳定在工业控制系统中还需要区分操作系统层面的周期抖动与整个控制链路的时序变化。以 EtherCAT 运动控制为例完整链路可能包括周期任务按计划释放。主站周期线程开始运行。输入过程数据被读取。控制算法计算目标输出。输出过程数据被更新。主站完成必要的数据交换。从站按照自身时钟与同步配置处理数据。驱动器和机械系统产生实际响应。即使控制线程的启动迟到很稳定也不能由此证明整个链路没有抖动。数据可能在进入控制线程前已经过期也可能在输出更新之后等待设备处理还可能受到从站同步配置、伺服内部周期、反馈滤波和机械系统动态特性的影响。同样EtherCAT 的工作计数器正常只能说明相应通信状态满足特定条件并不能独立证明控制算法按时执行或者输出在预期时刻被设备采用。要分析端到端抖动需要先明确起点和终点再为关键环节添加时间戳并尽可能对齐不同设备的时钟。若不同测量点使用不同时间基准必须考虑时钟偏差和同步误差否则测得的差值可能包含时钟误差。四、如何采集与分析数据从 cyclictest 到真实控制任务理解指标后下一步是建立可重复的测试流程。这里的目标不是找到一个尽可能小的数字而是确认系统在明确条件下的行为并识别长尾异常来自哪里。1. 用 cyclictest 建立基础唤醒延迟基线在支持相应工具和配置的 Linux 系统中可以先使用cyclictest观察周期定时唤醒延迟。例如sudo cyclictest -m -p 80 -i 1000 -D 60s这个命令是一个测试示例使用内存锁定相关选项、设置实时优先级并以 1000 μs 为测试间隔运行 60 秒。具体选项含义和支持情况应以当前版本的cyclictest --help为准。运行时还可能受到权限、实时资源限制和内核配置的影响。执行测试前需要明确几个问题测试线程运行在哪个 CPU 上是否存在其他实时线程或高负载业务测试时间是否足以覆盖目标异常输出是否能够提供所需的统计信息当前测试的是空载基线还是实际业务负载下的结果建议先在相对空闲的条件下采集基线再逐步增加业务负载。不要只在空载环境中测试一次就将结果作为真实控制系统的性能结论。2. 将测试条件记录完整为了让测试结果可以复现建议建立统一的测试记录表。记录项需要记录的内容硬件CPU 型号、核心拓扑、内存和关键外设软件环境内核版本、内核配置、启动参数、驱动版本任务配置调度策略、优先级、CPU 亲和性、目标周期业务负载网络流量、日志量、数据采集、算法负载等测试范围测试时长、样本数、测量起止点统计指标平均值、P95、P99、P99.9、最大观测延迟任务结果截止时间违约次数、实际完成时间异常证据应用日志、调度轨迹、IRQ 记录和系统状态如果比较不同内核、不同实时配置或者不同操作系统方案应尽量保持硬件、驱动、应用程序、业务负载和统计口径一致。否则测得的差异可能来自其他变量无法直接归因于内核或调度机制。3. 发生长尾异常时如何进一步定位假设cyclictest的平均延迟变化不大但 P99.9 和最大观测延迟明显上升。此时应当把问题转化为具体的时间线分析。可以先检查目标线程和中断分布ps -eLo pid,tid,psr,cls,rtprio,pri,ni,stat,comm cat /proc/interrupts如果系统提供相应的 tracepoint可以进一步使用trace-cmd记录调度事件和中断事件。例如sudo trace-cmd record \ -e sched:sched_wakeup \ -e sched:sched_switch \ -e irq:irq_handler_entry \ -e irq:irq_handler_exit \ sleep 10 sudo trace-cmd report这些事件是否存在、名称是否一致以及能否获得预期信息都取决于内核版本和配置。开始前应先检查当前系统支持的事件详细追踪也可能产生额外开销因此应控制记录时长和事件范围。分析时可以依次回答第一目标线程是否按预期时间被唤醒第二线程被唤醒之后是否因为其他任务或中断而迟迟没有获得 CPU第三线程开始运行之后是否发生了额外抢占或阻塞第四实际延迟是否与某个中断、业务负载或系统事件同时出现第五在关闭或调整相关负载后异常是否能够稳定复现或明显减少要注意事件在时间上相邻并不等于存在因果关系。需要通过重复测试和对照实验验证推断。对于真实控制任务还应增加应用层时间戳记录任务计划释放、实际开始、控制计算完成和输出更新的时刻。只有这样才能将内核层面的唤醒延迟与完整任务响应时间联系起来。4. 统计工具不能代替任务级验收即使cyclictest的统计结果很好真实控制程序仍然可能因为锁等待、通信阻塞、算法执行时间变化或者设备数据处理方式而超时。因此实际项目至少应当同时建立两类测试一类是系统基础测试用于观察内核定时唤醒和调度环境的表现。另一类是业务级测试用于记录真实控制任务的执行时间、周期误差、数据新鲜度、端到端延迟和截止时间违约情况。如果应用使用 EtherCAT、串口或其他现场总线还需要根据具体数据路径增加相应测量点。测量点的起止定义应当保持稳定否则优化前后的结果就失去了可比性。五、如何判断测试是否达标从统计表现走向时间约束验证实时系统的验收不能简单地规定“平均延迟小于某个值”也不能只看 P99 或最大观测延迟。更合理的方式是从任务的时间约束出发结合统计分析、异常定位和系统级测试建立明确的验收条件。1. 把截止时间违约作为核心指标之一假设一个任务在释放时刻 (r_i) 被要求执行并在截止时间 (d_i) 前完成实际完成时刻为 (f_i)。可以将任务的响应时间表示为[R_if_i-r_i]如果规定的相对截止时间为 (D_i)那么在相应的任务模型下只有当[R_i\leq D_i]任务才满足该次执行的截止时间要求。这比只观察启动迟到更加接近实际控制需求因为任务即使及时开始运行也可能由于计算时间过长而无法按时完成。对于周期控制任务还需要确认截止时间究竟相对于任务释放时刻、下一个周期边界还是某个设备输出事件定义。不同系统可能采用不同的时序模型必须在测试前明确。2. 不同指标应该回答不同问题可以用以下思路解读测试报告平均延迟系统整体的常规表现如何P95 和 P99大部分任务的延迟分布是否发生变化P99.9更靠近尾部的样本是否出现明显恶化最大观测延迟本次测试中最严重的延迟达到什么水平周期误差任务的执行节奏是否稳定任务响应时间任务从释放到完成需要多长时间截止时间违约次数在本次测试条件下有多少次任务未能按时完成端到端延迟从指定输入事件到指定输出事件整个链路经历了多长时间这些指标应当联合分析。没有任何一个统计值能够独立替代全部其他指标。3. 零违约不等于永远不会违约假设某系统运行了很长时间测试中没有观察到任何截止时间违约。这是有价值的证据但其含义应当限定在实际测试条件和测试覆盖范围内。如果需要进一步评估罕见事件的发生风险可以结合样本量、测试时长和统计假设进行分析。但即使采用统计方法也需要明确其前提条件真实系统中的延迟样本往往存在相关性并不一定满足简单独立同分布假设。对于硬实时或高安全要求系统还需要结合任务模型、资源竞争分析、硬件和驱动行为、故障模式以及系统安全需求建立更充分的验证证据不能仅凭长时间测试未出现异常就作出绝对保证。4. 建立可执行的验收流程一套实用的实时系统验收流程可以归纳为以下几个步骤明确需求。为每个关键任务定义周期、截止时间、响应时间和端到端测量范围。建立基线。记录系统配置、基础唤醒延迟、业务任务执行时间和实际负载。定义统计口径。确定样本数、测试时长、百分位算法、最大观测值和违约判定方式。开展压力测试。覆盖业务高负载、长时间运行、通信异常和资源压力等场景。分析异常。对长尾样本进行应用层与内核层关联分析验证可能的根因。复测与回归。在修复或优化后用同样的条件重复测试并确认没有引入新的问题。形成验收记录。保存环境、配置、测试脚本、结果数据和异常证据使后续升级能够复现比较。在望获OS或其他实时 Linux 平台的工程评估中也应遵循同样的原则。不能只比较某次测试报告中的平均延迟或最大观测值而应当在相同的硬件、驱动、业务负载和测量口径下验证目标应用的完整执行链路是否满足时间约束。最终实时系统追求的不是一个尽可能漂亮的平均值而是在明确的运行条件下让关键任务能够按规定时间完成并且能够通过可复现的测试与分析证明这一点。
阅读完成 · 觉得有帮助?