2

I am wondering if it is possible to create a clever macro to automatically bench a "process" in C and using only C. Let's say I have a small structure like this:

typedef struct pbench {
  char description[256];
  int nbenchs;
  double times;
} ProcessBench;

And a macro (with get_time() being a function returning a double):

#define BENCH(process, bench_struct, description)      \
  int i;                                               \
  bench_struct.description = description;              \
  bench_struct.nbenchs = 50;                           \
  double start = get_time();                           \
  for (i = 0; i < bench_struct.nbenchs; ++i)           \
    process();                                         \
  bench_struct.times = get_time() - start;

If I'm not mistaken, this macro can be used to benchmark any function with the signature void func() using BENCH(func, func_bench, func_description).

Is there a way I can create some macros like this one to benchmark functions like void func_args(args...), return_type func_return(), return_type func_return(args...) and even small lines of code ?

Kyle Strand
  • 15,941
  • 8
  • 72
  • 167
baptiste
  • 1,107
  • 2
  • 15
  • 30
  • Never use a macro where a function will also work. – too honest for this site Sep 27 '16 at 16:54
  • @Olaf: difficult to do this with a function in C, particularly if the timed function needs to have arbitrary parameters. – Paul R Sep 27 '16 at 17:28
  • @PaulR: I refer to what OP shows. There are no parameters; not sure what he means with "process" in this context, though. Alternatively a mixture of two functions and a macro would be an option. In any case, that macro above does not look very sane to me. – too honest for this site Sep 27 '16 at 17:46
  • 1
    The idea is to have only one function / macro to bench a lot of different stuff on a lot of platforms. I think a macro is a better way to do this. By process I mean any kind of function and at the same time, bench it without polluting the code with benchmarking specific instructions. – baptiste Sep 28 '16 at 07:05

2 Answers2

2

You can just pass the whole function call, including parameters, and ignore any function result, e.g.

#define BENCH(process, bench_struct, description) do { \
  int i;                                               \
  bench_struct.description = description;              \
  bench_struct.nbenchs = 50;                           \
  double start = get_time();                           \
  for (i = 0; i < bench_struct.nbenchs; ++i)           \
    process;                                           \
  bench_struct.times = get_time() - start;             \
} while (0)


BENCH(func(x, y, z), func_bench, func_description)

(Note the small change to the macro - the parentheses have been removed from process.)

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • 5
    It would be good to enclose it in a block to avoid any clashes with `i`. Even better if it's a [`do { ... } while(0)`](http://stackoverflow.com/questions/154136/why-use-apparently-meaningless-do-while-and-if-else-statements-in-c-c-macros). – Andrea Biondo Sep 27 '16 at 16:56
  • @AndreaBiondo: yes, good point, added enclosing do/while (0) – Paul R May 16 '23 at 11:46
2

here is my solution.

#define benchmark(x) for (float startTime = (float)clock() / CLOCKS_PER_SEC, run = 1.0; run == 1.0; run = 0, printf("\n%s\nTime elapsed: %fs\n", x, (float)clock() / CLOCKS_PER_SEC - startTime))

Make sure it is in one line or use "\". Use it like this:

benchmark("Some description")    
{    
    ///your code that you wanna measure its execution time     
}