/** * Code max/min/avg time spend counting * * @file platon/misc/rdtsc.h * @author Tomas Corej * @author Lubomir Host * @author Ondrej Jombik * @version \$Platon: libplaton/platon/misc/rdtsc.h,v 1.13 2003/04/23 19:01:37 nepto Exp $ * @date 2002-2003 * * This set of macros are very useful in particular code parts time spend * counting. They can be also used for benchmarking. Note, that result depens * on many factors such as architecture, operating system, machine load, etc. * * Here is simple example of usage: * * @code * double result_avg; * rdtsc_avg(time(NULL), 500000, result_avg); * printf("time(NULL): avg:%g\n", result_avg); * @endcode */ #ifndef _PLATON_MISC_RDTSC_H #define _PLATON_MISC_RDTSC_H #ifndef PLATON_DOXYGEN_SKIP /* Skipped parts of code by Doxygen are already documented. It can be usuable when generating private documentation for libplaton developers, not for public usage. */ /** * @name Result types * @internal dummy text to make Doxygen happy */ /*@{*/ #define RDTSC_FIRST 0 /**< First result; default behaviour */ #define RDTSC_MIN 1 /**< Shortest result */ #define RDTSC_MAX 2 /**< Longest result */ #define RDTSC_AVG 3 /**< Average result */ /*@}*/ #endif /* #ifndef PLATON_DOXYGEN_SKIP */ /** * Get first time result of code execution * * @param code code to execute * @param count number of repetition * @retval result pointer to double where time result will be stored */ #define rdtsc_first(code, count, result) \ rdtsc_core(RDTSC_FIRST, code, count, result) /** * Get shortest time result from code executions * * @param code code to execute * @param count number of repetition * @retval result pointer to double where time result will be stored */ #define rdtsc_min(code, count, result) \ rdtsc_core(RDTSC_MIN, code, count, result) /** * Get longest time result from code executions * * @param code code to execute * @param count number of repetition * @retval result pointer to double where time result will be stored */ #define rdtsc_max(code, count, result) \ rdtsc_core(RDTSC_MAX, code, count, result) /** * Get average time result from code executions * * @param code code to execute * @param count number of repetition * @retval result pointer to double where time result will be stored */ #define rdtsc_avg(code, count, result) \ rdtsc_core(RDTSC_AVG, code, count, result) #ifndef PLATON_DOXYGEN_SKIP /** * Time spend counting core function * * @internal dummy text to make Doxygen happy * this must be at the beginning, else Doxygen will f*ck this up * @param type type of result, see Result types * (@ref RDTSC_FIRST and similar) * @param code code to execute * @param count number of repetition * @retval result pointer to double where time result will be stored */ #define rdtsc_core(type, code, count, result) \ do { \ unsigned long __start, __end, __i; \ double __result; \ for (__i = 0; __i < (count); __i++) { \ __asm__ __volatile__("rdtsc" : "=a" (__start) : : "edx"); \ code \ __asm__ __volatile__("rdtsc" : "=a" (__end) : : "edx"); \ __end -= __start; \ if ((type) == RDTSC_AVG) { \ /* compute average value on the fly */ \ /* can't be optimized due overflow */ \ __result = (__result * ((double) __i / ((double) __i + 1)) \ + (double) __end / ((double) __i + 1)); \ } \ else { \ if (! __i \ || ((type) == RDTSC_MIN && __end < __result) \ || ((type) == RDTSC_MAX && __end > __result)) \ __result = __end; \ } \ } \ (result) = __result; \ } while(0) #endif /* #ifndef PLATON_DOXYGEN_SKIP */ #endif /* #ifndef _PLATON_MISC_RDTSC_H */