提问人:Uberhumus 提问时间:11/18/2023 最后编辑:Uberhumus 更新时间:11/18/2023 访问量:120
如何测量 bash 命令之间的执行时间差异?
How to measure the difference in execution time between bash commands?
问:
当给定两个 bash 命令时,如何测量执行时间的差异?理想情况下,我希望这是有方向性的,而不是绝对的。毫秒级精度是首选。command1
command2
我可以通过代码来实现这一点,但相比之下,我这样做的方式感觉非常麻烦。
#!/bin/env bash
command1=$1
command2=$2
time1=$(/usr/bin/time -f "%E" $command1 2>&1 >/dev/null |\
awk -F: '{secs=$3; secs+=$2*60; sec+=$3*3600; printf "%.3f\n", secs*1000}')
time2=$(/usr/bin/time -f "%E" $command2 2>&1 >/dev/null |\
awk -F: '{secs=$3; secs+=$2*60; sec+=$3*3600; printf "%.3f\n", secs*1000}')
time_diff=$(echo "$time1 - $time2" | bc)
echo $time_diff
答:
4赞
KamilCuk
11/18/2023
#1
为什么不只是:
start=$(date +%s.%N)
command1
mid=$(date +%s.%N)
command2
stop=$(date +%s.%N)
time_diff=$(bc -l <<<"($mid - $start) - ($stop - $mid)")
echo "$time_diff"
或者更好
start=$EPOCHREALTIME
command1
mid=$EPOCHREALTIME
command2
stop=$EPOCHREALTIME
time_diff=$(bc -l <<<"($mid - $start) - ($stop - $mid)")
echo "$time_diff"
评论
2赞
Léa Gris
11/18/2023
由于您使用的是特定于 Bash 的重定向,因此请使用特定于 Bash 的变量: 由于没有生成日期命令子 shell,因此测量更准确。LC_NUMERIC=C; start=$EPOCHREALTIME; command1; mid=$EPOCHREALTIME; command2; stop=$EPOCHREALTIME; ...
0赞
Uberhumus
11/18/2023
卡米尔,如果我能问,为什么不呢?为什么你更喜欢用 or 代替 or ?不是批评,要求学习。bc -l
bc
here string
echo
here doc
1赞
KamilCuk
11/18/2023
why bc -l instead of bc?
默认小数位数=0,因此在默认情况下,逗号后没有数字。 生成一个单独的进程,所以速度较慢,这里 doc 需要输入更多。bc
bc -l
scale=20
why did you prefer to use here string
echo
2赞
Walter A
11/18/2023
#2
避免并使用内置的 .date
time
SECONDS
SECONDS=0
command1
firststop=$SECONDS
SECONDS=0
command2
echo "Diff $((SECONDS - firststop))."
例
SECONDS=0
sleep 4
firststop=$SECONDS
SECONDS=0
sleep 7
echo "Diff $((SECONDS - firststop))."
# Returns...
Diff 3.
评论
0赞
Uberhumus
11/18/2023
这将丢失 的毫秒数或 的纳秒数。我不认为纳秒特别有意义,但如果我多次运行它并聚合数据,毫秒可能会被证明是有意义的。我认为。time
date
3赞
Ed Morton
11/18/2023
#3
$ begs[1]=$EPOCHREALTIME; sleep 1; ends[1]=$EPOCHREALTIME
$ begs[2]=$EPOCHREALTIME; sleep 3; ends[2]=$EPOCHREALTIME
$ awk -v bs="${begs[*]}" -v es="${ends[*]}" 'BEGIN {
split(bs,begs)
split(es,ends)
for (i in begs) {
durs[i] = ends[i] - begs[i]
}
print durs[2] - durs[1]
}'
2.0128
但是,如果要分析一堆命令的时间,请考虑编写一个小脚本来执行每个命令并打印计时信息,例如:
$ cat tst.sh
#!/usr/bin/env bash
cnt=0
while IFS= read -p 'Cmd> ' -r cmd; do
if [[ "$cmd" == "." ]]; then
break
fi
cnt=$(( cnt + 1 ))
cmds["$cnt"]="$cmd"
begs["$cnt"]=$EPOCHREALTIME
eval "$cmd"
ends["$cnt"]=$EPOCHREALTIME
done
awk '
FILENAME == ARGV[1] { begs[FNR] = $0; next }
FILENAME == ARGV[2] { ends[FNR] = $0; next }
{
cmds[FNR] = $0
durs[FNR] = ends[FNR] - begs[FNR]
print "---"
printf "Cmd = %s\n", cmds[FNR]
printf "Dur = %f\n", durs[FNR]
printf "Chg = %f\n", (FNR>1 ? durs[FNR] - durs[FNR-1] : 0)
}' \
<(printf '%s\n' "${begs[@]}") \
<(printf '%s\n' "${ends[@]}") \
<(printf '%s\n' "${cmds[@]}") \
>&2
您可以按如下所示运行,并获得如下所示的输出:
$ ./tst.sh
Cmd> date -d today +'%F %T'
2023-11-18 06:22:38
Cmd> sleep 1
Cmd> seq 10000000 > /dev/null
Cmd> echo "$(date)"
Sat Nov 18 06:23:14 CST 2023
Cmd> sleep 2
Cmd> .
---
Cmd = date -d today +'%F %T'
Dur = 0.019273
Chg = 0.000000
---
Cmd = sleep 1
Dur = 1.021269
Chg = 1.001996
---
Cmd = seq 10000000 > /dev/null
Dur = 0.341198
Chg = -0.680071
---
Cmd = echo "$(date)"
Dur = 0.023039
Chg = -0.318159
---
Cmd = sleep 2
Dur = 2.019530
Chg = 1.996491
评论
0赞
Ed Morton
11/19/2023
对不起,但我不知道你的评论是什么意思。但是,如果您有后续问题,那么只需提出一个新问题,而不是将其放在评论中。
0赞
Uberhumus
11/19/2023
我认为,如果你开始扩展它的功能,它会更好地实现为编译的二进制文件。你觉得怎么样?
1赞
Ed Morton
11/19/2023
不一定,这取决于它做什么,每秒要调用多少次,等等。不要假设编译的东西比解释的东西运行得更快——情况并非总是如此。解释的 awk 脚本通常比编译的 C 程序更快,例如,因为 awk 中内置的所有用于读取输入、拆分字段、动态调整数组内存大小、实现哈希表等的代码都在 awk 命令中进行了高度优化,而个人必须自己用 C 语言编写它,并且可能不会做得那么好。
0赞
Ed Morton
11/19/2023
即使解释脚本比编译的二进制文件慢,它几乎肯定足够快,可以满足您的需求(并且需要的编码要少得多),除非在某个需要以极快速度运行的系统中每秒调用多次。如果它太慢,很有可能是因为你在写它时做错了什么,并且有一个更快的、仍然被解释的替代方案(例如,如果你写了一个 shell while-read 循环来操作文本,而不是调用 awk 来更快地完成它)。
1赞
ufopilot
11/18/2023
#4
$ command1(){ sleep 5; }
$ command2(){ sleep 2; }
$ { (time command1) 2>&1; (time command2) 2>&1; } |
awk -F'real *|m|s' '
/real/{
a[i+=1]=($2*60)+$3
}
END{
print "time1:", a[1]
print "time2:", a[2]
print "diff:", a[1]-a[2]
}
'
time1: 5.008
time2: 2.011
diff: 2.997
评论