对于我正在编写的框架,我想测量一段(bash)代码执行多少,然后以秒为单位打印经过的时间。
测量时,我会执行以下操作:
start=$(date +%s%N)
# do something here
elapsed_time=$(($(date +%s%N) - start))
这给了我与经过的纳米级连接的经过的秒数。如果我现在把它除以1000000,我会得到ms的时间
elapsed_time_in_ms=$(($elapsed time / 1000000))
这一切都很好,似乎有效,但真正的问题是我想以这种格式打印它:
12.789s
其中.
是秒之前,而点之后是ms值的最后3位数。
我将如何实现这样的目标?
修改
我知道时间可能没什么用,我仍然想实现这个(即使只是出于美观的原因: - ))。
编辑2
对于遇到同样问题的人:
最后我选择使用时间,因为它不需要叉子,似乎是最便携的解决方案。
查看it
函数和全局total_elapsed_time
变量here,了解我是如何实现此功能的。
答案 0 :(得分:4)
您可以使用bc
命令:
elapsed_time_in_ms=$(echo "scale=3;$elapsed_time/1000000" | bc)
scale
基本上设置了.
答案 1 :(得分:1)
这也可以使用shell参数扩展或通过printf
来完成。例如,一个接一个地运行以下两个序列,在一次运行中打印1349883230.715
和1349883230.721
,在另一个运行中打印1349884003.025
和1349884003.032
。 (%N
日期格式填充前导零。)
s=$(date +%s.%N); s=${s%??????}; echo $s
t=$(printf "%20.3f" $(date +%s.%N)); echo $t
如模式匹配中的man bash所述,特殊模式字符?
匹配任何单个字符。如参数扩展中所述,表单
${parameter%word}
删除匹配的后缀模式:“如果模式匹配尾部...扩展是具有最短匹配模式的参数的扩展值(”%“情况)或最长匹配模式(”%%“情况)删除。“
答案 2 :(得分:1)
从纳秒开始,只需将前三个数字后的数字切掉。
printf“%d。%。3ss \ n”date +%S
date +%N
#只运行一次日期可能不是非常不明智,顺便说一句。
- 打印一个数字后跟一个点,然后将下一个参数视为字符串并仅打印前三个字符。
$ i=0; while [ $i -lt 9 ];do i=$((i+1)); sleep 0.1; \ printf "%d.%.3ss\n" `date +%S` `date +%N` ;done 33.917s 34.025s 34.133s 34.240s 34.348s 34.457s 34.566s 34.674s 34.784s
答案 3 :(得分:1)
由于使用需要时间的bc
implie forks,我更喜欢纯bash 解决方案:
start=$(date +%s%N);sleep 1.1;elapsed_time=$(($(date +%s%N) - start))
_Z9=000000000
[ ${#elapsed_time} -lt 9 ] && \
elapsed_time=${_Z9:0:9-${#elapsed_time}}$elapsed_time;
printf "%.3fs\n" ${elapsed_time:0:${#elapsed_time}-9
}.${elapsed_time:${#elapsed_time}-9}
打印:
1.107s
对于那种事情,我写了一些bash source file即可 工作快速。
它在Linux /proc/timer_list
或Linux /proc/uptime
或date +%s%n
上使用,但在其他系统上未经过充分测试(欢迎使用反馈;)。
它使用两个计数器(每个调用一个,另一个作为整体计数器)并接受一些参数(读取注释):
. elap.bash
elap -R ; for i in {1..10};do sleep .1; elap Counter $i;done;elap -t total
0.110488478 Counter 1
0.111014783 Counter 2
0.117158015 Counter 3
0.112897232 Counter 4
0.111928207 Counter 5
0.108822248 Counter 6
0.113464053 Counter 7
0.117487421 Counter 8
0.115716626 Counter 9
0.110493433 Counter 10
0.008513430 1.137983926 total
并且,bc
可能有用:
time echo 'scale=1000;pi=4*a(1);0'|bc -l
0
real 0m1.590s
user 0m0.768s
sys 0m0.008s
或
elap -R;elap BC answer is: $(echo 'scale=1000;pi=4*a(1);0'|bc -l )
1.539957483 BC answer is: 0
将此脚本与/proc/timer_list
一起使用可以:
elap -R ; for i in {1..10};do elap Counter $i;done;elap -t total
0.001299574 Counter 1
0.001574097 Counter 2
0.005771637 Counter 3
0.001428803 Counter 4
0.010423721 Counter 5
0.004037965 Counter 6
0.001392464 Counter 7
0.008092812 Counter 8
0.001634280 Counter 9
0.001365652 Counter 10
0.008201473 0.045222478 total
当相同的脚本无法访问/ proc 时,使用fork to date +%s%N
给出:
elap -R ; for i in {1..10};do elap Counter $i;done;elap -t total
0.012148259 Counter 1
0.013415551 Counter 2
0.008279329 Counter 3
0.013700332 Counter 4
0.012837796 Counter 5
0.015562929 Counter 6
0.008062369 Counter 7
0.016810494 Counter 8
0.011537439 Counter 9
0.009731194 Counter 10
0.012959840 0.135045532 total
我们可以看到 fork的成本(在这种情况下接近1/100秒)。
好吧,最后,对于匹配SO问题的确切格式,可以修补这个小脚本,以这种方式获取样本:
eval "$(sed -e < elap.bash '
/6d/{ s/6d.%/10.3f/g;p;N;
:a;
s/^.*\n//g;N;s/" \\\n[ \t]*"/./; p;
s/^.*//g; N;/elaP_elap2/ba; }')"
elap -R ; for i in {1..10};do elap Counter $i;done;elap -t total
0.001s Counter 1
0.006s Counter 2
0.007s Counter 3
0.004s Counter 4
0.003s Counter 5
0.002s Counter 6
0.001s Counter 7
0.001s Counter 8
0.006s Counter 9
0.002s Counter 10
0.004s 0.038s total
总共38秒