8.3 计算命令执行时间
当测试一个应用程序或比较不同的算法时,程序的执行时间非常重要。一个好算法的执行时间应该最短。在某些情况下,我们需要监视程序执行所需要的时间。例如,当学习排序算法时,你该怎么样表明哪一种算法更快一些?答案就是计算这些算法针对同一个数据集所耗费的时间。让我们看看如何计算。
实战演练
所有的类UNIX操作系统都包含time
命令。你可以将time
放在需要计算执行时间的命令之前,例如:
- $ time COMMAND
命令COMMAND
会执行并生成输出 。除此之外,time
命令会将命令的执行时间添加到stderr
中。例如:
- $ time ls
- test.txt
- next.txt
- real 0m0.008s
- user 0m0.001s
- sys 0m0.003s
输出中分别显示了执行该命令所花费的real
时间、user
时间以及sys
时间。
real
时间指的是挂钟时间(wall clock time),也就是命令从开始执行到结束的时间。这段时间包括其他进程所占用的时间片(time slice)以及进程被阻塞时所花费的时间(例如,为等待I/O操作完成所用的时间)。user
时间是指进程花费在用户模式(user-mode)中的CPU时间。这是唯一真正用于执行进程所花费的时间。执行其他进程以及花费在阻塞状态中的时间并没有计算在内。sys
时间是指进程花费在内核模式(in the kernel)中的CPU时间。它代表在内核中执行系统调用所使用的时间,这和库代码(library code)不同,后者仍旧运行在用户空间(user space)。与“user时间”类似,这也是真正由进程使用的CPU时间。
![]()
time
命令的可执行二进制文件位于/usr/bin/time,还有一个Shell内建命令也叫做time
。当运行time
时,默认调用的是Shell的内建命令。Shell内建的time
命令选项有限。因此,如果我们需要使用另外的功能,就应该使用可执行文件time的绝对路径(/usr/bin/time)。
可以用选项-o filename
将命令执行时间写入文件:
- $ /usr/bin/time -o output.txt COMMAND
文件名应该出现在选项-o
之后。
要将命令执行时间添加到文件而不影响其原有内容,使用选项-a
以及-o
:
- $ /usr/bin/time -a -o output.txt COMMAND
我们也可以使用选项-f
,利用格式字符串格式化时间输出。格式字符串由对应于特定选项的参数组成,这些参数以 %
作为前缀。real
时间、user
时间、sys
时间的格式字符串分别如下:
real
-%e
user
-%U
sys
-%S
通过结合参数字符串,我们就可以创建格式化输出:
- $ /usr/bin/time -f "FORMAT STRING" COMMAND
例如:
- $ /usr/bin/time -f "Time: %U" -a -o timing.log uname
- Linux
其中,%U
是user
时间的参数。
格式化输出生成后被写入标准输出,执行时间信息被写入标准错误。我们可以用重定向操作符(>
)对格式化输出重定向,用错误重定向操作符(2>
)对时间信息重定向。例如:
- $ /usr/bin/time -f "Time: %U" uname> command_output.txt 2>time.log
- $ cat time.log
- Time: 0.00
- $ cat command_output.txt
- Linux
通过time
命令可以获得进程的很多细节信息,包括退出状态、接收到的信号数量、进程上下文的切换次数等。每一个参数都可以用适合的格式字符串显示。
表8-1展示了一些可以使用的参数。
表 8-1
参 数 | 描 述 |
---|---|
%C | 进行计时的命令名称以及命令行参数 |
%D | 进程非共享数据区域的大小,以KB为单位 |
%E | 进程使用的real 时间(挂钟时间),显示格式为[小时:]分钟:秒 |
%x | 命令的退出状态 |
%k | 进程接收到的信号数量 |
%W | 进程被交换出主存的次数 |
%Z | 系统的页面大小。这是一个系统常量,但在不同的系统中,这个常量值也不同 |
%P | 进程所获得的CPU时间百分比。这个值等于user+system 时间除以总共的运行时间。结果以百分比形式显示 |
%K | 进程的平均总(data+stack+text)内存使用量,以KB为单位 |
%w | 进程主动(voluntarily )进行上下文切换的次数,例如等待I/O 操作完成 |
%c | 进程被迫(involuntarily )进行上下文切换的次数(由于时间片到期) |
例如,用参数 %Z
显示系统页面大小:
- $ /usr/bin/time -f "Page size: %Z bytes" ls> /dev/null
- Page size: 4096 bytes
这里并不需要被计时命令的输出(即ls
),因此为了使其不显示在终端中,我们将标准输出重定向到了/dev/null设备。
还有很多可用格式字符串,请阅读man time
,以便获取更多的细节信息。