vprof.h (9666B)
1 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 4 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 // 7 // Here are a few examples of using the value-profiling utility: 8 // 9 // _vprof (e); 10 // at the end of program execution, you'll get a dump of the source location 11 // of this probe, its min, max, average, the total sum of all instances of e, 12 // and the total number of times this probe was called. 13 // 14 // _vprof (x > 0); 15 // shows how many times and what percentage of the cases x was > 0, 16 // that is the probablitiy that x > 0. 17 // 18 // _vprof (n % 2 == 0); 19 // shows how many times n was an even number 20 // as well as th probablitiy of n being an even number. 21 // 22 // _hprof (n, 4, 1000, 5000, 5001, 10000); 23 // gives you the histogram of n over the given 4 bucket boundaries: 24 // # cases < 1000 25 // # cases >= 1000 and < 5000 26 // # cases >= 5000 and < 5001 27 // # cases >= 5001 and < 10000 28 // # cases >= 10000 29 // 30 // _nvprof ("event name", value); 31 // all instances with the same name are merged 32 // so, you can call _vprof with the same event name at difference places 33 // 34 // _vprof (e, myProbe); 35 // value profile e and call myProbe (void* vprofID) at the profiling point. 36 // inside the probe, the client has the predefined variables: 37 // _VAL, _COUNT, _SUM, _MIN, _MAX, and the general purpose registers 38 // _IVAR1, ..., IVAR4 general integer registrs 39 // _I64VAR1, ..., I64VAR4 general integer64 registrs 40 // _DVAR1, ..., _DVAR4 general double registers 41 // _GENPTR a generic pointer that can be used by the client 42 // the number of registers can be changed in vprof.h 43 // 44 45 #ifndef devtools_vprof_vprof_h 46 #define devtools_vprof_vprof_h 47 // 48 // If the application for which you want to use vprof is threaded, THREADED must 49 // be defined as 1, otherwise define it as 0 50 // 51 // If your application is not threaded, define THREAD_SAFE 0, 52 // otherwise, you have the option of setting THREAD_SAFE to 1 which results in 53 // exact counts or to 0 which results in a much more efficient but non-exact 54 // counts 55 // 56 #define THREADED 0 57 #define THREAD_SAFE 0 58 59 #include "VMPI.h" 60 61 // Note, this is not supported in configurations with more than one AvmCore 62 // running in the same process. 63 64 // portable align macro 65 #if defined(_MSC_VER) 66 # define vprof_align8(t) __declspec(align(8)) t 67 #elif defined(__GNUC__) 68 # define vprof_align8(t) t __attribute__((aligned(8))) 69 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) 70 # define vprof_align8(t) t __attribute__((aligned(8))) 71 #elif defined(VMCFG_SYMBIAN) 72 # define vprof_align8(t) t __attribute__((aligned(8))) 73 #endif 74 75 #ifdef __cplusplus 76 extern "C" { 77 #endif 78 79 int initValueProfile(void** id, char* file, int line, ...); 80 int profileValue(void* id, int64_t value); 81 int initHistProfile(void** id, char* file, int line, int nbins, ...); 82 int histValue(void* id, int64_t value); 83 uint64_t readTimestampCounter(); 84 85 #ifdef __cplusplus 86 } 87 #endif 88 89 // #define DOPROF 90 91 #ifndef DOPROF 92 # define _nvprof(e, v) 93 # ifndef VMCFG_SYMBIAN 94 # define _vprof(v, ...) 95 # define _hprof(v, n, ...) 96 # define _nhprof(e, v, n, ...) 97 # define _ntprof_begin(e) 98 # define _ntprof_end(e) 99 # define _jvprof_init(id, ...) 100 # define _jnvprof_init(id, e, ...) 101 # define _jhprof_init(id, n, ...) 102 # define _jnhprof_init(id, e, n, ...) 103 # define _jvprof(id, v) 104 # define _jhprof(id, v) 105 # endif // ! VMCFG_SYMBIAN 106 #else 107 108 // Historical/compatibility note: 109 // The macros below were originally written using conditional expressions, not 110 // if/else. The original author said that this was done to allow _vprof and 111 // _nvprof to be used in an expression context, but the old code had already 112 // wrapped the macro bodies in { }, so it is not clear how this could have 113 // worked. At present, the profiling macros must appear in a statement context 114 // only. 115 116 # define _vprof(v, ...) \ 117 do { \ 118 static void* id = 0; \ 119 if (id == 0) \ 120 initValueProfile(&id, __FILE__, __LINE__, ##__VA_ARGS__, NULL); \ 121 profileValue(id, (int64_t)(v)); \ 122 } while (0) 123 124 # define _nvprof(e, v) \ 125 do { \ 126 static void* id = 0; \ 127 if (id == 0) initValueProfile(&id, (char*)(e), -1, NULL); \ 128 profileValue(id, (int64_t)(v)); \ 129 } while (0) 130 131 # define _hprof(v, n, ...) \ 132 do { \ 133 static void* id = 0; \ 134 if (id == 0) \ 135 initHistProfile(&id, __FILE__, __LINE__, (int)(n), ##__VA_ARGS__); \ 136 histValue(id, (int64_t)(v)); \ 137 } while (0) 138 139 # define _nhprof(e, v, n, ...) \ 140 do { \ 141 static void* id = 0; \ 142 if (id == 0) \ 143 initHistProfile(&id, (char*)(e), -1, (int)(n), ##__VA_ARGS__); \ 144 histValue(id, (int64_t)(v)); \ 145 } while (0) 146 147 // Profile execution time between _ntprof_begin(e) and _ntprof_end(e). 148 // The tag 'e' must match at the beginning and end of the region to 149 // be timed. Regions may be nested or overlap arbitrarily, as it is 150 // the tag alone that defines the begin/end correspondence. 151 152 # define _ntprof_begin(e) \ 153 do { \ 154 static void* id = 0; \ 155 if (id == 0) initValueProfile(&id, (char*)(e), -1, NULL); \ 156 ((entry_t)id)->i64var[0] = readTimestampCounter(); \ 157 } while (0) 158 159 // Assume 2.6 Ghz CPU 160 # define TICKS_PER_USEC 2600 161 162 # define _ntprof_end(e) \ 163 do { \ 164 static void* id = 0; \ 165 uint64_t stop = readTimestampCounter(); \ 166 if (id == 0) initValueProfile(&id, (char*)(e), -1, NULL); \ 167 uint64_t start = ((entry_t)id)->i64var[0]; \ 168 uint64_t usecs = (stop - start) / TICKS_PER_USEC; \ 169 profileValue(id, usecs); \ 170 } while (0) 171 172 // These macros separate the creation of a profile record from its later usage. 173 // They are intended for profiling JIT-generated code. Once created, the JIT 174 // can bind a pointer to the profile record into the generated code, which can 175 // then record profile events during execution. 176 177 # define _jvprof_init(id, ...) \ 178 if (*(id) == 0) \ 179 initValueProfile((id), __FILE__, __LINE__, ##__VA_ARGS__, NULL) 180 181 # define _jnvprof_init(id, e, ...) \ 182 if (*(id) == 0) initValueProfile((id), (char*)(e), -1, ##__VA_ARGS__, NULL) 183 184 # define _jhprof_init(id, n, ...) \ 185 if (*(id) == 0) \ 186 initHistProfile((id), __FILE__, __LINE__, (int)(n), ##__VA_ARGS__) 187 188 # define _jnhprof_init(id, e, n, ...) \ 189 if (*(id) == 0) \ 190 initHistProfile((id), (char*)(e), -1, (int)(n), ##__VA_ARGS__) 191 192 // Calls to the _jvprof and _jhprof macros must be wrapped in a non-inline 193 // function in order to be invoked from JIT-compiled code. 194 195 # define _jvprof(id, v) profileValue((id), (int64_t)(v)) 196 197 # define _jhprof(id, v) histValue((id), (int64_t)(v)) 198 199 #endif 200 201 #define NUM_EVARS 4 202 203 enum { LOCK_IS_FREE = 0, LOCK_IS_TAKEN = 1 }; 204 205 extern 206 #ifdef __cplusplus 207 "C" 208 #endif 209 long 210 _InterlockedCompareExchange(long volatile* Destination, long Exchange, 211 long Comperand); 212 213 typedef struct hist hist; 214 215 typedef struct hist { 216 int nbins; 217 int64_t* lb; 218 int64_t* count; 219 }* hist_t; 220 221 typedef struct entry entry; 222 223 typedef struct entry { 224 long lock; 225 char* file; 226 int line; 227 int64_t value; 228 int64_t count; 229 int64_t sum; 230 int64_t min; 231 int64_t max; 232 void (*func)(void*); 233 hist* h; 234 235 entry* next; 236 237 // exposed to the clients 238 void* genptr; 239 int ivar[NUM_EVARS]; 240 vprof_align8(int64_t) i64var[NUM_EVARS]; 241 vprof_align8(double) dvar[NUM_EVARS]; 242 // 243 244 char pad[128]; // avoid false sharing 245 }* entry_t; 246 247 #define _VAL ((entry_t)vprofID)->value 248 #define _COUNT ((entry_t)vprofID)->count 249 #define _SUM ((entry_t)vprofID)->sum 250 #define _MIN ((entry_t)vprofID)->min 251 #define _MAX ((entry_t)vprofID)->max 252 253 #define _GENPTR ((entry_t)vprofID)->genptr 254 255 #define _IVAR0 ((entry_t)vprofID)->ivar[0] 256 #define _IVAR1 ((entry_t)vprofID)->ivar[1] 257 #define _IVAR2 ((entry_t)vprofID)->ivar[2] 258 #define _IVAR3 ((entry_t)vprofID)->ivar[3] 259 260 #define _I64VAR0 ((entry_t)vprofID)->i64var[0] 261 #define _I64VAR1 ((entry_t)vprofID)->i64var[1] 262 #define _I64VAR2 ((entry_t)vprofID)->i64var[2] 263 #define _I64VAR3 ((entry_t)vprofID)->i64var[3] 264 265 #define _DVAR0 ((entry_t)vprofID)->dvar[0] 266 #define _DVAR1 ((entry_t)vprofID)->dvar[1] 267 #define _DVAR2 ((entry_t)vprofID)->dvar[2] 268 #define _DVAR3 ((entry_t)vprofID)->dvar[3] 269 270 #endif /* devtools_vprof_vprof_h */