# 穷人的采样分析仪
本节将介绍如何使用 穷人的采样分析仪 (打开新窗口) (PMSP) shell 脚本来评估 PX4 的性能。这是对最初由 马克-卡拉汉和多马斯-米图扎斯 (打开新窗口).
# 方法
PMSP 是一个 shell 脚本,通过定期中断固件的执行来对当前堆栈跟踪进行采样。取样的堆栈跟踪会被添加到文本文件中。采样完成后(通常需要一小时或更长时间),收集到的堆栈跟踪会被保存到一个文本文件中。 褶皱的.结果是 褶皱 是另一个包含相同堆栈轨迹的文本文件,但所有相似的堆栈轨迹(即在程序中同一时刻获得的堆栈轨迹)都被合并在一起,并记录了它们的出现次数。然后将折叠后的堆栈输入可视化脚本,为此我们使用了 FlameGraph - 一种开源堆栈跟踪可视化工具 (打开新窗口).
# 基本用法
# 先决条件
剖析器依靠 GDB 在嵌入式目标机上运行 PX4。因此,在对目标进行剖析之前,您必须拥有要剖析的硬件,并且必须编译固件并上传到该硬件。然后,您需要一个 调试探针 (例如 DroneCode Probe),以运行 GDB 服务器并与电路板交互。
# 确定调试器设备
poor-mans-profiler.sh
自动检测并使用正确的 USB 设备。 无人机代码探测器.如果您使用的是另一种探针,可能需要输入特定的 装置 上的调试器。您可以使用 bash 命令 ls -alh /dev/serial/by-id/
来枚举 Ubuntu 上可能的设备。例如,通过 USB 连接 Pixhawk 4 和 DroneCode 探针后,可枚举出以下设备:
user@ubuntu:~/PX4-Autopilot$ ls -alh /dev/serial/by-id/ total 0 drwxr-xr-x 2 root root 100 Apr 23 18:57 . drwxr-xr-x 4 root root 80 Apr 23 18:48 ... lrwxrwxrwx 1 root root 13 Apr 23 18:48 usb-3D_Robotics_PX4_FMU_v5.x_0-if00 -> .../../ttyACM0 lrwxrwxrwx 1 root root 13 Apr 23 18:57 usb-Black_Sphere_Technologies_Black_Magic_Probe_BFCCB401-if00 -> ../../ttyACM1 lrwxrwxrwx 1 root root 13 Apr 23 18:57 usb-Black_Sphere_Technologies_Black_Magic_Probe_BFCCB401-if02 -> ../../ttyACM2
在这种情况下,脚本会自动拾取名为 *Black_Magic_Probe*-if00
.但如果您使用的是其他设备,您可以从上面的列表中找到相应的 ID。
然后使用 -gdbdev
这样的论点:
./poor-mans-profiler.sh --elf=build/px4_fmu-v4_default/px4_fmu-v4_default.elf --nsamples=30000 -gdbdev=/dev/ttyACM2
# 跑步
剖析器的基本用法可通过构建系统实现。例如,以下命令可构建并剖析具有 10000 个样本的 px4_fmu-v4pro 目标机(获取 FlameGraph 并根据需要将其添加到路径中)。
制作 px4_fmu-v4pro_default 配置文件
要对构建过程进行更多控制,包括设置样本数量,请参阅 实施情况.
# 了解输出
下面是输出示例的截图(注意这里不是交互式的):
在火焰图上,水平层代表堆栈帧,而每个帧的宽度与采样次数成正比。反过来,函数最终被采样的次数与函数执行的持续时间乘以频率成正比。
# 可能出现的问题
该脚本是作为临时解决方案开发的,因此存在一些问题。使用时请注意:
如果 GDB 出现故障,脚本可能无法检测到,并继续运行。在这种情况下,显然不会产生可用的堆栈。为了避免这种情况,用户应该定期检查文件
/tmp/pmpn-gdberr.log
,其中包含最近一次调用 GDB 的 stderr 输出。将来应该修改脚本,以便在安静模式下调用 GDB,并通过退出代码显示问题。有时,GDB 在对堆栈跟踪进行采样时会永远停止。在此故障期间,目标将无限期停止。解决方法是手动中止脚本,然后使用
--附加
选项。今后应修改脚本,使每次调用 GDB 时都有一个超时时间。不支持多线程环境。这不会影响单核嵌入式目标,因为它们总是在一个线程中执行,但这一限制使得剖析器与许多其他应用程序不兼容。今后应修改堆栈文件夹,以支持每个样本的多个堆栈跟踪。
# 实施情况
脚本位于 /platforms/nuttx/Debug/poor-mans-profiler.sh (打开新窗口)
启动后,它将以指定的时间间隔执行指定数量的采样。采集的样本将保存在系统临时目录下的文本文件中(通常为 /tmp
).取样完成后,脚本将自动调用堆栈文件夹,其输出结果将保存在临时目录下的相邻文件中。如果堆栈折叠成功,脚本将调用 FlameGraph 脚本,并将结果存储到交互式 SVG 文件中。请注意,并非所有图像查看器都支持交互式图像;建议在网络浏览器中打开生成的 SVG。
FlameGraph 脚本必须位于 路径
否则 PMSP 将拒绝启动。
PMSP 使用 GDB 收集堆栈跟踪。目前它使用 arm-none-eabi-gdb
今后还可能增加其他工具链。
为了将内存位置映射到符号,脚本需要引用目标机上当前运行的可执行文件。这需要借助 --elf=<文件>;
,它需要一个指向当前执行的 ELF 位置的路径(相对于资源库根目录)。
使用示例
./poor-mans-profiler.sh --elf=build/px4_fmu-v4_default/px4_fmu-v4_default.elf --nsamples=30000
请注意,每次启动脚本都会覆盖旧堆栈。如果您想追加而不是覆盖旧堆栈,可使用选项 --附加
:
./poor-mans-profiler.sh --elf=build/px4_fmu-v4_default/px4_fmu-v4_default.elf --nsamples=30000 --附加
正如人们所猜测的那样、 --附加
与 --样本数=0
将指示脚本只重新生成 SVG,而完全不访问目标。
请阅读脚本,更深入地了解其工作原理。