如何在Bash中监控标准输出每行作为最后输出行的时长用于基准测试?
捕获标准输出每行的持续时间并格式化输出
刚好遇到过类似的需求,不用修改原程序,通过管道配合awk就能完美解决。直接上解决方案,再给你拆解逻辑:
完整实现命令
针对你给出的测试脚本,运行这个命令就能得到想要的结果:
(echo a; sleep 1; echo b; sleep 3; echo c; sleep 2) | awk ' { # 存储每行内容和对应的精确时间戳(含毫秒) lines[NR] = $0 times[NR] = systime() + (substr(strftime("%N"), 1, 6)/1000000) } END { # 记录程序结束的时间戳 end_time = systime() + (substr(strftime("%N"), 1, 6)/1000000) # 遍历所有行计算时长 for (i=1; i<=NR; i++) { if (i < NR) { # 非最后一行:时长 = 下一行输出时间 - 当前行输出时间 duration = times[i+1] - times[i] } else { # 最后一行:时长 = 程序结束时间 - 当前行输出时间 duration = end_time - times[i] } # 格式化输出,保留两位小数 printf "%.2f %s ", duration, lines[i] } # 最后补一个换行,让输出更整洁 print "" } '
运行后会输出:1.00 a 3.00 b 2.00 c (末尾的小空格不影响使用,介意的话可以用数组收集结果后再拼接输出)
适配实际场景(比如QEMU)
把上面命令里的测试脚本(echo a; sleep 1; echo b; sleep 3; echo c; sleep 2)换成你的QEMU命令就行,比如:
qemu-system-x86_64 your_args_here | awk '...' # 这里的awk脚本和上面完全一样
注意事项
输出缓冲问题:如果原程序用了全缓冲(而非行缓冲),会导致多行输出一次性被awk读取,时间差会变成0。这种情况可以用
stdbuf强制行缓冲:stdbuf -oL qemu-system-x86_64 your_args_here | awk '...'-oL参数会让标准输出以行缓冲模式工作,确保每行输出都会立即被awk捕获。时间精度调整:上面的脚本用了毫秒级精度,如果需要更高精度(比如微秒),可以把时间戳的计算改成:
times[NR] = systime() + (substr(strftime("%N"), 1, 9)/1000000000)对应的输出格式也可以改成
%.6f来保留六位小数。
内容的提问来源于stack exchange,提问作者Ciro Santilli OurBigBook.com
相关产品推荐
相关产品推荐

