| 特性 | Shell 内置 time (Bash) |
外部命令 /usr/bin/time |
|---|---|---|
| 位置 | Shell 解释器的一部分(内置) | 一个独立的可执行文件 |
| 调用方式 | 直接在命令前加 time |
使用完整路径 time 或通过 command time |
| 输出格式 | 相对固定,易于阅读 | 高度可定制,可通过环境变量修改 |
| 额外信息 | 仅显示:实际时间、用户CPU时间、系统CPU时间 | 极其丰富:内存、I/O、上下文切换、页面错误等 |
| 精度 | 通常较低(秒级) | 非常高(微秒级) |
| 测量对象 | 只能测量单个简单命令或管道的第一部分 | 可以测量整个管道,或任何复杂的命令组合 |
Shell 内置的 time (例如在 Bash 中)
当你直接在终端输入 time 时,你使用的是 Shell(如 Bash、Zsh)内置的 time 关键字,它非常方便,但功能相对有限。

基本用法
# 测量一个简单命令的执行时间 $ time sleep 2 real 0m2.005s user 0m0.000s sys 0m0.002s
输出详解
- real (实际时间 / wall-clock time): 从命令开始到结束所经过的真实世界时间,这是你从时钟上看到的时间流逝,它包括了命令执行本身、等待I/O(如读写文件、网络请求)、以及被操作系统调度其他进程所消耗的时间。
- user (用户CPU时间): 命令在用户态下消耗的CPU时间,这是程序执行自己代码所花费的时间。
- sys (系统CPU时间): 命令在内核态下消耗的CPU时间,这是程序请求操作系统内核服务(如文件读写、内存分配)所花费的时间。
总CPU时间 = user + sys。
对于 sleep 2 这样的命令,它大部分时间都在等待,real 时间远大于 user 和 sys 时间之和,对于一个CPU密集型任务(如编译代码),user 和 sys 时间之和会接近 real 时间。
局限性
- 功能有限:只能显示这三个基本的时间信息。
- 精度较低:
time命令本身的输出精度通常是秒级,虽然它内部可能测量得更精确,但显示结果被截断了。 - 无法测量复杂管道:这是它最大的一个限制。
# 这是一个错误的用法,只会测量 ls 的执行时间 $ time ls -l | grep "my_file" real 0m0.002s user 0m0.001s sys 0m0.001s # 你看不到 grep 的执行时间
外部命令 /usr/bin/time
为了克服内置 time 的限制,Linux 和 macOS 系统都提供了一个功能更强大的外部命令,通常位于 /usr/bin/time,它的输出更详细,精度也更高。
基本用法
为了避免与 Shell 内置的 time 冲突,你需要使用以下几种方式之一来调用它:

