C语言计算时间函数 & 理解linux time命令的输出中“real”“user”“sys”的真正含义

本文解释了Linux中time命令的输出含义,包括real、user和sys时间的区别,并通过实例说明如何计算程序的CPU利用率。

在完成编译原理的实验时,想比较用链表和哈希表共同执行一段程序的时间是否有差异,最开始使用函数如下:

main()
{
  clock_t start = 0;   
  clock_t end = 0;   
  double time;
  int i;
  start = clock();   

  yylex();

  end = clock();   
  time = (double)(end - start)/CLOCKS_PER_SEC;/*#define CLOCKS_PER_SEC ((clock_t)1000)*/

  printf("\n执行时间%fsecond\n",time);

}

但由于程序太小,时间显示出来全是0.00000……查到可以用Linux附带的函数,所以就尝试了一下,

使用命令:

time ./test.out

结果显示如下:

real    0m0.026s
user    0m0.012s
sys    0m0.008s

下面转载的文章详细地介绍了time出来显示的“real”“user”“sys”的真正含义。


http://laiwei.net/2010/06/19/%E7%90%86%E8%A7%A3linux-time%E5%91%BD%E4%BB%A4%E7%9A%84%E8%BE%93%E5%87%BAwhat-do-real-user-and-sys-mean-2/

Linux中time命令,我们经常用来计算某个程序的运行耗时,用户态cpu耗时,系统态cpu耗时。

例如:

$ time foo 
real        0m0.003s
user        0m0.000s
sys         0m0.004s$

那么这三个时间都具体代表什么意思呢?

[1] real : 表示foo程序整个的运行耗时,可以理解为foo运行开始时刻你看了一下手表,foo运行结束时,你又看了一下手表,两次时间的差值就是本次real 代表的值

举个极端的例子如下:可以看到real time恰好为2秒。

# time sleep 2

real    0m2.003s

user    0m0.000s

sys     0m0.000s

[2] user   0m0.000s:这个时间代表的是foo运行在用户态的cpu时间,什么意思?

首先,我来讲一下用户态和核心态:

核心态(Kernel Mode)

      在内核态,代码拥有完全的,不受任何限制的访问底层硬件的能力。可以执行任意的CPU指令,访问任意的内存地址。内核态通常情况下,都是为那些最底层的,由操作系统提供的,可信可靠的代码来运行的。内核态的代码崩溃将是灾难性的,它会影响到整个系统。

       —– In Kernel mode, the executing code has complete and unrestricted access to the underlying hardware. It can execute any CPU instruction and reference any memory address. Kernel mode is generally reserved for the lowest-level, most trusted functions of the operating system. Crashes in kernel mode are catastrophic; they will halt the entire PC.

用户态(User Mode)

      在用户态,代码不具备直接访问硬件或者访问内存的能力,而必须借助操作系统提供的可靠的,底层的APIs来访问硬件或者内存。由于这种隔离带来的保护作用,用户态的代码崩溃(Crash),系统是可以恢复的。我们大多数的代码都是运行在用户态的。

      —– In User mode, the executing code has no ability to directly access hardware or reference memory. Code running in user mode must delegate to system APIs to access hardware or memory. Due to the protection afforded by this sort of isolation, crashes in user mode are always recoverable. Most of the code running on your computer will execute in user mode.

为什么要区分Kernel Mode 和 User Mode

     隔离保护,使得系统更稳定。

好,讲完用户态和核心态之后,我们来看user time,说过了,这个指的是程序foo运行在用户态的cpu时间,cpu时间不是墙上的钟走过的时间,而是指CPU工作时间。

[3] sys   0m0.004s : 这个时间代表的是foo运行在核心态的cpu时间。

 

好,讲完上面的这些,我们来看看这三个的关系,这三者之间没有严格的关系,常见的误区有:

误区一: real_time = user_time + sys_time

       我们错误的理解为,real time 就等于 user time + sys time,这是不对的,real time是时钟走过的时间,user time 是程序在用户态的cpu时间,sys time 为程序在核心态的cpu时间。

利用这三者,我们可以计算程序运行期间的cpu利用率如下:

%cpu_usage = (user_time + sys_time)/real_time * 100%

如:

# time sleep 2

real     0m2.003s

user    0m0.000s

sys     0m0.000s

cpu利用率为0,因为本身就是这样的,sleep 了2秒,时钟走过了2秒,但是cpu时间都为0,所以利用率为0

误区二:real_time > user_time + sys_time

一般来说,上面是成立的,上面的情况在单cpu的情况下,往往都是对的。

但是在多核cpu情况下,而且代码写的确实很漂亮,能把多核cpu都利用起来,那么这时候上面的关系就不成立了,例如可能出现下面的情况,请不要惊奇。

real 1m47.363s

user 2m41.318s

sys 0m4.013s

误区三:real_time < user_time + sys_time

一般来讲不会有人闯入这个误区^^

 

参考资料:理解time的输出



