要获得任何可执行文件的执行时间,比如a.out
,我可以简单地写time ./a.out
。这将输出实时,用户时间和系统时间。
是否有可能编写一个运行程序多次的bash脚本并计算并输出平均实际执行时间?
您可以编写一个循环并收集time
命令的输出并将其传输到awk
以计算平均值:
avg_time() {
#
# usage: avg_time n command ...
#
n=$1; shift
(($# > 0)) || return # bail if no command given
for ((i = 0; i < n; i++)); do
{ time -p "$@" &>/dev/null; } 2>&1 # ignore the output of the command
# but collect time's output in stdout
done | awk '
/real/ { real = real + $2; nr++ }
/user/ { user = user + $2; nu++ }
/sys/ { sys = sys + $2; ns++}
END {
if (nr>0) printf("real %f\n", real/nr);
if (nu>0) printf("user %f\n", user/nu);
if (ns>0) printf("sys %f\n", sys/ns)
}'
}
例:
avg_time 5 sleep 1
会给你的
real 1.000000
user 0.000000
sys 0.000000
这可以很容易地增强到:
来自time -p
的man time
的含义:
-p When in the POSIX locale, use the precise traditional format "real %f\nuser %f\nsys %f\n" (with numbers in seconds) where the number of decimals in the output for %f is unspecified but is sufficient to express the clock tick accuracy, and at least one.
您可能还想查看此命令行基准测试工具:
关心!除以N舍入执行时间之和是不精确的!
相反,我们可以划分N次迭代的总执行时间(N)
avg_time_alt() {
local -i n=$1
local foo real sys user
shift
(($# > 0)) || return;
{ read foo real; read foo user; read foo sys ;} < <(
{ time -p for((;n--;)){ "$@" &>/dev/null ;} ;} 2>&1
)
printf "real: %.5f\nuser: %.5f\nsys : %.5f\n" $(
bc -l <<<"$real/$n;$user/$n;$sys/$n;" )
}
注意:这使用bc
而不是awk
来计算平均值。为此,我们将创建一个临时的bc
文件:
printf >/tmp/test-pi.bc "scale=%d;\npi=4*a(1);\nquit\n" 60
这将计算¶
与小数点后60,然后安静地退出。 (您可以调整主机的小数位数。)
演示:
avg_time_alt 1000 sleep .001
real: 0.00195
user: 0.00008
sys : 0.00016
avg_time_alt 1000 bc -ql /tmp/test-pi.bc
real: 0.00172
user: 0.00120
sys : 0.00058
qazxsw poi将回答:
codeforester's function
avg_time 1000 sleep .001
real 0.000000
user 0.000000
sys 0.000000
avg_time 1000 bc -ql /tmp/test-pi.bc
real 0.000000
user 0.000000
sys 0.000000
, using Linux'schoroba's answer好的,你可以考虑:
/proc
这是基于avgByProc() {
local foo start end n=$1 e=$1 values times
shift;
export n;
{
read foo;
read foo;
read foo foo start foo
} < /proc/timer_list;
mapfile values < <(
for((;n--;)){ "$@" &>/dev/null;}
read -a endstat < /proc/self/stat
{
read foo
read foo
read foo foo end foo
} </proc/timer_list
printf -v times "%s/100/$e;" ${endstat[@]:13:4}
bc -l <<<"$[end-start]/10^9/$e;$times"
)
printf -v fmt "%-7s: %%.5f\\n" real utime stime cutime cstime
printf "$fmt" ${values[@]}
}
:
/proc
那么现在:
man 5 proc | grep [su]time\\\|timer.list | sed 's/^/> /'
(14) utime %lu
(15) stime %lu
(16) cutime %ld
(17) cstime %ld
/proc/timer_list (since Linux 2.6.21)
其中avgByProc 1000 sleep .001
real : 0.00242
utime : 0.00015
stime : 0.00021
cutime : 0.00082
cstime : 0.00020
和utime
代表用户时间和系统时间为bash本人和stime
和cutime
代表儿童用户时间和儿童系统时间最有趣。
Nota:在这种情况下(qazxsw poi)命令不会使用大量资源。
cstime
这变得更加明确......当然,随着sleep
和avgByProc 1000 bc -ql /tmp/test-pi.bc
real : 0.00175
utime : 0.00015
stime : 0.00025
cutime : 0.00108
cstime : 0.00032
连续但不是原子的访问,timer_list
(基于nanosecs)和self/stat
(基于刻度,即:1/100秒)之间的差异可能会出现!
记录执行的开始和结束时间并将差异除以执行次数可能更容易。
real
我使用c?[su]time
来计算平均值,因为bash不支持浮点算术。
要获得更高的精度,您可以切换到纳秒:
#!/bin/bash
times=10
start=$(date +%s)
for ((i=0; i < times; i++)) ; do
run_your_executable_here
done
end=$(date +%s)
bc -l <<< "($end - $start) / $times"
和bc
类似。