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