76 lines
3.2 KiB
C
76 lines
3.2 KiB
C
#ifndef TIME_IT_H
|
|
#define TIME_IT_H
|
|
|
|
#include <stddef.h>
|
|
#include <time.h>
|
|
|
|
#define ARRAY_OF double
|
|
#include "array.h"
|
|
|
|
|
|
/*
|
|
* time_it - executes the provided code and returns a
|
|
* following argument (a1, a2, ..., an)
|
|
* resulting in (fun(a1)), (fun(a2)), ..., (fun(an))
|
|
*
|
|
* @code: the code to time; It can be a simple function call or
|
|
* a full block code
|
|
* @...: the optional argument number that
|
|
*
|
|
* @return: the elapsed execution time in seconds
|
|
* Note: fun can be either a macro, a function or a cast
|
|
* in parenthesis (e.g. for_each((char), 67, 10))
|
|
*/
|
|
#define time_it(code, ...) TIME_IT_NOT_EXPOSED__GENERIC_IMPLEMENTATION(, code, __VA_ARGS__)
|
|
|
|
/*
|
|
* for_each - apply a function-like object (fun) to each
|
|
* following argument (a1, a2, ..., an)
|
|
* resulting in (fun(a1)), (fun(a2)), ..., (fun(an))
|
|
*
|
|
* @fun: the function-like object to apply
|
|
* @...: the list of agurments on which to apply
|
|
*
|
|
* Note: fun can be either a macro, a function or a cast
|
|
* in parenthesis (e.g. for_each((char), 67, 10))
|
|
*/
|
|
#define time_it_repeat(code, ...) TIME_IT_NOT_EXPOSED__GENERIC_IMPLEMENTATION(REPEAT, code, __VA_ARGS__)
|
|
|
|
|
|
#define TIME_IT_NOT_EXPOSED__GENERIC_IMPLEMENTATION(type, code, ...) __extension__({ \
|
|
struct time_it_params { TIME_IT_NOT_EXPOSED__IF_REPEAT(type, size_t repeat;) size_t number;} time_it_params = (struct time_it_params){ TIME_IT_NOT_EXPOSED__IF_REPEAT(type, .repeat = 1, _) .number = 1}; \
|
|
__VA_OPT__(time_it_params TIME_IT_NOT_EXPOSED__FIRST_ARG(__VA_ARGS__);) \
|
|
__VA_OPT__(TIME_IT_NOT_EXPOSED__MAYBE_SECOND_ARG(time_it_params TIME_IT_NOT_EXPOSED__FIRST_ARG, __VA_ARGS__);) \
|
|
TIME_IT_NOT_EXPOSED__INIT_RES(type, time_it_params.repeat);\
|
|
TIME_IT_NOT_EXPOSED__IF_REPEAT(type, for(size_t i = 0; i < time_it_params.repeat; i++){) \
|
|
double time_it_time = 0; \
|
|
for(size_t j = 0; j < time_it_params.number; j++){ \
|
|
struct timespec time_it_start, time_it_stop; \
|
|
clock_gettime(CLOCK_MONOTONIC, &time_it_start); \
|
|
code; \
|
|
clock_gettime(CLOCK_MONOTONIC, &time_it_stop); \
|
|
time_it_time += ((time_it_stop.tv_sec - time_it_start.tv_sec) + (time_it_stop.tv_nsec - time_it_start.tv_nsec) / 1000000000.0); \
|
|
}\
|
|
TIME_IT_NOT_EXPOSED__WRITE_RES(type, time_it_time); \
|
|
TIME_IT_NOT_EXPOSED__IF_REPEAT(type, }) \
|
|
res;\
|
|
})
|
|
|
|
|
|
#define TIME_IT_NOT_EXPOSED__MAYBE_SECOND_ARG(macro, a1, ...) __VA_OPT__(macro(__VA_ARGS__))
|
|
#define TIME_IT_NOT_EXPOSED__FIRST_ARG(a1, ...) a1
|
|
|
|
#define TIME_IT_NOT_EXPOSED__INIT_RES_REPEAT(repeat) double_arr_t *res = double_arr_init(repeat)
|
|
#define TIME_IT_NOT_EXPOSED__INIT_RES_(_) double res = 0
|
|
#define TIME_IT_NOT_EXPOSED__INIT_RES(type, repeat) TIME_IT_NOT_EXPOSED__INIT_RES_ ## type (repeat)
|
|
|
|
#define TIME_IT_NOT_EXPOSED__WRITE_RES_REPEAT(value) double_arr_push(res, value)
|
|
#define TIME_IT_NOT_EXPOSED__WRITE_RES_(value) res = value
|
|
#define TIME_IT_NOT_EXPOSED__WRITE_RES(type, value) TIME_IT_NOT_EXPOSED__WRITE_RES_ ## type(value)
|
|
|
|
#define TIME_IT_NOT_EXPOSED__IF_REPEAT_REPEAT(code, ...) code __VA_OPT__(,)
|
|
#define TIME_IT_NOT_EXPOSED__IF_REPEAT_(...)
|
|
#define TIME_IT_NOT_EXPOSED__IF_REPEAT(type, ...) TIME_IT_NOT_EXPOSED__IF_REPEAT_ ## type (__VA_ARGS__)
|
|
|
|
#endif //TIME_IT_H
|