我在这里找到了一个简单的函数来测量C中函数的执行时间:
#include <stdio.h>
#include <stdint.h>
#include <time.h>
int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}
int main(int argc, char **argv)
{
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
// Some code I am interested in measuring
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t timeElapsed = timespecDiff(&end, &start);
}
现在我想用它来衡量一些加密函数的执行情况。就目前而言,我只对Openssl
和Crypto++
感兴趣(但希望将列表扩展到其他库)。
在C ++中我会使用模板,但C怎么样?让我们说,我有两个功能:
void md4_openssl(...);
和void md4_cryptopp(...);
所有参数设置(键,缓冲区,...)都在这些函数中。现在,我怎样才能使我的测量功能更加通用&#34;?就像这样的事情是可能的:
void measureTime()
{
function(); // could be md4_openssl or md4_cryptopp
}
当然,如果安装,我会使用opnessl
,但如果不安装,则会调用cryptopp
函数
答案 0 :(得分:3)
显而易见的方法是将函数指针传递给measureTime()
:
uint64_t measureTime(void (*fp)(void)) {
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
fp(); // Call the function you want to measure
clock_gettime(CLOCK_MONOTONIC, &end);
return timespecDiff(&end, &start);
}
void measure_ssl(void) {
md4_openssl(1, 2, 3, whatever); // Setup and call however you need to
}
void measure_crypt(void) {
md4_cryptopp(1, 2, 3, whatever); // Setup and call however you need to
}
int main(void) {
uint64_t t1 = measureTime(measure_ssl);
uint64_t t2 = measureTime(measure_crypt);
// Do something with t1 and t2
return 0;
}
编辑:响应您的注释,传递给函数的任何函数指针都必须具有与参数匹配的签名。如果你需要调用具有不同签名的函数,那么你需要像上面的代码一样包装它们。
如果您的包装函数可以处理参数,那么您只需使用上面的代码而无需修改。换句话说,measure_ssl()
可以拨打md4_openssl(1, 2, 3, "more", "args")
,measure_crypt()
可以拨打md4_cryptopp(5.4, "different", ARGS)
或其他任何内容。
如果确实需要向measureTime()
提供实际参数,那么您必须将信息传递给包装函数并让它们做一些解释。如果每个函数都使用了一个指针,但是它的类型不同,那么你可以传递一个void *
并传递它。
如果参数可以完全不同且不可预测,那么最简单的方法是创建一个struct
并传递该地址,例如:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <time.h>
void func1(int a, int b, int c) {
printf("Let's count to %d, %d and %d!\n", a, b, c);
}
struct func1_params {
int a;
int b;
int c;
};
void func2(double d, const char * c) {
printf("There are %f %ss\n", d, c);
}
struct func2_params {
double d;
const char * c;
};
void func1_wrap(void * params) {
struct func1_params * p = params;
func1(p->a, p->b, p->c);
}
void func2_wrap(void * params) {
struct func2_params * p = params;
func2(p->d, p->c);
}
int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p) {
return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}
uint64_t measureTime(void (*fp)(void *), void * params) {
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
fp(params);
clock_gettime(CLOCK_MONOTONIC, &end);
return timespecDiff(&end, &start);
}
int main(void) {
struct func1_params p1 = {1, 2, 3};
uint64_t t1 = measureTime(func1_wrap, &p1);
struct func2_params p2 = {3.14159, "pie"};
uint64_t t2 = measureTime(func2_wrap, &p2);
printf("First func took time %" PRIu64 " units.\n", t1);
printf("Second func took time %" PRIu64 " units.\n", t2);
return 0;
}
这是通用的,因为measureTime()
并不需要了解您正在调用的函数或struct
的任何内容。你可以将它编译成一个库,然后再写一下,比如func1_wrap()
和struct func1_params
并传入它们。你可以通过编写一个{{1}来测量你喜欢的任何函数的时间。包含参数和类型struct
的包装函数,以接受指向该结构的指针,并将成员作为参数传递给您感兴趣的函数。
在上面的代码中,我提供了void (*)(void *)
和func1()
的定义,以提供完整的工作示例,但您可以将其视为func2()
和md4_openssl()
{1}}函数,让你的包装器函数调用它们。