Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-07 10:15:34

0001 /*
0002     Copyright (C) 2007 William Hart
0003     Copyright (C) 2007 David Harvey
0004     Copyright (C) 2025 Albin Ahlbäck
0005 
0006     This file is part of FLINT.
0007 
0008     FLINT is free software: you can redistribute it and/or modify it under
0009     the terms of the GNU Lesser General Public License (LGPL) as published
0010     by the Free Software Foundation; either version 3 of the License, or
0011     (at your option) any later version.  See <https://www.gnu.org/licenses/>.
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 /* memory usage **************************************************************/
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 /* timeit ********************************************************************/
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 /* raw clock cycles **********************************************************/
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 /* FLINT_HAVE_get_cycle_counter */
0213 
0214 #ifdef __cplusplus
0215 }
0216 #endif
0217 
0218 #endif /* FLINT_PROFILER_H */