| version 1.9, 2002/09/29 03:55:01 |
version 1.10, 2002/10/05 09:50:57 |
|
|
| /** |
/** |
| |
* Code max/min/avg time spend counting |
| |
* |
| * @file platon/misc/rdtsc.h |
* @file platon/misc/rdtsc.h |
| * @brief Code max/min/avg time spend counting |
|
| * @author Lynx ??? <mizon@centrum.sk> |
* @author Lynx ??? <mizon@centrum.sk> |
| * @author Lubomir Host <rajo@host.sk> |
* @author Lubomir Host <rajo@host.sk> |
| * @author Ondrej Jombik <nepto@pobox.sk> |
* @author Ondrej Jombik <nepto@pobox.sk> |
| * @version \$Id$ |
* @version \$Platon: rdtsc.h,v 1.9 2002/09/29 03:55:01 nepto Exp $ |
| * @date 2001-2002 |
* @date 2002 |
| |
* |
| |
* 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 |
#ifndef _PLATON_MISC_RDTSC_H |
| #define _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 |
* @name Result types |
| * @internal dummy text to make silly Doxygen happy |
* @internal dummy text to make Doxygen happy |
| */ |
*/ |
| /*@{*/ |
/*@{*/ |
| #define RDTSC_FIRST 0 /**< First result; default behaviour */ |
#define RDTSC_FIRST 0 /**< First result; default behaviour */ |
|
|
| #define RDTSC_MAX 2 /**< Longest result */ |
#define RDTSC_MAX 2 /**< Longest result */ |
| #define RDTSC_AVG 3 /**< Average result */ |
#define RDTSC_AVG 3 /**< Average result */ |
| /*@}*/ |
/*@}*/ |
| |
#endif /* #ifndef PLATON_DOXYGEN_SKIP */ |
| #ifdef __cplusplus |
|
| extern "C" { |
|
| #endif |
|
| |
|
| /** |
/** |
| * Get first time result of code execution |
* Get first time result of code execution |
|
|
| #define rdtsc_avg(code, count, result) \ |
#define rdtsc_avg(code, count, result) \ |
| rdtsc_core(RDTSC_AVG, code, count, result) |
rdtsc_core(RDTSC_AVG, code, count, result) |
| |
|
| |
#ifndef PLATON_DOXYGEN_SKIP |
| |
|
| /** |
/** |
| * Time spend counting core function |
* Time spend counting core function |
| * |
* |
| * @internal dummy text to make silly Doxygen happy |
* @internal dummy text to make Doxygen happy |
| * this must be at the beginning, else Doxygen will f*ck this up |
* this must be at the beginning, else Doxygen will f*ck this up |
| * @param type type of result, see Result types |
* @param type type of result, see Result types |
| * (@ref RDTSC_FIRST and similar) |
* (@ref RDTSC_FIRST and similar) |
|
|
| #define rdtsc_core(type, code, count, result) \ |
#define rdtsc_core(type, code, count, result) \ |
| do { \ |
do { \ |
| unsigned long __start, __end, __i; \ |
unsigned long __start, __end, __i; \ |
| double __result; \ |
double __result; \ |
| for (__i = 0; __i < (count); __i++) { \ |
for (__i = 0; __i < (count); __i++) { \ |
| __asm__ __volatile__("rdtsc" : "=a" (__start) : : "edx"); \ |
__asm__ __volatile__("rdtsc" : "=a" (__start) : : "edx"); \ |
| (code); \ |
(code); \ |
| __asm__ __volatile__("rdtsc" : "=a" (__end) : : "edx"); \ |
__asm__ __volatile__("rdtsc" : "=a" (__end) : : "edx"); \ |
| __end -= __start; \ |
__end -= __start; \ |
| if ((type) == RDTSC_AVG) { \ |
if ((type) == RDTSC_AVG) { \ |
| /* compute average value on the fly */ \ |
/* compute average value on the fly */ \ |
| /* can't be optimized due overflow */ \ |
/* can't be optimized due overflow */ \ |
| __result = (__result * ((double) __i / ((double) __i + 1)) \ |
__result = (__result * ((double) __i / ((double) __i + 1)) \ |
| + (double) __end / ((double) __i + 1)); \ |
+ (double) __end / ((double) __i + 1)); \ |
| |
} \ |
| |
else { \ |
| |
if (! __i \ |
| |
|| ((type) == RDTSC_MIN && __end < __result) \ |
| |
|| ((type) == RDTSC_MAX && __end > __result)) \ |
| |
__result = __end; \ |
| |
} \ |
| } \ |
} \ |
| else { \ |
|
| if (! __i \ |
|
| || ((type) == RDTSC_MIN && __end < __result) \ |
|
| || ((type) == RDTSC_MAX && __end > __result)) \ |
|
| __result = __end; \ |
|
| } \ |
|
| } \ |
|
| (result) = __result; \ |
(result) = __result; \ |
| } while(0) |
} while(0) |
| |
#endif /* #ifndef PLATON_DOXYGEN_SKIP */ |
| #ifdef __cplusplus |
|
| } |
|
| #endif |
|
| |
|
| #endif /* #ifndef _PLATON_MISC_RDTSC_H */ |
#endif /* #ifndef _PLATON_MISC_RDTSC_H */ |
| |
|