File indexing completed on 2026-11-07 10:15:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef FLINT_PROFILER_H
0015 #define FLINT_PROFILER_H
0016
0017 #if defined(_MSC_VER)
0018 # include <intrin.h>
0019 # include "gettimeofday.h"
0020 # pragma intrinsic(__rdtsc)
0021 #else
0022 # include <sys/time.h>
0023 #endif
0024 #include <time.h>
0025 #include "flint.h"
0026
0027 #if defined(_MSC_VER) || defined(__x86_64__) || defined(__aarch64__)
0028 # define FLINT_HAVE_get_cycle_counter 1
0029 #endif
0030 #if (defined(__unix__) && !defined(__CYGWIN__) && !defined(__EMSCRIPTEN__)) || defined(__APPLE__)
0031 # define FLINT_HAVE_getrusage 1
0032 #endif
0033
0034 #define FLINT_NUM_CLOCKS 20
0035 #if !defined(FLINT_CLOCKSPEED)
0036 # define FLINT_CLOCKSPEED 3100000000.0
0037 #endif
0038 #define FLINT_CLOCK_SCALE_FACTOR (1000000.0 / FLINT_CLOCKSPEED)
0039
0040 #ifdef __cplusplus
0041 extern "C" {
0042 #endif
0043
0044 #if defined(__WIN32) && !defined(__CYGWIN__) && !defined(_MSC_VER)
0045 int gettimeofday(struct timeval * p, void * tz);
0046 #endif
0047
0048
0049
0050 #if FLINT_HAVE_getrusage
0051 #if FLINT_HAVE_FILE
0052 void fprint_memory_usage(FILE * fs);
0053 #endif
0054 void print_memory_usage(void);
0055 #endif
0056
0057
0058
0059 typedef struct { slong cpu, wall; } timeit_t[1];
0060
0061 static inline void timeit_start(timeit_t t)
0062 {
0063 struct timeval tv;
0064 gettimeofday(&tv, 0);
0065 t->wall = - tv.tv_sec * 1000 - tv.tv_usec / 1000;
0066 t->cpu = - clock() * 1000 / CLOCKS_PER_SEC;
0067 }
0068
0069 static inline slong timeit_query_wall(timeit_t t)
0070 {
0071 struct timeval tv;
0072 gettimeofday(&tv, 0);
0073 return t->wall + tv.tv_sec * 1000 + tv.tv_usec / 1000;
0074 }
0075
0076 static inline void timeit_stop(timeit_t t)
0077 {
0078 struct timeval tv;
0079 gettimeofday(&tv, 0);
0080 t->wall += tv.tv_sec * 1000 + tv.tv_usec / 1000;
0081 t->cpu += clock() * 1000 / CLOCKS_PER_SEC;
0082 }
0083
0084 static inline void timeit_start_us(timeit_t t)
0085 {
0086 struct timeval tv;
0087 gettimeofday(&tv, 0);
0088 t->wall = - tv.tv_sec * 1000000 - tv.tv_usec;
0089 }
0090
0091 static inline void timeit_stop_us(timeit_t t)
0092 {
0093 struct timeval tv;
0094 gettimeofday(&tv, 0);
0095 t->wall += tv.tv_sec * 1000000 + tv.tv_usec;
0096 }
0097
0098 static inline void timeit_print(timeit_t timer, ulong reps)
0099 {
0100 flint_printf("cpu/wall(s): %g %g\n", timer->cpu * 0.001 / reps,
0101 timer->wall * 0.001 / reps);
0102 }
0103
0104 #define TIMEIT_REPEAT(__timer, __reps) \
0105 do \
0106 { \
0107 slong __timeit_k; \
0108 __reps = 1; \
0109 while (1) \
0110 { \
0111 timeit_start(__timer); \
0112 for (__timeit_k = 0; __timeit_k < __reps; __timeit_k++) \
0113 {
0114
0115 #define TIMEIT_END_REPEAT(__timer, __reps) \
0116 } \
0117 timeit_stop(__timer); \
0118 if (__timer->cpu >= 100) \
0119 break; \
0120 __reps *= 10; \
0121 } \
0122 } while (0)
0123
0124 #define TIMEIT_START \
0125 do { \
0126 timeit_t __timer; slong __reps; \
0127 TIMEIT_REPEAT(__timer, __reps)
0128
0129 #define TIMEIT_STOP \
0130 TIMEIT_END_REPEAT(__timer, __reps); \
0131 timeit_print(__timer, __reps); \
0132 } while (0)
0133
0134 #define TIMEIT_STOP_VALUES(tcpu, twall) \
0135 TIMEIT_END_REPEAT(__timer, __reps); \
0136 (tcpu) = __timer->cpu*0.001 / __reps; \
0137 (twall) = __timer->wall*0.001 / __reps; \
0138 } while (0)
0139
0140 #define TIMEIT_ONCE_START \
0141 do \
0142 { \
0143 timeit_t __timer; \
0144 timeit_start(__timer); \
0145 do {
0146
0147 #define TIMEIT_ONCE_STOP \
0148 } while (0); \
0149 timeit_stop(__timer); \
0150 timeit_print(__timer, 1); \
0151 } while (0)
0152
0153
0154
0155 #if FLINT_HAVE_get_cycle_counter
0156 static inline double get_cycle_counter(void)
0157 {
0158 #if defined(_MSC_VER)
0159 return __rdtsc();
0160 #elif defined(__x86_64__)
0161 unsigned int hi, lo;
0162 __asm__ volatile ("rdtsc; movl %%edx,%0; movl %%eax,%1"
0163 : "=r" (hi), "=r" (lo) : : "%edx", "%eax");
0164 return hi * (double) (WORD(1) << 32) + lo;
0165 #elif defined(__aarch64__)
0166 ulong val;
0167 __asm__ volatile ("mrs %0, cntvct_el0" : "=r" (val));
0168 return val;
0169 #endif
0170 }
0171
0172 FLINT_DLL extern double clock_last[FLINT_NUM_CLOCKS];
0173 FLINT_DLL extern double clock_accum[FLINT_NUM_CLOCKS];
0174
0175 static inline void init_clock(int n)
0176 {
0177 clock_accum[n] = 0.0;
0178 }
0179
0180 static inline void init_all_clocks(void)
0181 {
0182 for (int i = 0; i < FLINT_NUM_CLOCKS; i++)
0183 init_clock(i);
0184 }
0185
0186 static inline double get_clock(int n)
0187 {
0188 return clock_accum[n] * FLINT_CLOCK_SCALE_FACTOR;
0189 }
0190
0191 static inline void start_clock(int n)
0192 {
0193 clock_last[n] = get_cycle_counter();
0194 }
0195
0196 static inline void stop_clock(int n)
0197 {
0198 double now = get_cycle_counter();
0199 clock_accum[n] += (now - clock_last[n]);
0200 }
0201
0202 #define DURATION_TARGET 10000.0
0203 #define DURATION_THRESHOLD 5000.0
0204
0205 static inline void prof_start(void) { start_clock(0); }
0206 static inline void prof_stop(void) { stop_clock(0); }
0207
0208 typedef void (*profile_target_t)(void* arg, ulong count);
0209
0210 void prof_repeat(double* min, double* max, profile_target_t target, void* arg);
0211
0212 #endif
0213
0214 #ifdef __cplusplus
0215 }
0216 #endif
0217
0218 #endif