在上一篇博客《python计时函数timeit.timeit()使用小结》中介绍了python中timeit()及其用法,现在我们看看如何在c中实现类似功能.
可以考虑使用一个接受变参的宏(Variadic Macro)来实现,在这种定义方式中,用"..."表示形参,运行时所有传入的实参被内置标识符__VA_ARGS__来取代。一个实现如下所示: 在运行函数前获取当前时间(line 9), 之后按指定的运行次数执行函数(line 11~13), 最后再一次获取当前时间(line 15), 两次时间差即为函数运行时间 (line 16-17). 需要指出的是,这里选用clock_gettime(CLOCK_PROCESS_CPUTIME, ...)来获取当前时间,基于两点考虑:1)可以得到纳秒(nano seconds)级别的精度; 2)CLOCK_PROCESS_CPUTIME时钟意味着Per-process CPU-time clock,从而排除了函数执行期间进程被操作系统schedule out的干扰。
1 #include <stdio.h> 2 #include <time.h> // for clock_gettime 3 #include <stdint.h> // for int64_t 4 5 6 #define timeit(n, func, ...) do { 7 uint64_t duration; 8 struct timespec start, end; 9 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); 10 11 for (int i=0; i<n; i++) { 12 func(__VA_ARGS__); 13 } 14 15 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); 16 duration = (end.tv_sec - start.tv_sec) * 1000000000 17 + (end.tv_nsec - start.tv_nsec); 18 19 char strSpan[256]; 20 char strAvgSpan[256]; 21 get_desc_time(duration, strSpan, sizeof(strSpan)); 22 get_desc_time(duration/n, strAvgSpan, sizeof(strAvgSpan)); 23 printf("%d loops, %s, avg: %s per loop\n", n, strSpan, strAvgSpan); 24 } while (0)
与python的timeit()相比,参数表示稍有不同:
n: 函数执行次数
func: 将要执行的函数
...: func的参数(0个或多个)
get_desc_time() 是格式化函数,将纳秒为单位的整数转换为可读性更强的字符串:
1 void get_desc_time(uint64_t ns, char *buf, int len) 2 { 3 uint64_t nano_per_sec = 1000000000; 4 uint64_t nano_per_milli = 1000000; 5 uint64_t nano_per_micro = 1000; 6 uint64_t unit = 1000; 7 8 uint64_t nanos = ns % unit; 9 uint64_t micros = ns / nano_per_micro % unit; 10 uint64_t millis = ns / nano_per_milli % unit; 11 uint64_t seconds = ns / nano_per_sec; 12 13 memset(buf, ‘\0‘, sizeof buf); 14 if (seconds > 0) { 15 snprintf(buf+strlen(buf), len-strlen(buf), "%lds", seconds); 16 } 17 18 if (millis > 0) { 19 snprintf(buf+strlen(buf), len-strlen(buf), "%ldms", millis); 20 } 21 22 if (micros > 0) { 23 snprintf(buf+strlen(buf), len-strlen(buf), "%ldµs", micros); 24 } 25 26 if (nanos > 0) { 27 snprintf(buf+strlen(buf), len-strlen(buf), "%ldns", nanos); 28 } 29 }
下面我们定义两个函数: 斐波那契函数fibanocci(int) 和最大公约数函数gcd(int, int), 并用timeit()对他们进行计时统计:
1 int fibonacci(int n) 2 { 3 if (n <= 0) { 4 return 0; 5 } else if (n == 1 || n == 2) { 6 return 1; 7 } 8 9 return fibonacci(n-1) + fibonacci(n-2); 10 } 11 12 13 int gcd(int a, int b)
14 { 15 if (a == 0 || b== 0) { 16 return 1; 17 } 18 19 int bigger = (a > b ? a : b); 20 int smaller = (a > b ? b : a); 21 if (bigger % smaller == 0) { 22 return smaller; 23 } 24 25 return gcd(smaller, bigger % smaller); 26 }
对fibanocci()进行统计:
1 printf("timeit(5, fibonacci, 25): "); 2 timeit(5, fibonacci, 25);
结果:timeit(5, fibonacci, 25): 5 loops, 3ms646µs173ns, avg: 729µs234ns per loop
对gcd()进行统计:
1 printf("timeit(10, gcd, 15000, 5525): "); 2 timeit(10, gcd, 15000, 5525);
结果:timeit(10, gcd, 15000, 5525): 10 loops, 1µs373ns, avg: 137ns per loop
原文:https://www.cnblogs.com/wangwenzhi2019/p/10893189.html