1 /* 2 * Copyright (C) 2014 Artem Polyakov <artpol84@gmail.com> 3 * Copyright (c) 2014-2017 Intel, Inc. All rights reserved. 4 * Copyright (c) 2015 Research Organization for Information Science 5 * and Technology (RIST). All rights reserved. 6 * $COPYRIGHT$ 7 * 8 * Additional copyrights may follow 9 * 10 * $HEADER$ 11 */ 12 13 #ifndef PMIX_UTIL_TIMING_H 14 #define PMIX_UTIL_TIMING_H 15 16 #include <src/include/pmix_config.h> 17 18 19 #include "src/class/pmix_list.h" 20 21 #if PMIX_ENABLE_TIMING 22 23 #define PMIX_TIMING_DESCR_MAX 1024 24 #define PMIX_TIMING_BUFSIZE 32 25 #define PMIX_TIMING_OUTBUF_SIZE (10*1024) 26 27 typedef enum { 28 PMIX_TIMING_TRACE, 29 PMIX_TIMING_INTDESCR, 30 PMIX_TIMING_INTBEGIN, 31 PMIX_TIMING_INTEND 32 } pmix_event_type_t; 33 34 typedef struct { 35 pmix_list_item_t super; 36 int fib; 37 pmix_event_type_t type; 38 const char *func; 39 const char *file; 40 int line; 41 double ts, ts_ovh; 42 char descr[PMIX_TIMING_DESCR_MAX]; 43 int id; 44 } pmix_timing_event_t; 45 46 typedef double (*get_ts_t)(void); 47 48 typedef struct pmix_timing_t 49 { 50 int next_id_cntr; 51 // not thread safe! 52 // The whole implementation is not thread safe now 53 // since it is supposed to be used in service 54 // thread only. Fix in the future or now? 55 int current_id; 56 pmix_list_t *events; 57 pmix_timing_event_t *buffer; 58 size_t buffer_offset, buffer_size; 59 get_ts_t get_ts; 60 } pmix_timing_t; 61 62 typedef struct { 63 pmix_timing_t *t; 64 pmix_timing_event_t *ev; 65 int errcode; 66 } pmix_timing_prep_t; 67 68 /* Pass down our namespace and rank for pretty-print purposes */ 69 PMIX_EXPORT void pmix_init_id(char* nspace, int rank); 70 71 /** 72 * Initialize timing structure. 73 * 74 * @param t pointer to the timing handler structure 75 */ 76 PMIX_EXPORT void pmix_timing_init(pmix_timing_t *t); 77 78 /** 79 * Prepare timing event, do all printf-like processing. 80 * Should not be directly used - for service purposes only. 81 * 82 * @param t pointer to the timing handler structure 83 * @param fmt printf-like format 84 * @param ... other parameters that should be converted to string representation 85 * 86 * @retval partly filled pmix_timing_prep_t structure 87 */ 88 PMIX_EXPORT pmix_timing_prep_t pmix_timing_prep_ev(pmix_timing_t *t, const char *fmt, ...); 89 90 /** 91 * Prepare timing event, ignore printf-like processing. 92 * Should not be directly used - for service purposes only. 93 * 94 * @param t pointer to the timing handler structure 95 * @param fmt printf-like format 96 * @param ... other parameters that should be converted to string representation 97 * 98 * @retval partly filled pmix_timing_prep_t structure 99 */ 100 PMIX_EXPORT pmix_timing_prep_t pmix_timing_prep_ev_end(pmix_timing_t *t, const char *fmt, ...); 101 102 /** 103 * Enqueue timing event into the list of events in handler 't'. 104 * 105 * @param p result of pmix_timing_prep_ev 106 * @param func function name where event occurs 107 * @param file file name where event occurs 108 * @param line line number in the file 109 * 110 * @retval 111 */ 112 PMIX_EXPORT void pmix_timing_add_step(pmix_timing_prep_t p, const char *func, 113 const char *file, int line); 114 115 /** 116 * Enqueue the description of the interval into a list of events 117 * in handler 't'. 118 * 119 * @param p result of pmix_timing_prep_ev 120 * @param func function name where event occurs 121 * @param file file name where event occurs 122 * @param line line number in the file 123 * 124 * @retval id of event interval 125 */ 126 PMIX_EXPORT int pmix_timing_descr(pmix_timing_prep_t p, const char *func, 127 const char *file, int line); 128 129 /** 130 * Enqueue the beginning of timing interval that already has the 131 * description and assigned id into the list of events 132 * in handler 't'. 133 * 134 * @param p result of pmix_timing_prep_ev 135 * @param func function name where event occurs 136 * @param file file name where event occurs 137 * @param line line number in the file 138 * 139 * @retval 140 */ 141 PMIX_EXPORT void pmix_timing_start_id(pmix_timing_t *t, int id, const char *func, 142 const char *file, int line); 143 144 /** 145 * Enqueue the end of timing interval that already has 146 * description and assigned id into the list of events 147 * in handler 't'. 148 * 149 * @param p result of pmix_timing_prep_ev 150 * @param func function name where event occurs 151 * @param file file name where event occurs 152 * @param line line number in the file 153 * 154 * @retval 155 */ 156 PMIX_EXPORT void pmix_timing_end(pmix_timing_t *t, int id, const char *func, 157 const char *file, int line ); 158 159 /** 160 * Enqueue both description and start of timing interval 161 * into the list of events and assign its id. 162 * 163 * @param p result of pmix_timing_prep_ev 164 * @param func function name where event occurs 165 * @param file file name where event occurs 166 * @param line line number in the file 167 * 168 * @retval interval id 169 */ 170 static inline int pmix_timing_start_init(pmix_timing_prep_t p, 171 const char *func, 172 const char *file, int line) 173 { 174 int id = pmix_timing_descr(p, func, file, line); 175 if( id < 0 ) 176 return id; 177 pmix_timing_start_id(p.t, id, func, file, line); 178 return id; 179 } 180 181 /** 182 * The wrapper that is used to stop last measurement in PMIX_TIMING_MNEXT. 183 * 184 * @param p result of pmix_timing_prep_ev 185 * @param func function name where event occurs 186 * @param file file name where event occurs 187 * @param line line number in the file 188 * 189 * @retval interval id 190 */ 191 PMIX_EXPORT void pmix_timing_end_prep(pmix_timing_prep_t p, 192 const char *func, const char *file, int line); 193 194 /** 195 * Report all events that were enqueued in the timing handler 't'. 196 * - if fname == NULL the output will be done using pmix_output and 197 * each line will be prefixed with "prefix" to ease grep'ing. 198 * - otherwise the corresponding file will be used for output in "append" mode 199 * WARRNING: not all filesystems provide enough support for that feature, some records may 200 * disappear. 201 * 202 * @param t timing handler 203 * @param account_overhead consider malloc overhead introduced by timing code 204 * @param prefix prefix to use when no fname was specifyed to ease grep'ing 205 * @param fname name of the output file (may be NULL) 206 * 207 * @retval PMIX_SUCCESS On success 208 * @retval PMIX_ERROR or PMIX_ERR_OUT_OF_RESOURCE On failure 209 */ 210 PMIX_EXPORT pmix_status_t pmix_timing_report(pmix_timing_t *t, char *fname); 211 212 /** 213 * Report all intervals that were enqueued in the timing handler 't'. 214 * - if fname == NULL the output will be done using pmix_output and 215 * each line will be prefixed with "prefix" to ease grep'ing. 216 * - otherwise the corresponding file will be used for output in "append" mode 217 * WARRNING: not all filesystems provide enough support for that feature, some records may 218 * disappear. 219 * 220 * @param t timing handler 221 * @param account_overhead consider malloc overhead introduced by timing code 222 * @param fname name of the output file (may be NULL) 223 * 224 * @retval PMIX_SUCCESS On success 225 * @retval PMIX_ERROR or PMIX_ERR_OUT_OF_RESOURCE On failure 226 */ 227 PMIX_EXPORT pmix_status_t pmix_timing_deltas(pmix_timing_t *t, char *fname); 228 229 /** 230 * Release all memory allocated for the timing handler 't'. 231 * 232 * @param t timing handler 233 * 234 * @retval 235 */ 236 PMIX_EXPORT void pmix_timing_release(pmix_timing_t *t); 237 238 /** 239 * Macro for passing down process id - compiled out 240 * when configured without --enable-timing 241 */ 242 #define PMIX_TIMING_ID(n, r) pmix_timing_id((n), (r)); 243 244 /** 245 * Main macro for use in declaring pmix timing handler; 246 * will be "compiled out" when PMIX is configured without 247 * --enable-timing. 248 * 249 */ 250 #define PMIX_TIMING_DECLARE(t) pmix_timing_t t; /* need semicolon here to avoid warnings when not enabled */ 251 252 /** 253 * Main macro for use in declaring external pmix timing handler; 254 * will be "compiled out" when PMIX is configured without 255 * --enable-timing. 256 * 257 */ 258 #define PMIX_TIMING_DECLARE_EXT(x, t) x extern pmix_timing_t t; /* need semicolon here to avoid warnings when not enabled */ 259 260 /** 261 * Main macro for use in initializing pmix timing handler; 262 * will be "compiled out" when PMIX is configured without 263 * --enable-timing. 264 * 265 * @see pmix_timing_init() 266 */ 267 #define PMIX_TIMING_INIT(t) pmix_timing_init(t) 268 269 /** 270 * Macro that enqueues event with its description to the specified 271 * timing handler; 272 * will be "compiled out" when PMIX is configured without 273 * --enable-timing. 274 * 275 * @see pmix_timing_add_step() 276 */ 277 #define PMIX_TIMING_EVENT(x) pmix_timing_add_step( pmix_timing_prep_ev x, __FUNCTION__, __FILE__, __LINE__) 278 279 /** 280 * MDESCR: Measurement DESCRiption 281 * Introduce new timing measurement with string description for the specified 282 * timing handler; 283 * will be "compiled out" when PMIX is configured without 284 * --enable-timing. 285 * 286 * @see pmix_timing_descr() 287 */ 288 #define PMIX_TIMING_MDESCR(x) pmix_timing_descr( pmix_timing_prep_ev x, __FUNCTION__, __FILE__, __LINE__) 289 290 /** 291 * MSTART_ID: Measurement START by ID. 292 * Marks the beginning of the measurement with ID=id on the 293 * specified timing handler; 294 * will be "compiled out" when PMIX is configured without 295 * --enable-timing. 296 * 297 * @see pmix_timing_start_id() 298 */ 299 #define PMIX_TIMING_MSTART_ID(t, id) pmix_timing_start_id(t, id, __FUNCTION__, __FILE__, __LINE__) 300 301 /** 302 * MSTART: Measurement START 303 * Introduce new timing measurement conjuncted with its start 304 * on the specifyed timing handler; 305 * will be "compiled out" when PMIX is configured without 306 * --enable-timing. 307 * 308 * @see pmix_timing_start_init() 309 */ 310 #define PMIX_TIMING_MSTART(x) pmix_timing_start_init( pmix_timing_prep_ev x, __FUNCTION__, __FILE__, __LINE__) 311 312 /** 313 * MSTOP: STOP Measurement 314 * Finishes the most recent measurement on the specifyed timing handler; 315 * will be "compiled out" when PMIX is configured without 316 * --enable-timing. 317 * 318 * @see pmix_timing_end() 319 */ 320 #define PMIX_TIMING_MSTOP(t) pmix_timing_end(t, -1, __FUNCTION__, __FILE__, __LINE__) 321 322 /** 323 * MSTOP_ID: STOP Measurement with ID=id. 324 * Finishes the measurement with give ID on the specifyed timing handler; 325 * will be "compiled out" when PMIX is configured without 326 * --enable-timing. 327 * 328 * @see pmix_timing_end() 329 */ 330 #define PMIX_TIMING_MSTOP_ID(t, id) pmix_timing_end(t, id, __FUNCTION__, __FILE__, __LINE__) 331 332 /** 333 * MNEXT: start NEXT Measurement 334 * Convinient macro, may be implemented with the sequence of three previously 335 * defined macroses: 336 * - finish current measurement (PMIX_TIMING_MSTOP); 337 * - introduce new timing measurement (PMIX_TIMING_MDESCR); 338 * - starts next measurement (PMIX_TIMING_MSTART_ID) 339 * on the specifyed timing handler; 340 * will be "compiled out" when PMIX is configured without 341 * --enable-timing. 342 * 343 * @see pmix_timing_start_init() 344 */ 345 #define PMIX_TIMING_MNEXT(x) ( \ 346 pmix_timing_end_prep(pmix_timing_prep_ev_end x, \ 347 __FUNCTION__, __FILE__, __LINE__ ), \ 348 pmix_timing_start_init( pmix_timing_prep_ev x, \ 349 __FUNCTION__, __FILE__, __LINE__) \ 350 ) 351 352 /** 353 * The macro for use in reporting collected events with absolute values; 354 * will be "compiled out" when PMIX is configured without 355 * --enable-timing. 356 * 357 * @param enable flag that enables/disables reporting. Used for fine-grained timing. 358 * @see pmix_timing_report() 359 */ 360 #define PMIX_TIMING_REPORT(enable, t) { \ 361 if( enable ) { \ 362 pmix_timing_report(t, pmix_timing_output); \ 363 } \ 364 } 365 366 /** 367 * The macro for use in reporting collected events with relative times; 368 * will be "compiled out" when PMIX is configured without 369 * --enable-timing. 370 * 371 * @param enable flag that enables/disables reporting. Used for fine-grained timing. 372 * @see pmix_timing_deltas() 373 */ 374 #define PMIX_TIMING_DELTAS(enable, t) { \ 375 if( enable ) { \ 376 pmix_timing_deltas(t, pmix_timing_output); \ 377 } \ 378 } 379 380 /** 381 * Main macro for use in releasing allocated resources; 382 * will be "compiled out" when PMIX is configured without 383 * --enable-timing. 384 * 385 * @see pmix_timing_release() 386 */ 387 #define PMIX_TIMING_RELEASE(t) pmix_timing_release(t) 388 389 #else 390 391 #define PMIX_TIMING_ID(n, r) 392 393 #define PMIX_TIMING_DECLARE(t) 394 395 #define PMIX_TIMING_DECLARE_EXT(x, t) 396 397 #define PMIX_TIMING_INIT(t) 398 399 #define PMIX_TIMING_EVENT(x) 400 401 #define PMIX_TIMING_MDESCR(x) 402 403 #define PMIX_TIMING_MSTART_ID(t, id) 404 405 #define PMIX_TIMING_MSTART(x) 406 407 #define PMIX_TIMING_MSTOP(t) 408 409 #define PMIX_TIMING_MSTOP_ID(t, id) 410 411 #define PMIX_TIMING_MNEXT(x) 412 413 #define PMIX_TIMING_REPORT(enable, t) 414 415 #define PMIX_TIMING_DELTAS(enable, t) 416 417 #define PMIX_TIMING_RELEASE(t) 418 419 #endif 420 421 #endif