C中的“通用”功能 - 对2个不同的库使用相同的时间测量功能

时间:2014-06-19 14:02:19

标签: c

我在这里找到了一个简单的函数来测量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);
}

现在我想用它来衡量一些加密函数的执行情况。就目前而言,我只对OpensslCrypto++感兴趣(但希望将列表扩展到其他库)。

在C ++中我会使用模板,但C怎么样?让我们说,我有两个功能:

void md4_openssl(...);void md4_cryptopp(...);所有参数设置(键,缓冲区,...)都在这些函数中。现在,我怎样才能使我的测量功能更加通用&#34;?就像这样的事情是可能的:

void measureTime()
{
   function(); // could be md4_openssl or md4_cryptopp
}

当然,如果安装,我会使用opnessl,但如果不安装,则会调用cryptopp函数

1 个答案:

答案 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}}函数,让你的包装器函数调用它们。