自驾场景监控偶现高延迟技术方案

一、背景与目的

线上会偶现高延迟的处理过程,这些高延迟问题往往是自动驾驶异常的关键节点。但有这类问题往往发生时机不固定,不好确定复现路径,缺少异常发生现场,难于排查根本原因。

为了便于排查这类问题,我们可以在全链路延迟埋点的基础上添加 高延迟监控功能。

通过添加埋点+定时器,当定时器触发时,主动调用一些工具采集该时刻的现场数据用于后续分析,如使用: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中的点,会自动进行高延迟监控。

需要在日志中记录: 什么埋点 在 什么时刻 因为什么样的状况 触发了什么样的行为

三、详细设计:

配置内容:

20                              # 冷却期,单位s

/home/mogo/data/kls_ws/traces   # 日志输出前缀,完整路径是:前缀/节点名_时间ms/

cp /proc/<pid>/task/<tid>/stack <outdir>/stack       # 第三行开始为cmdline,<pid> <tid> <outdir> 为支持的占位符

perf trace -t <tid> -o <outdir>/tracing.log sleep 5

perf record -t <tid> --call-graph fp -F 10000 -o <outdir>/perf.data sleep 5

-                      # cmdline 以 - 为结束标识,tracing entity 也以 - 为分隔符

/local_panning         # 第一字段为 节点名

1                      # 第二字段为 tracing 类型 0 为point, 1 为 span

planning_begin         # span类型的 start  可以是任意的topic,也可以是自定义的监控点

/planning/trajectory   # span类型的 stop   可以是任意的topic,也可以是自定义的监控点

600                    # 监控阈值 单位 ms

-                      # 分隔符

/sensor/camera/sensing60/drivers_camera_sensing60   # 第一字段为 节点名

0                      # 第二字段为 tracing 类型 0 为point, 1 为 span

camera_grab            # point类型的 ident字段

500                    # 监控阈值 单位 ms

-                      # 最后需要以 - 为结尾

流程图:

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增加(%)

1100005.5300.2450.0245
5100005.5600.5450.0545
1050003701.340.134
5050018015.81.58

2. 关于tracing 程序组:

提供触发入口,可进行占位符替换,<pid> <tid> <outdir>。可根据不同场景对不同的监控埋点进行自定义动态配置(目前只支持全局的配置)

cp /proc/<pid>/task/<tid>/stack <outdir>/stack

perf trace -t <tid> -o <outdir>/tracing.log sleep 5

perf record -t <tid> --call-graph fp -F 10000 -o <outdir>/perf.data sleep 5

调用耗时:从触发到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 则删除

  • 14
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值