# 使用完整路径 $ /usr/bin/time ls # 使用 command 关键字(推荐) $ command time ls # 在脚本中,通常使用绝对路径
强大的输出信息
外部 time 命令的输出非常丰富,你可以通过设置环境变量 TIMEFORMAT 来自定义输出格式,或者直接使用其默认的详细输出。
示例 1:测量一个C程序的编译
$ /usr/bin/time gcc -O2 my_program.c -o my_program 0.03user 0.01system 0:00.04elapsed 99%CPU (0avgtext+0avgdata 2328maxresident)k 0inputs+0outputs (0major+105minor)pagefaults 0swaps
输出详解(从左到右):
03user: 用户态CPU时间(秒)。01system: 系统态CPU时间(秒)。0:00.04elapsed: 实际经过时间(分:秒)。99%CPU: CPU利用率。(0avgtext+0avgdata 2328maxresident)k: 内存使用情况。avgtext: 平均文本段大小(代码)。avgdata: 平均数据段大小。maxresident: 最大常驻内存集大小(KB)。
0inputs+0outputs: I/O 操作统计。(0major+105minor)pagefaults: 页错误统计。major: 重大页错误(需要从磁盘读取)。minor: 次要页错误(在内存中找到,但需要处理)。
0swaps: 交换次数。
示例 2:正确测量整个管道
这是外部 time 相对于内置 time 的巨大优势。
# 这会测量 ls 和 grep 的总执行时间和资源消耗 $ /usr/bin/time ls -l | grep "my_file"
自定义输出格式
你可以通过 TIMEFORMAT 环境变量来指定你想要的输出格式,类似于 printf 的格式化字符串。
# 设置只显示实际时间,精确到小数点后3位 $ export TIMEFORMAT="%3R seconds" $ /usr/bin/time sleep 1.234 1.234 seconds
TIMEFORMAT 中常用的格式说明符:
%R: 实际时间(秒),浮点数。%U: 用户CPU时间(秒)。%S: 系统CPU时间(秒)。%P: CPU利用率(百分比)。
C 语言中的 time.h
现在我们转向 C 语言本身,C 语言通过标准库 <time.h> 提供了测量时间的函数,让你可以在程序内部进行高精度的性能分析。
主要函数和数据结构
-
clock_t clock(void):- 功能: 返回自程序启动以来,处理器所消耗的时钟滴答数。
- 头文件:
<time.h> - 精度: 取决于
CLOCKS_PER_SEC的值,通常是毫秒级。 - 特点: 它测量的是CPU时间,而不是真实时间,如果一个程序大部分时间都在等待I/O,
clock()返回的时间会很少。
#include <stdio.h> #include <time.h> int main() { clock_t start, end; double cpu_time_used; start = clock(); // 要测量的代码块 for (int i = 0; i < 1000000; i++) { // do something } end = clock(); cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; printf("CPU time used: %f seconds\n", cpu_time_used); return 0; } -
*`time_t time(time_t timer)`**:
- 功能: 返回自 Epoch (1970-01-01 00:00:00 UTC) 以来的秒数,这是一个真实世界时间。
- 头文件:
<time.h> - 精度: 秒级。
- 用途: 主要用于获取当前时间戳,而不是测量代码执行时间。
-
int gettimeofday(struct timeval *tv, struct timezone *tz):- 功能: 获取当前时间,精度为微秒(microseconds),这是测量代码执行时间的首选方法之一,因为它同时提供了秒和微秒。
- 头文件:
<sys/time.h>(非标准,但在几乎所有Unix-like系统上都可用) - 特点: 测量的是真实时间。
#include <stdio.h> #include <sys/time.h> int main() { struct timeval start, end; long long elapsed; gettimeofday(&start, NULL); // 要测量的代码块 for (int i = 0; i < 1000000; i++) { // do something } gettimeofday(&end, NULL); elapsed = (end.tv_sec - start.tv_sec) * 1000000LL; elapsed += (end.tv_usec - start.tv_usec); printf("Time elapsed: %lld microseconds\n", elapsed); return 0; } -
*`int clock_gettime(clockid_t clk_id, struct timespec tp)`**:
- 功能: POSIX 标准推荐的高精度时间获取函数,比
gettimeofday更现代、更灵活。 - 头文件:
<time.h> - 精度: 纳秒级(实际精度取决于系统)。
clk_id: 可以指定时钟类型。CLOCK_REALTIME: 类似于time(),返回真实世界时间。CLOCK_MONOTONIC: 推荐用于性能测量,它返回一个单调递增的时间,不受系统时间更改(如NTP同步或手动修改时间)的影响。CLOCK_PROCESS_CPUTIME_ID: 测量当前进程的CPU时间,类似于clock()但精度更高。
#include <stdio.h> #include <time.h> int main() { struct timespec start, end; long long elapsed; clock_gettime(CLOCK_MONOTONIC, &start); // 要测量的代码块 for (int i = 0; i < 1000000; i++) { // do something } clock_gettime(CLOCK_MONOTONIC, &end); elapsed = (end.tv_sec - start.tv_sec) * 1000000000LL; elapsed += (end.tv_nsec - start.tv_nsec); printf("Time elapsed: %lld nanoseconds\n", elapsed); return 0; } - 功能: POSIX 标准推荐的高精度时间获取函数,比
总结与最佳实践
| 场景 | 推荐工具 | 原因 |
|---|---|---|
| 快速查看一个命令的执行时间 | time (Shell 内置) |
方便快捷,无需记忆路径。 |
| 测量整个管道或复杂脚本 | /usr/bin/time 或 command time |
能正确测量管道中所有命令的总耗时和资源消耗。 |
| 需要详细的性能分析(内存、I/O等) | /usr/bin/time |
提供最全面的系统资源使用报告。 |
| 在C程序中测量代码块的性能 | clock_gettime(CLOCK_MONOTONIC, ...) |
最佳实践,精度高、不受系统时间影响,是现代C/C++程序的首选。 |
| 在C程序中测量CPU时间 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) |
精度比 clock() 高,且是POSIX标准,比 clock() 更可靠。 |
| 在旧代码或简单场景中测量CPU时间 | clock() |
简单易用,但精度和灵活性有限。 |
- 在 Shell 外部测量命令:用
/usr/bin/time。 - 在 C 程序内部测量代码:用
clock_gettime。
