打印经过的时间,以秒为单位,带有三个尾随数字

时间:2012-10-10 13:46:40

标签: bash

对于我正在编写的框架,我想测量一段(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,了解我是如何实现此功能的。

4 个答案:

答案 0 :(得分:4)

您可以使用bc命令:

elapsed_time_in_ms=$(echo "scale=3;$elapsed_time/1000000" | bc)

scale基本上设置了.

之后所需的位数

答案 1 :(得分:1)

这也可以使用shell参数扩展或通过printf来完成。例如,一个接一个地运行以下两个序列,在一次运行中打印1349883230.7151349883230.721,在另一个运行中打印1349884003.0251349884003.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/uptimedate +%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秒