乐趣区

linux下统计程序函数运行时间

linux 下统计程序 / 函数运行时间

time 命令

作用

time 命令常用于测量一个命令的运行时间。


但是仔细查看 man 手册发现,time 能做的不仅仅是测量运行时间,还可以测量内存、I/ O 等使用情况。手册页上的说法是 time a simple command or give resource usage,其中 time 一词我认为它应该是测量或测定的意思,并不单指时间。

用例

jonathan@cloud:~$ time ls
bak  gitbook  github  learn  test  work

real    0m0.002s
user    0m0.000s
sys    0m0.002s

输出的信息分别显示了该命令所花费的 real 时间、user 时间和 sys 时间。

  • real 时间:是指挂钟时间,也就是命令开始执行到结束的时间。这个短时间包括其他进程所占用的时间片,和进程被阻塞时所花费的时间。
  • user 时间:是指进程花费在用户模式中的 CPU 时间,这是唯一真正用于执行进程所花费的时间,其他进程和花费阻塞状态中的时间没有计算在内。
  • sys 时间:是指花费在内核模式中的 CPU 时间,代表在内核中执系统调用所花费的时间,这也是真正由进程使用的 CPU 时间。

linux 中 time 命令不只一个

shell 中一般会内建 time 命令,但是这个内建的 time,功能比较弱。如果我们要使用复杂的功能的话就必须使用外部的 time。

内建 time:time

外部 time:/usr/bin/time

/usr/bin/time 的参数

  • 无参数

    jonathan@cloud:~$ /usr/bin/time ls
    bak  gitbook  github  learn  outfile.txt  test    work
    0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 1012maxresident)k
    0inputs+0outputs (0major+313minor)pagefaults 0swaps
  • -v 输出详细信息

    jonathan@cloud:~$ /usr/bin/time -v ls
    bak  gitbook  github  learn  outfile.txt  test    work
        Command being timed: "ls"
        User time (seconds): 0.00
        System time (seconds): 0.00
        Percent of CPU this job got: 100%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 1012
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 313
        Voluntary context switches: 1
        Involuntary context switches: 0
        Swaps: 0
        File system inputs: 0
        File system outputs: 0
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
  • -o 将执行时间写入到文件中

    $ /usr/bin/time -o outfile.txt ls
  • -a 追加信息

    $ /usr/bin/time -a -o outfile.txt ls
  • -f 格式化时间输出

    $ /usr/bin/time -f "time: %U" ls

    参数:

    参数 描述
    %E real 时间,显示格式为 [小时:] 分钟: 秒
    %U user 时间。
    %S sys 时间。
    %C 进行计时的命令名称和命令行参数。
    %D 进程非共享数据区域,以 KB 为单位。
    %x 命令退出状态。
    %k 进程接收到的信号数量。
    %w 进程被交换出主存的次数。
    %Z 系统的页面大小,这是一个系统常量,不用系统中常量值也不同。
    %P 进程所获取的 CPU 时间百分百,这个值等于 user+system 时间除以总共的运行时间。
    %K 进程的平均总内存使用量(data+stack+text),单位是 KB。
    %w 进程主动进行上下文切换的次数,例如等待 I / O 操作完成。
    %c 进程被迫进行上下文切换的次数(由于时间片到期)。

clock() / clock_gettime()函数

clock()

注意:clock()函数返回的是进程在运行中使用 cpu 的时间,而非真实时间时间流逝。显然这个时间比真实时间慢很多,除非你程序满 cpu 在跑。

这个函数比较适合用来衡量程序性能。

用法

clock()/CLOCKS_PER_SEC 可以得到秒计数的时间。

用例

#include<stdio.h>           
#include <time.h>               /* 要包含的头文件 */

int main(int argc, char *argv[])
{
    /* Init  */
    clock_t start, end;
    start = clock();           /* 记录起始时间 */

    printf("time calc test\n");
/*
* 函数进行的一些列操作
* */

    /* Final Status */
    end = clock();           /* 记录结束时间 */
    {double seconds  =(double)(end - start)/CLOCKS_PER_SEC;
        fprintf(stderr, "Use time is: %.8f\n", seconds);
    }
    return 0;
}

运行结果:

# time ./helloTest
time calc test
Use time is 0.00003100

real    0m0.003s
user    0m0.000s
sys     0m0.000s

clock_gettime()

原型

extern int clock_gettime(clockid_t, struct timespec*);
  • 参数 clockid_t 类型常见的有四种:

    • CLOCK_REALTIME:系统实时时间。
    • CLOCK_MONOTONIC:从系统启动时开始计时,不受系统时间被用户改变的影响。
    • CLOCK_PROCESS_CPUTIME_ID:本进程到当前代码系统 CPU 花费的时间,包含该进程下的所有线程。
    • CLOCK_THREAD_CPUTIME_ID:本线程到当前代码系统 CPU 花费的时间。
    • CLOCK_REALTIME_COARSE:精度低,速度快
    • CLOCK_MONOTONIC_COARSE:精度低,速度快
    • CLOCK_MONOTONIC_RAW:和 CLOCK_MONOTONIC 类似,但是它是访问的硬件时间,不受 NTP 时间服务器的调整和 adjtime()的影响。
    • CLOCK_BOOTTIME:和 CLOCK_MONOTONIC 一样,但是包含系统挂起的时间。
  • 参数 struct timespec

    struct timespec {
     __kernel_time_t tv_sec;
     long tv_nsec;
    };

可以看到,如果用 CLOCK_PROCESS_CPUTIME_ID,就和直接用 clock()是一样的。而要计算现实时间,就不能用后两种类型,必须用 CLOCK_REALTIME 或者 CLOCK_MONOTONIC。要计算时间差,秒对秒一减,纳秒对纳秒一减,统一到同一个单位相加即可。

退出移动版