&lt;think&gt;好的,我现在需要回答用户的问题:如何在Linux中测量程序的执行时间。根据用户提供的引用内容,我需要综合这些信息,给出结构清晰的步骤,并确保正确使用LaTeX格式。首先,我得回忆一下不同的方法,比如使用time命令、C/C++中的函数,以及系统工具如perf。 首先,用户提到的time命令是最直接的。引用[1]和[4]都提到了time命令,可以用来测量命令的执行时间。我需要解释它的基本用法,以及三个时间指标:实际时间、用户CPU时间和系统CPU时间。比如用户运行time ./program,然后解析输出的各个部分。这里需要注意使用行内数学公式,比如总时间=用户时间+系统时间,写成$T_{\text{总}} = T_{\text{用户}} + T_{\text{系统}}$。 接下来是C语言的方法。引用[2]、[3]、[4]提到了clock_gettime函数和getrusage函数,以及gettimeofday。比如clock_gettime可以获取高精度的时间,需要包含头文件time.h,并指定CLOCK_REALTIME或CLOCK_MONOTONIC。这里可能需要给出一个代码示例,但用户提供的示例中有Python代码,所以C语言的代码块需要用正确的语法,比如: ```c struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &amp;start); // 被测代码 clock_gettime(CLOCK_MONOTONIC, &amp;end); double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; ``` 然后是C++中的方法,引用[5]提到使用ctime的clock()函数,或者gettimeofday。不过clock()测量的是CPU时间,而gettimeofday测量的是实际时间。这里需要注意区分两者,并给出示例代码,比如: ```cpp #include &lt;ctime&gt; clock_t start = clock(); // 被测代码 clock_t end = clock(); double cpu_time = static_cast&lt;double&gt;(end - start) / CLOCKS_PER_SEC; ``` 另外,用户还提到了perf工具,引用[4]提到perf可以用于性能分析。需要简要说明如何使用perf stat来测量时间和其他性能指标。 在组织回答时,应该分点列出不同的方法,每个方法下给出步骤和示例代码。同时,确保所有的数学表达式如时间计算公式用$...$包裹,独立公式如总时间公式用$$...$$。例如,实际时间计算可以写成: 实际时间计算公式: $$T_{\text{实际}} = T_{\text{结束}} - T_{\text{开始}}$$ 还要注意引用标识的正确放置,每个引用来源在相关段落末尾添加,比如使用time命令的部分末尾加上[^1],C语言函数部分加上[^2][^3][^4]等。 接下来,生成相关问题。根据用户提供的示例,问题应围绕方法的比较、不同工具的选择、高精度需求等。例如: 1. time命令输出的三个时间指标有什么区别? 2. 如何选择适合的时间测量方法? 3. 为什么clock()函数和实际时间会有差异? 最后,检查LaTeX语法是否正确,比如变量和公式的格式,确保行内公式用$...$,独立公式用$$...$$,并且代码块的语言标识正确。同时,保持回答结构清晰,分步骤说明每个方法,帮助用户理解不同场景下的选择。&lt;/think&gt;在Linux环境中测量程序执行时间可通过多种方法实现,以下分步骤说明常用的技术手段: --- ### 一、使用`time`命令(最简单) **步骤**: 1. 在终端中运行命令:`time ./your_program` 2. 输出结果包含三个关键指标: - **实际时间Real Time)**:程序从启动到结束的总时间,即$T_{\text{实际}} = T_{\text{结束}} - T_{\text{开始}}$ - **用户CPU时间User Time)**:程序在用户态消耗的CPU时间,如计算$f(x) = x^2$的循环操作 - **系统CPU时间Sys Time)**:程序在内核态消耗的CPU时间,如系统调用 **示例**: ```bash $ time ./my_program real 0m1.002s # 实际时间 user 0m0.800s # 用户CPU时间 sys 0m0.200s # 系统CPU时间 ``` --- ### 二、编程实现(C/C++) #### 1. **高精度时间函数`clock_gettime`** **步骤**: 1. 包含头文件`&lt;time.h&gt;` 2. 使用`CLOCK_MONOTONIC`参数避免系统时间跳变影响 3. 计算时间差:$$T_{\text{耗时}} = (t_{\text{end}}.tv\_sec - t_{\text{start}}.tv\_sec) + \frac{t_{\text{end}}.tv\_nsec - t_{\text{start}}.tv\_nsec}{10^9}$$ **代码示例**: ```c #include &lt;stdio.h&gt; #include &lt;time.h&gt; int main() { struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &amp;start); // 开始时间 // 被测代码(例如排序算法) clock_gettime(CLOCK_MONOTONIC, &amp;end); // 结束时间 double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; printf(&quot;耗时: %.6f秒\n&quot;, elapsed); return 0; } ``` &gt; 注:适用于需要纳秒级精度的场景[^2] #### 2. **`clock()`函数(测量CPU时间)** **公式**:$$T_{\text{CPU}} = \frac{\text{clock\_end} - \text{clock\_start}}{\text{CLOCKS\_PER\_SEC}}$$ **代码示例**: ```cpp #include &lt;iostream&gt; #include &lt;ctime&gt; int main() { clock_t start = clock(); // 被测代码(例如计算&pi;的数值积分) clock_t end = clock(); double cpu_time = static_cast&lt;double&gt;(end - start) / CLOCKS_PER_SEC; std::cout &lt;&lt; &quot;CPU时间: &quot; &lt;&lt; cpu_time &lt;&lt; &quot;秒&quot; &lt;&lt; std::endl; return 0; } ``` &gt; 注:`clock()`统计的是进程占用的CPU时间总和,可能与实际时间不同[^5] --- ### 三、使用`perf`工具(性能分析) **步骤**: 1. 安装perf:`sudo apt install linux-tools-common` 2. 运行命令:`perf stat ./your_program` 3. 输出包含: - 任务时钟(Task Clock) - CPU周期(CPU Cycles) - 缓存命中率(Cache Misses) **适用场景**:需同时分析程序性能瓶颈(如分支预测失败次数)[^4] --- ### 四、方法对比 | 方法 | 精度 | 适用场景 | |---------------|------------|----------------------------| | `time`命令 | 毫秒级 | 快速测量命令行程序 | | `clock_gettime`| 纳秒级 | 需要高精度时间的嵌入式系统 | | `perf stat` | 多维数据 | 性能分析与优化 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值