一、背景与目的
线上会偶现高延迟的处理过程,这些高延迟问题往往是自动驾驶异常的关键节点。但有这类问题往往发生时机不固定,不好确定复现路径,缺少异常发生现场,难于排查根本原因。
为了便于排查这类问题,我们可以在全链路延迟埋点的基础上添加 高延迟监控功能。
通过添加埋点+定时器,当定时器触发时,主动调用一些工具采集该时刻的现场数据用于后续分析,如使用:perf trace 进行系统调用过程及耗时分析等,这些工具是可以动态配置进行扩展的。
问题实例一:
描述:相机节点运行中偶现不发出图像数据。
现象:无现场,但可以确认当时进程未coredump,无 rostopic 输出,日志中无error输出
排查:怀疑死锁?理论分析了代码,不会发生死锁。为什么日志无error输出? 究竟在哪里卡住了?难道卡在了ioctl?dmesg中发现异常时刻有大量的camera驱动 err出现。由此猜测大概率是在ioctl中发生异常。
如果有高延迟监控,则可以在遇到这种场景时,读取 /proc/../stack 查看当前的调用堆栈、或使用perf trace 查看当前的系统调用是在那部分循环、还是阻塞在哪一个系统调用。可以一目了然的看出问题的源头。
问题实例二:
write(fd=1 写日志卡>500ms,如果在监控段内,也可以被捕捉到现场数据。
二、方案描述:
监控场景可以归结为两类:
1)是点监控(监控点触发到下一次点触发之间的延迟),
2)是段监控(监控起始点触发到结束点触发之间的延迟)。
我们可以预设好,有哪些监控场景,他们对应的延迟阈值。以及 tracing 程序组的配置。
监控埋点触发时,定时器开始。若在阈值范围内监控埋点恢复则停止定时器,否则则触发tracing 程序组的数据采集。
针对持续运行的采集工具(如perf record),当监控埋点恢复时会主动停止记录。
同一个监控点触发后,会进入冷却期,冷却器内不再重复触发。
全链路延迟DAG中的点,会自动进行高延迟监控。
需要在日志中记录: 什么埋点 在 什么时刻 因为什么样的状况 触发了什么样的行为
三、详细设计:
配置内容:
|
流程图:
1. 关于定时器:
使用 ros 提供的 steadyTimer
1)内部使用 clock_gettime(CLOCK_MONOTONIC, timespec),单调的,不会因系统时间改变而跳变。
2)内部使用 ros::TimerManager 进行管理,timers 保存在 vector中,当timer 对象过多时,会有性能问题。
3)回调的触发依赖 ros::CallbackQueueInterface,默认使用的主CallbackQueue。为了不受到主CallbackQueue的影响,TracingManager 中会创建自己的CallbackQueue,并循环调用。
单进程内,在不同timer数量,以及对timer做start和stop 的cpu占用情况:(注:已排除定时器回调触发消耗,只计算timer 操作性能)
timer数量 | Hz | 对照组,不操作timer(%) | 操作所有timer(%) | 等比100Hz增加(%) | 等比10Hz增加(%) |
---|---|---|---|---|---|
1 | 10000 | 5.5 | 30 | 0.245 | 0.0245 |
5 | 10000 | 5.5 | 60 | 0.545 | 0.0545 |
10 | 5000 | 3 | 70 | 1.34 | 0.134 |
50 | 500 | 1 | 80 | 15.8 | 1.58 |
2. 关于tracing 程序组:
提供触发入口,可进行占位符替换,<pid> <tid> <outdir>。可根据不同场景对不同的监控埋点进行自定义动态配置(目前只支持全局的配置)
|
调用耗时:从触发到tracing开始采集时间差
create thread & fork 2-3ms
exec("perf") 7-8ms
total: 10ms左右
3. 关于监控配置:
集中式配置:所有节点的监控配置都在一个配置文件中进行配置,统一管理
路径:/home/mogo/autopilot/share/config/tracing/tracing.config
优势:
1) 统一管理,可以在一个文件中直观的看到所有节点的监控配置
2) 无需各个节点开发人员介入,接入成本低
劣势:
1) 统一管理的人员,需要了解每个节点的内部大致逻辑
2) 若算法节点重构,可能需要重新判断是否进行监控埋点的修改
分离式配置:各自节点的监控配置归自己节点所属,配置文件中只放自己节点相关的监控配置
优势:
1) 各算法各自管理各自的监控配置,自由度较高
2) 新增、修改、重构,各自管理响应及时
劣势:
1) 需要各算法节点,了解 tracing 埋点以及全链路延迟埋点的运行机制,接入成本较高
2) 日志解析模块,需要额外开发从各个分离式配置中组合完成配置的功能模块,具有一定的开发成本。
4. 部署与维护过程
perf 的部署
依赖库的 apt-get install libdw-dev systemtap-sdt-dev libaudit-dev 需要运维在镜像中进行部署
perf 的部署,13M,运维放到原始镜像中
日志文件的输出和清理
/home/mogo/data/log/tracing_log/nodename_timesec/**.log
在autopoilt.sh中 >7 day 则删除