1 /**
2 Lightweight profiler library for c++
3 Copyright(C) 2016-2017  Sergey Yagovtsev, Victor Zarubkin
4 
5 Licensed under either of
6     * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
7     * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
8 at your option.
9 
10 The MIT License
11     Permission is hereby granted, free of charge, to any person obtaining a copy
12     of this software and associated documentation files (the "Software"), to deal
13     in the Software without restriction, including without limitation the rights
14     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
15     of the Software, and to permit persons to whom the Software is furnished
16     to do so, subject to the following conditions:
17 
18     The above copyright notice and this permission notice shall be included in all
19     copies or substantial portions of the Software.
20 
21     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
22     INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23     PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24     LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
26     USE OR OTHER DEALINGS IN THE SOFTWARE.
27 
28 
29 The Apache License, Version 2.0 (the "License");
30     You may not use this file except in compliance with the License.
31     You may obtain a copy of the License at
32 
33     http://www.apache.org/licenses/LICENSE-2.0
34 
35     Unless required by applicable law or agreed to in writing, software
36     distributed under the License is distributed on an "AS IS" BASIS,
37     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
38     See the License for the specific language governing permissions and
39     limitations under the License.
40 
41 **/
42 
43 #ifndef EASY_PROFILER_H
44 #define EASY_PROFILER_H
45 
46 #include <easy/details/profiler_public_types.h>
47 
48 #if defined ( __clang__ )
49 # pragma clang diagnostic push
50 # pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
51 #endif
52 
53 //
54 // BUILD_WITH_EASY_PROFILER is defined in CMakeLists.txt if your project is linked to easy_profiler.
55 //
56 
57 //
58 // DISABLE_EASY_PROFILER may be defined manually in source-file before #include <easy/profiler.h>
59 //                       to disable profiler for certain source-file or project.
60 //
61 
62 #if defined(BUILD_WITH_EASY_PROFILER) && !defined(DISABLE_EASY_PROFILER)
63 
64 /**
65 \defgroup profiler EasyProfiler
66 */
67 
68 
69 /** Indicates that EasyProfiler is used.
70 
71 \ingroup profiler
72 */
73 #define USING_EASY_PROFILER
74 
75 
76 // EasyProfiler core API:
77 
78 /** Macro for beginning of a scoped block with custom name and color.
79 
80 \code
81     #include <easy/profiler.h>
82     void foo()
83     {
84         // some code ...
85 
86         EASY_BLOCK("Check something", profiler::OFF); // Disabled block (There is possibility to enable this block later via GUI)
87         if(something){
88             EASY_BLOCK("Calling bar()"); // Block with default color
89             bar();
90         }
91         else{
92             EASY_BLOCK("Calling baz()", profiler::colors::Red); // Red block
93             baz();
94         }
95         EASY_END_BLOCK; // End of "Check something" block (Even if "Check something" is disabled, this EASY_END_BLOCK will not end any other block).
96 
97         EASY_BLOCK("Some another block", profiler::colors::Blue, profiler::ON_WITHOUT_CHILDREN); // Block with Blue color without
98         // some another code...
99         EASY_BLOCK("Calculate sum"); // This block will not be profiled because it's parent is ON_WITHOUT_CHILDREN
100         int sum = 0;
101         for (int i = 0; i < 10; ++i)
102             sum += i;
103         EASY_END_BLOCK; // End of "Calculate sum" block
104     }
105 \endcode
106 
107 Block will be automatically completed by destructor.
108 
109 \ingroup profiler
110 */
111 # define EASY_BLOCK(name, ...)\
112     EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(::profiler::extract_enable_flag(__VA_ARGS__),\
113         EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name), __FILE__, __LINE__, ::profiler::BlockType::Block, ::profiler::extract_color(__VA_ARGS__),\
114         ::std::is_base_of<::profiler::ForceConstStr, decltype(name)>::value));\
115     ::profiler::Block EASY_UNIQUE_BLOCK(__LINE__)(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name));\
116     ::profiler::beginBlock(EASY_UNIQUE_BLOCK(__LINE__));
117 
118 /** Macro for beginning of a non-scoped block with custom name and color.
119 
120 You must end such block manually with EASY_END_BLOCK.
121 
122 \code
123     #include <easy/profiler.h>
124     void foo() {
125         EASY_NONSCOPED_BLOCK("Callback"); // Begin block which would not be finished when function returns.
126 
127         // some code ...
128     }
129 
130     void bar() {
131         // some another code...
132 
133         EASY_END_BLOCK; // This, as always, ends last opened block. You have to take care about blocks order by yourself.
134     }
135 
136     void baz() {
137         foo(); // non-scoped block begins here
138 
139         // some code...
140 
141         bar(); // non-scoped block ends here
142     }
143 \endcode
144 
145 Block will be automatically completed by destructor.
146 
147 \ingroup profiler
148 */
149 #define EASY_NONSCOPED_BLOCK(name, ...)\
150     EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(::profiler::extract_enable_flag(__VA_ARGS__),\
151         EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name), __FILE__, __LINE__, ::profiler::BlockType::Block, ::profiler::extract_color(__VA_ARGS__),\
152         ::std::is_base_of<::profiler::ForceConstStr, decltype(name)>::value));\
153     ::profiler::beginNonScopedBlock(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name));
154 
155 /** Macro for beginning of a block with function name and custom color.
156 
157 \code
158     #include <easy/profiler.h>
159     void foo(){
160         EASY_FUNCTION(); // Block with name="foo" and default color
161         //some code...
162     }
163 
164     void bar(){
165         EASY_FUNCTION(profiler::colors::Green); // Green block with name="bar"
166         //some code...
167     }
168 
169     void baz(){
170         EASY_FUNCTION(profiler::FORCE_ON); // Force enabled block with name="baz" and default color (This block will be profiled even if it's parent is OFF_RECURSIVE)
171         // som code...
172     }
173 \endcode
174 
175 Name of the block automatically created with function name.
176 
177 \ingroup profiler
178 */
179 # define EASY_FUNCTION(...) EASY_BLOCK(EASY_FUNC_NAME, ## __VA_ARGS__)
180 
181 /** Macro for completion of last opened block explicitly.
182 
183 \code
184 #include <easy/profiler.h>
185 int foo()
186 {
187     // some code ...
188 
189     int sum = 0;
190     EASY_BLOCK("Calculating sum");
191     for (int i = 0; i < 10; ++i){
192         sum += i;
193     }
194     EASY_END_BLOCK;
195 
196     // some antoher code here ...
197 
198     return sum;
199 }
200 \endcode
201 
202 \ingroup profiler
203 */
204 # define EASY_END_BLOCK ::profiler::endBlock();
205 
206 /** Macro for creating event marker with custom name and color.
207 
208 Event marker is a block with zero duration and special type.
209 
210 \warning Event marker ends immidiately and calling EASY_END_BLOCK after EASY_EVENT
211 will end previously opened EASY_BLOCK or EASY_FUNCTION.
212 
213 \ingroup profiler
214 */
215 # define EASY_EVENT(name, ...)\
216     EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(\
217         ::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
218             __FILE__, __LINE__, ::profiler::BlockType::Event, ::profiler::extract_color(__VA_ARGS__),\
219             ::std::is_base_of<::profiler::ForceConstStr, decltype(name)>::value));\
220     ::profiler::storeEvent(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name));
221 
222 /** Macro for enabling profiler.
223 
224 \ingroup profiler
225 */
226 # define EASY_PROFILER_ENABLE ::profiler::setEnabled(true);
227 
228 /** Macro for disabling profiler.
229 
230 \ingroup profiler
231 */
232 # define EASY_PROFILER_DISABLE ::profiler::setEnabled(false);
233 
234 /** Macro for current thread registration.
235 
236 \note If this thread has been already registered then nothing happens.
237 
238 \ingroup profiler
239 */
240 # define EASY_THREAD(name)\
241     EASY_THREAD_LOCAL static const char* EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__) = 0;\
242     if (!EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__))\
243         EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__) = ::profiler::registerThread(name);
244 
245 /** Macro for current thread registration and creating a thread guard object.
246 
247 \note If this thread has been already registered then nothing happens.
248 
249 \note Also creates thread guard which marks thread as "expired" on it's destructor
250 and creates "ThreadFinished" profiler event.
251 
252 \ingroup profiler
253 */
254 # define EASY_THREAD_SCOPE(name)\
255     EASY_THREAD_LOCAL static const char* EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__) = 0;\
256     ::profiler::ThreadGuard EASY_TOKEN_CONCATENATE(unique_profiler_thread_guard, __LINE__);\
257     if (!EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__))\
258         EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__) = ::profiler::registerThreadScoped(name,\
259         EASY_TOKEN_CONCATENATE(unique_profiler_thread_guard, __LINE__));
260 
261 /** Macro for main thread registration.
262 
263 This is just for user's comfort. There is no difference for EasyProfiler GUI between different threads.
264 
265 \ingroup profiler
266 */
267 # define EASY_MAIN_THREAD EASY_THREAD("Main")
268 
269 /** Enable or disable event tracing (context switch events).
270 
271 \note Default value is controlled by EASY_OPTION_EVENT_TRACING_ENABLED macro.
272 
273 \note Change will take effect on the next call to EASY_PROFILER_ENABLE.
274 
275 \sa EASY_PROFILER_ENABLE, EASY_OPTION_EVENT_TRACING_ENABLED
276 
277 \ingroup profiler
278 */
279 # define EASY_SET_EVENT_TRACING_ENABLED(isEnabled) ::profiler::setEventTracingEnabled(isEnabled);
280 
281 /** Set event tracing thread priority (low or normal).
282 
283 Event tracing with low priority will affect your application performance much more less, but
284 it can be late to gather information about thread/process (thread could be finished to the moment
285 when event tracing thread will be awaken) and you will not see process name and process id
286 information in GUI for such threads. You will still be able to see all context switch events.
287 
288 Event tracing with normal priority could gather more information about processes but potentially
289 it could affect performance as it has more work to do. Usually you will not notice any performance
290 breakdown, but if you care about that then you change set event tracing priority level to low.
291 
292 \sa EASY_OPTION_LOW_PRIORITY_EVENT_TRACING
293 
294 \ingroup profiler
295 */
296 # define EASY_SET_LOW_PRIORITY_EVENT_TRACING(isLowPriority) ::profiler::setLowPriorityEventTracing(isLowPriority);
297 
298 /** Macro for setting temporary log-file path for Unix event tracing system.
299 
300 \note Default value is "/tmp/cs_profiling_info.log".
301 
302 \ingroup profiler
303 */
304 # define EASY_EVENT_TRACING_SET_LOG(filename) ::profiler::setContextSwitchLogFilename(filename);
305 
306 /** Macro returning current path to the temporary log-file for Unix event tracing system.
307 
308 \ingroup profiler
309 */
310 # define EASY_EVENT_TRACING_LOG ::profiler::getContextSwitchLogFilename();
311 
312 // EasyProfiler settings:
313 
314 /** If != 0 then EasyProfiler will measure time for blocks storage expansion.
315 If 0 then EasyProfiler will be compiled without blocks of code responsible
316 for measuring these events.
317 
318 These are "EasyProfiler.ExpandStorage" blocks on a diagram.
319 
320 \ingroup profiler
321 */
322 # ifndef EASY_OPTION_MEASURE_STORAGE_EXPAND
323 #  define EASY_OPTION_MEASURE_STORAGE_EXPAND 0
324 # endif
325 
326 # if EASY_OPTION_MEASURE_STORAGE_EXPAND != 0
327 /** If true then "EasyProfiler.ExpandStorage" blocks are enabled by default and will be
328 writed to output file or translated over the net.
329 If false then you need to enable these blocks via GUI if you want to see them.
330 
331 \ingroup profiler
332 */
333 #  ifndef EASY_OPTION_STORAGE_EXPAND_BLOCKS_ON
334 #   define EASY_OPTION_STORAGE_EXPAND_BLOCKS_ON true
335 #  endif
336 
337 # endif // EASY_OPTION_MEASURE_STORAGE_EXPAND != 0
338 
339 /** If true then EasyProfiler event tracing is enabled by default
340 and will be turned on and off when you call profiler::setEnabled().
341 Otherwise, it have to be turned on via GUI and then it will be
342 turned on/off with next calls of profiler::setEnabled().
343 
344 \ingroup profiler
345 */
346 # ifndef EASY_OPTION_EVENT_TRACING_ENABLED
347 #  define EASY_OPTION_EVENT_TRACING_ENABLED true
348 # endif
349 
350 /** If true then EasyProfiler.ETW thread (Event tracing for Windows) will have low priority by default.
351 
352 \sa EASY_SET_LOW_PRIORITY_EVENT_TRACING
353 
354 \note You can always change priority level via GUI or API while profiling session is not launched.
355 You don't need to rebuild or restart your application for that.
356 
357 \ingroup profiler
358 */
359 # ifndef EASY_OPTION_LOW_PRIORITY_EVENT_TRACING
360 #  define EASY_OPTION_LOW_PRIORITY_EVENT_TRACING true
361 # endif
362 
363 
364 /** If != 0 then EasyProfiler will print error messages into stderr.
365 Otherwise, no log messages will be printed.
366 
367 \ingroup profiler
368 */
369 # ifndef EASY_OPTION_LOG_ENABLED
370 #  define EASY_OPTION_LOG_ENABLED 0
371 # endif
372 
373 /** If != 0 then EasyProfiler will start listening thread immidiately on ProfileManager initialization.
374 
375 \sa startListen
376 
377 \ingroup profiler
378 */
379 # ifndef EASY_OPTION_START_LISTEN_ON_STARTUP
380 #  define EASY_OPTION_START_LISTEN_ON_STARTUP 0
381 # endif
382 
383 #else // #ifdef BUILD_WITH_EASY_PROFILER
384 
385 # define EASY_BLOCK(...)
386 # define EASY_NONSCOPED_BLOCK(...)
387 # define EASY_FUNCTION(...)
388 # define EASY_END_BLOCK
389 # define EASY_PROFILER_ENABLE
390 # define EASY_PROFILER_DISABLE
391 # define EASY_EVENT(...)
392 # define EASY_THREAD(...)
393 # define EASY_THREAD_SCOPE(...)
394 # define EASY_MAIN_THREAD
395 # define EASY_SET_EVENT_TRACING_ENABLED(isEnabled)
396 # define EASY_SET_LOW_PRIORITY_EVENT_TRACING(isLowPriority)
397 
398 # ifndef _WIN32
399 #  define EASY_EVENT_TRACING_SET_LOG(filename)
400 #  define EASY_EVENT_TRACING_LOG ""
401 # endif
402 
403 # ifndef EASY_OPTION_MEASURE_STORAGE_EXPAND
404 #  define EASY_OPTION_MEASURE_STORAGE_EXPAND 0
405 # endif
406 
407 # ifndef EASY_OPTION_EVENT_TRACING_ENABLED
408 #  define EASY_OPTION_EVENT_TRACING_ENABLED false
409 # endif
410 
411 # ifndef EASY_OPTION_LOW_PRIORITY_EVENT_TRACING
412 #  define EASY_OPTION_LOW_PRIORITY_EVENT_TRACING true
413 # endif
414 
415 # ifndef EASY_OPTION_LOG_ENABLED
416 #  define EASY_OPTION_LOG_ENABLED 0
417 # endif
418 
419 # ifndef EASY_OPTION_START_LISTEN_ON_STARTUP
420 #  define EASY_OPTION_START_LISTEN_ON_STARTUP 0
421 # endif
422 
423 #endif // #ifndef BUILD_WITH_EASY_PROFILER
424 
425 # ifndef EASY_DEFAULT_PORT
426 #  define EASY_DEFAULT_PORT 28077
427 # endif
428 
429 /** Alias for EASY_PROFILER_ENABLE.
430 
431 Added for clarification.
432 
433 \sa EASY_PROFILER_ENABLE
434 
435 \ingroup profiler
436 */
437 #define EASY_START_CAPTURE EASY_PROFILER_ENABLE
438 
439 /** Alias for EASY_PROFILER_DISABLE.
440 
441 Added for clarification.
442 
443 \sa EASY_PROFILER_DISABLE
444 
445 \ingroup profiler
446 */
447 #define EASY_STOP_CAPTURE EASY_PROFILER_DISABLE
448 
449 //////////////////////////////////////////////////////////////////////////
450 //////////////////////////////////////////////////////////////////////////
451 
452 namespace profiler {
453 
454     EASY_CONSTEXPR uint16_t DEFAULT_PORT = EASY_DEFAULT_PORT;
455 
456     //////////////////////////////////////////////////////////////////////
457     // Core API
458     // Note: It is better to use macros defined above than a direct calls to API.
459     //       But some API functions does not have macro wrappers...
460 
461 #ifdef USING_EASY_PROFILER
462     extern "C" {
463 
464         /** Returns current time in ticks.
465 
466         You can use it if you want to store block explicitly.
467 
468         \retval Current CPU time in ticks.
469 
470         \ingroup profiler
471         */
472         PROFILER_API timestamp_t currentTime();
473 
474         /** Convert ticks to nanoseconds.
475 
476         \retval _ticks converted to nanoseconds.
477 
478         \ingroup profiler
479         */
480         PROFILER_API timestamp_t toNanoseconds(timestamp_t _ticks);
481 
482         /** Convert ticks to microseconds.
483 
484         \retval _ticks converted to microseconds.
485 
486         \ingroup profiler
487         */
488         PROFILER_API timestamp_t toMicroseconds(timestamp_t _ticks);
489 
490         /** Registers static description of a block.
491 
492         It is general information which is common for all such blocks.
493         Includes color, block type (see BlockType), file-name, line-number, compile-time name of a block and enable-flag.
494 
495         \note This API function is used by EASY_EVENT, EASY_BLOCK, EASY_FUNCTION macros.
496         There is no need to invoke this function explicitly.
497 
498         \retval Pointer to registered block description.
499 
500         \ingroup profiler
501         */
502         PROFILER_API const BaseBlockDescriptor* registerDescription(EasyBlockStatus _status, const char* _autogenUniqueId, const char* _compiletimeName, const char* _filename, int _line, block_type_t _block_type, color_t _color, bool _copyName = false);
503 
504         /** Stores event in the blocks list.
505 
506         An event ends instantly and has zero duration.
507 
508         \note There is no need to invoke this function explicitly - use EASY_EVENT macro instead.
509 
510         \param _desc Reference to the previously registered description.
511         \param _runtimeName Standard zero-terminated string which will be copied to the events buffer.
512 
513         \note _runtimeName must be an empty string ("") if you do not want to set name to the event at run-time.
514 
515         \ingroup profiler
516         */
517         PROFILER_API void storeEvent(const BaseBlockDescriptor* _desc, const char* _runtimeName = "");
518 
519         /** Stores block explicitly in the blocks list.
520 
521         Use this function for additional flexibility if you want to set block duration manually.
522 
523         \param _desc Reference to the previously registered description.
524         \param _runtimeName Standard zero-terminated string which will be copied to the events buffer.
525         \param _beginTime begin time of the block
526         \param _endTime end time of the block
527 
528         \note _runtimeName must be an empty string ("") if you do not want to set name to the block at run-time.
529 
530         \ingroup profiler
531         */
532         PROFILER_API void storeBlock(const BaseBlockDescriptor* _desc, const char* _runtimeName, timestamp_t _beginTime, timestamp_t _endTime);
533 
534         /** Begins scoped block.
535 
536         \ingroup profiler
537         */
538         PROFILER_API void beginBlock(Block& _block);
539 
540         /** Begins non-scoped block.
541 
542         \param _desc Reference to the previously registered description (see registerDescription).
543         \param _runtimeName Standard zero-terminated string which will be copied to the block buffer when block will end.
544 
545         \note There is no need to invoke this function explicitly - use EASY_NONSCOPED_BLOCK macro instead.
546         EASY_NONSCOPED_BLOCK macro could be used for higher flexibility if you have to begin block in one
547         function and end it in another one.
548 
549         \note _runtimeName must be an empty string ("") if you do not want to set name to the block at run-time.
550         \note _runtimeName is copied only when block ends so you must ensure it's validity until block end.
551 
552         \warning You have to end this block explicitly.
553 
554         \ingroup profiler
555         */
556         PROFILER_API void beginNonScopedBlock(const BaseBlockDescriptor* _desc, const char* _runtimeName = "");
557 
558         /** Ends last started block.
559 
560         Use this only if you want to finish block explicitly.
561 
562         \ingroup profiler
563         */
564         PROFILER_API void endBlock();
565 
566         /** Enable or disable profiler.
567 
568         AKA start or stop profiling (capturing blocks).
569 
570         \ingroup profiler
571         */
572         PROFILER_API void setEnabled(bool _isEnable);
573         PROFILER_API bool isEnabled();
574 
575         /** Save all gathered blocks into file.
576 
577         \note This also disables profiler.
578 
579         \retval Number of saved blocks. If 0 then nothing was profiled or an error occured.
580 
581         \ingroup profiler
582         */
583         PROFILER_API uint32_t dumpBlocksToFile(const char* _filename);
584 
585         /** Register current thread and give it a name.
586 
587         Also creates a scoped ThreadGuard which would unregister thread on it's destructor.
588         This helps for memory management while using an old compiler whitout thread_local support.
589 
590         \note Only first call of registerThread() for the current thread will have an effect.
591 
592         \note Use this function if you want to build your source code with an old compiler (MSVC < 2013, GCC < 4.8, Clang < 3.3).
593         Otherwise there is no need in this function because a thread_local ThreadGuard created inside.
594 
595         \retval Registered name of the thread. It may differ from _name if the thread was registered before.
596 
597         \sa registerThread, ThreadGuard
598 
599         \ingroup profiler
600         */
601         PROFILER_API const char* registerThreadScoped(const char* _name, ThreadGuard&);
602 
603         /** Register current thread and give it a name.
604 
605         \note Only first call of registerThread() for the current thread will have an effect.
606 
607         \retval Registered name of the thread. It may differ from _name if the thread was registered before.
608 
609         \ingroup profiler
610         */
611         PROFILER_API const char* registerThread(const char* _name);
612 
613         /** Enable or disable event tracing.
614 
615         \note This change will take an effect on the next call of setEnabled(true);
616 
617         \sa setEnabled, EASY_SET_EVENT_TRACING_ENABLED
618 
619         \ingroup profiler
620         */
621         PROFILER_API void setEventTracingEnabled(bool _isEnable);
622         PROFILER_API bool isEventTracingEnabled();
623 
624         /** Set event tracing thread priority (low or normal).
625 
626         \note This change will take effect on the next call of setEnabled(true);
627 
628         \sa setEnabled, EASY_SET_LOW_PRIORITY_EVENT_TRACING
629 
630         \ingroup profiler
631         */
632         PROFILER_API void setLowPriorityEventTracing(bool _isLowPriority);
633         PROFILER_API bool isLowPriorityEventTracing();
634 
635         /** Set temporary log-file path for Unix event tracing system.
636 
637         \note Default value is "/tmp/cs_profiling_info.log".
638 
639         \ingroup profiler
640         */
641         PROFILER_API void setContextSwitchLogFilename(const char* _name);
642 
643         /** Returns current path to the temporary log-file for Unix event tracing system.
644 
645         \ingroup profiler
646         */
647         PROFILER_API const char* getContextSwitchLogFilename();
648 
649         /** Start listening for network commands.
650 
651         Launches a separate listening thread which would listen to the network commands (start, stop, etc.).
652         The listening thread sends all profiled blocks via network after receiving network command 'stop'.
653 
654         \ingroup profiler
655         */
656         PROFILER_API void startListen(uint16_t _port = ::profiler::DEFAULT_PORT);
657 
658         /** Stops listening thread.
659 
660         \note This would be invoked automatically on application exit.
661 
662         \note Does not send any messages to the network, just stops thread.
663 
664         \ingroup profiler
665         */
666         PROFILER_API void stopListen();
667 
668         /** Check if listening thread launched.
669 
670         \ingroup profiler
671         */
672         PROFILER_API bool isListening();
673 
674         /** Returns current major version.
675 
676         \ingroup profiler
677         */
678         PROFILER_API uint8_t versionMajor();
679 
680         /** Returns current minor version.
681 
682         \ingroup profiler
683         */
684         PROFILER_API uint8_t versionMinor();
685 
686         /** Returns current version patch.
687 
688         \ingroup profiler
689         */
690         PROFILER_API uint16_t versionPatch();
691 
692         /** Returns current version in 32-bit integer format.
693 
694         \note Format is: 0x MAJ-MAJ MIN-MIN PATCH-PATCH-PATCH-PATCH
695         For example v1.3.0 is: 0x01030000
696 
697         \ingroup profiler
698         */
699         PROFILER_API uint32_t version();
700 
701         /** Returns current version string.
702 
703         Example: "v1.3.0"
704 
705         \ingroup profiler
706         */
707         PROFILER_API const char* versionName();
708 
709         /** Returns true if current thread has been marked as Main.
710         Otherwise, returns false.
711 
712         \ingroup profiler
713         */
714         PROFILER_API bool isMainThread();
715 
716         /** Returns last frame duration for current thread.
717 
718         \param _durationCast desired duration units (could be cpu-ticks or microseconds)
719 
720         \ingroup profiler
721         */
722         PROFILER_API timestamp_t this_thread_frameTime(Duration _durationCast = ::profiler::MICROSECONDS);
723 
724         /** Returns local max of frame duration for current thread.
725 
726         Local max is maximum frame duration since last frameTimeLocalMax() call.
727 
728         \param _durationCast desired duration units (could be cpu-ticks or microseconds)
729 
730         \ingroup profiler
731         */
732         PROFILER_API timestamp_t this_thread_frameTimeLocalMax(Duration _durationCast = ::profiler::MICROSECONDS);
733 
734         /** Returns local average of frame duration for current thread.
735 
736         Local average is average frame duration since last frameTimeLocalAvg() call.
737 
738         \param _durationCast desired duration units (could be cpu-ticks or microseconds)
739 
740         \ingroup profiler
741         */
742         PROFILER_API timestamp_t this_thread_frameTimeLocalAvg(Duration _durationCast = ::profiler::MICROSECONDS);
743 
744         /** Returns last frame duration for main thread.
745 
746         \param _durationCast desired duration units (could be cpu-ticks or microseconds)
747 
748         \ingroup profiler
749         */
750         PROFILER_API timestamp_t main_thread_frameTime(Duration _durationCast = ::profiler::MICROSECONDS);
751 
752         /** Returns local max of frame duration for main thread.
753 
754         Local max is maximum frame duration since last frameTimeLocalMax() call.
755 
756         \param _durationCast desired duration units (could be cpu-ticks or microseconds)
757 
758         \ingroup profiler
759         */
760         PROFILER_API timestamp_t main_thread_frameTimeLocalMax(Duration _durationCast = ::profiler::MICROSECONDS);
761 
762         /** Returns local average of frame duration for main thread.
763 
764         Local average is average frame duration since last frameTimeLocalAvg() call.
765 
766         \param _durationCast desired duration units (could be cpu-ticks or microseconds)
767 
768         \ingroup profiler
769         */
770         PROFILER_API timestamp_t main_thread_frameTimeLocalAvg(Duration _durationCast = ::profiler::MICROSECONDS);
771 
772     }
773 #else
currentTime()774     inline timestamp_t currentTime() { return 0; }
toNanoseconds(timestamp_t)775     inline timestamp_t toNanoseconds(timestamp_t) { return 0; }
toMicroseconds(timestamp_t)776     inline timestamp_t toMicroseconds(timestamp_t) { return 0; }
777     inline const BaseBlockDescriptor* registerDescription(EasyBlockStatus, const char*, const char*, const char*, int, block_type_t, color_t, bool = false)
778     { return reinterpret_cast<const BaseBlockDescriptor*>(0xbad); }
endBlock()779     inline void endBlock() { }
setEnabled(bool)780     inline void setEnabled(bool) { }
isEnabled()781     inline bool isEnabled() { return false; }
782     inline void storeEvent(const BaseBlockDescriptor*, const char* = "") { }
storeBlock(const BaseBlockDescriptor *,const char *,timestamp_t,timestamp_t)783     inline void storeBlock(const BaseBlockDescriptor*, const char*, timestamp_t, timestamp_t) { }
beginBlock(Block &)784     inline void beginBlock(Block&) { }
785     inline void beginNonScopedBlock(const BaseBlockDescriptor*, const char* = "") { }
dumpBlocksToFile(const char *)786     inline uint32_t dumpBlocksToFile(const char*) { return 0; }
registerThreadScoped(const char *,ThreadGuard &)787     inline const char* registerThreadScoped(const char*, ThreadGuard&) { return ""; }
registerThread(const char *)788     inline const char* registerThread(const char*) { return ""; }
setEventTracingEnabled(bool)789     inline void setEventTracingEnabled(bool) { }
isEventTracingEnabled()790     inline bool isEventTracingEnabled() { return false; }
setLowPriorityEventTracing(bool)791     inline void setLowPriorityEventTracing(bool) { }
isLowPriorityEventTracing()792     inline bool isLowPriorityEventTracing() { return false; }
setContextSwitchLogFilename(const char *)793     inline void setContextSwitchLogFilename(const char*) { }
getContextSwitchLogFilename()794     inline const char* getContextSwitchLogFilename() { return ""; }
795     inline void startListen(uint16_t = ::profiler::DEFAULT_PORT) { }
stopListen()796     inline void stopListen() { }
isListening()797     inline bool isListening() { return false; }
versionMajor()798     inline uint8_t versionMajor() { return 0; }
versionMinor()799     inline uint8_t versionMinor() { return 0; }
versionPatch()800     inline uint16_t versionPatch() { return 0; }
version()801     inline uint32_t version() { return 0; }
versionName()802     inline const char* versionName() { return "v0.0.0_disabled"; }
isMainThread()803     inline bool isMainThread() { return false; }
804     inline timestamp_t this_thread_frameTime(Duration = ::profiler::MICROSECONDS) { return 0; }
805     inline timestamp_t this_thread_frameTimeLocalMax(Duration = ::profiler::MICROSECONDS) { return 0; }
806     inline timestamp_t this_thread_frameTimeLocalAvg(Duration = ::profiler::MICROSECONDS) { return 0; }
807     inline timestamp_t main_thread_frameTime(Duration = ::profiler::MICROSECONDS) { return 0; }
808     inline timestamp_t main_thread_frameTimeLocalMax(Duration = ::profiler::MICROSECONDS) { return 0; }
809     inline timestamp_t main_thread_frameTimeLocalAvg(Duration = ::profiler::MICROSECONDS) { return 0; }
810 #endif
811 
812     /** API functions binded to current thread.
813 
814     \ingroup profiler
815     */
816     namespace this_thread {
817 
registrate(const char * _name)818         inline const char* registrate(const char* _name) {
819             return ::profiler::registerThread(_name);
820         }
821 
registrate(const char * _name,ThreadGuard & _threadGuard)822         inline const char* registrate(const char* _name, ThreadGuard& _threadGuard) {
823             return ::profiler::registerThreadScoped(_name, _threadGuard);
824         }
825 
826         inline timestamp_t frameTime(Duration _durationCast = ::profiler::MICROSECONDS) {
827             return ::profiler::this_thread_frameTime(_durationCast);
828         }
829 
830         inline timestamp_t frameTimeLocalMax(Duration _durationCast = ::profiler::MICROSECONDS) {
831             return ::profiler::this_thread_frameTimeLocalMax(_durationCast);
832         }
833 
834         inline timestamp_t frameTimeLocalAvg(Duration _durationCast = ::profiler::MICROSECONDS) {
835             return ::profiler::this_thread_frameTimeLocalAvg(_durationCast);
836         }
837 
isMain()838         inline bool isMain() {
839             return ::profiler::isMainThread();
840         }
841 
842     } // END of namespace this_thread.
843 
844     /** API functions binded to main thread.
845 
846     Could be called from any thread.
847 
848     \ingroup profiler
849     */
850     namespace main_thread {
851 
852         inline timestamp_t frameTime(Duration _durationCast = ::profiler::MICROSECONDS) {
853             return ::profiler::main_thread_frameTime(_durationCast);
854         }
855 
856         inline timestamp_t frameTimeLocalMax(Duration _durationCast = ::profiler::MICROSECONDS) {
857             return ::profiler::main_thread_frameTimeLocalMax(_durationCast);
858         }
859 
860         inline timestamp_t frameTimeLocalAvg(Duration _durationCast = ::profiler::MICROSECONDS) {
861             return ::profiler::main_thread_frameTimeLocalAvg(_durationCast);
862         }
863 
864         /** Always returns true.
865         */
isMain()866         inline EASY_CONSTEXPR_FCN bool isMain() {
867             return true;
868         }
869 
870     } // END of namespace main_thread.
871 
872     /** Alias for isEnabled().
873 
874     Added for clarification.
875 
876     \sa isEnabled
877 
878     \ingroup profiler
879     */
isCapturing()880     EASY_FORCE_INLINE bool isCapturing() { return isEnabled(); }
881 
882     /** Alias for EASY_PROFILER_ENABLE.
883 
884     Added for clarification.
885 
886     \sa EASY_PROFILER_ENABLE
887 
888     \ingroup profiler
889     */
startCapture()890     EASY_FORCE_INLINE void startCapture() { EASY_PROFILER_ENABLE; }
891 
892     /** Alias for EASY_PROFILER_DISABLE.
893 
894     Added for clarification.
895 
896     \sa EASY_PROFILER_DISABLE
897 
898     \ingroup profiler
899     */
stopCapture()900     EASY_FORCE_INLINE void stopCapture() { EASY_PROFILER_DISABLE; }
901 
902     //////////////////////////////////////////////////////////////////////
903 
904 } // END of namespace profiler.
905 
906 #if defined ( __clang__ )
907 # pragma clang diagnostic pop
908 #endif
909 
910 #endif // EASY_PROFILER_H
911