SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
Profiler.h
Go to the documentation of this file.
1 /**
2  * \file Profiler.h
3  * \authors Marino von Wattenwyl
4  * \date December 2021
5  * \copyright http://opensource.org/licenses/GPL-3.0
6  * \remarks Please use clangformat to format the code. See more code style on
7  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
8 */
9 
10 #ifndef PROFILER_H
11 #define PROFILER_H
12 
13 #include <chrono>
14 #include <string>
15 #include <vector>
16 #include <map>
17 #include <mutex>
18 #include <fstream>
19 
20 //-----------------------------------------------------------------------------
21 /* Set PROFILING to 1 to enable profiling or to 0 for disabling profiling
22  * Just add PROFILE_FUNCTION(); at the beginning of a function that you want to
23  * profile. See the Profiler class below on how to display the profiling data.
24  */
25 #define PROFILING 0
26 //-----------------------------------------------------------------------------
27 #if PROFILING
28 # define BEGIN_PROFILING_SESSION(filePath) Profiler::instance().beginSession(filePath)
29 # define PROFILE_SCOPE(name) ProfilerTimer profilerTimer##__LINE__(name)
30 # define PROFILE_FUNCTION() PROFILE_SCOPE(__FUNCTION__)
31 # define PROFILE_THREAD(name) Profiler::instance().profileThread(name)
32 # define PROFILER_TRACE_FILE_PATH Profiler::instance().filePath()
33 # define END_PROFILING_SESSION() Profiler::instance().endSession()
34 #else
35 # define BEGIN_PROFILING_SESSION(filePath)
36 # define PROFILE_SCOPE(name)
37 # define PROFILE_FUNCTION()
38 # define PROFILE_THREAD(name)
39 # define PROFILER_TRACE_FILE_PATH
40 # define END_PROFILING_SESSION()
41 #endif
42 //-----------------------------------------------------------------------------
44 {
45  const char* name; //!< Name of the profiled function/scope
46  uint32_t depth; //!< Depth of the scope in it's thread's call stack
47  uint64_t start; //!< Start time in microseconds relative to the session start
48  uint64_t end; //!< End time in microseconds relative to the session start
49  uint32_t threadId; //!< ID of the thread in which the scope was entered
50 };
51 //-----------------------------------------------------------------------------
52 //! Utility for profiling functions/scopes and writing the results to a file.
53 /*!
54  * To start the profiling, call BEGIN_PROFILING_SESSION(filePath) with the path
55  * to the trace file. After that you can place "PROFILE_FUNCTION();" or
56  * "PROFILE_SCOPE(name);" at the start of every function or scope you want to
57  * measure.
58  * The profiler supports multithreading. To add a new thread, call
59  * "PROFILE_THREAD(name)" at the start of the thread. Threads with the same
60  * name will appear merged in the trace file. To end the session and write
61  * the result to the trace file, call END_PROFILING_SESSION().
62  *
63  * The resulting trace gets written into the data folder of SLProject and can
64  * be opened using the trace viewer located at /externals/trace-viewer/trace-viewer.jar.
65  * Note that a Java Runtime Environment is required to launch this JAR archive.
66  */
67 class Profiler
68 {
69 public:
70  static Profiler& instance()
71  {
72  static Profiler instance;
73  return instance;
74  }
75 
76  void beginSession(std::string filePath);
77  std::string filePath() { return _filePath; }
78  void endSession();
79 
80  void recordResult(ProfilingResult result);
81  void profileThread(const std::string& name);
82 
83 private:
84  static void writeString(const char* s, std::ofstream& stream);
85 
86 private:
87  std::string _filePath; //!< Future path of the trace file
88  uint64_t _sessionStart = 0; //!< Start timestamp of the session in microseconds
89  std::vector<ProfilingResult> _results; //!< List of profiling results (of all threads)
90  std::vector<std::string> _threadNames; //!< List of thread names (the thread ID is the index)
91  std::mutex _mutex; //!< Mutex for accessing profiling results and thread names
92 };
93 //-----------------------------------------------------------------------------
94 //! A timer for profiling functions and scopes
95 /*!
96  * This class should be instantiated at the start of functions and scopes that
97  * should be profiled. The object will record the current time at it's construction
98  * and the current time at it's destruction (when the scope ends) and the depth
99  * in the call stack. The destructor automatically calls Profiler::instance().recordResult().
100  */
102 {
103  friend class Profiler;
104 
105 public:
106  explicit ProfilerTimer(const char* name);
107  ~ProfilerTimer();
108 
109 private:
110  static constexpr uint32_t INVALID_THREAD_ID = -1;
111  static thread_local uint32_t threadId;
112  static thread_local uint32_t threadDepth;
113 
114  const char* _name;
115  uint32_t _depth;
116  std::chrono::time_point<std::chrono::high_resolution_clock> _startPoint;
117  bool _running;
118 };
119 //-----------------------------------------------------------------------------
120 #endif // PROFILER_H
Utility for profiling functions/scopes and writing the results to a file.
Definition: Profiler.h:68
void endSession()
Definition: Profiler.cpp:57
static Profiler & instance()
Definition: Profiler.h:70
std::string _filePath
Future path of the trace file.
Definition: Profiler.h:87
std::vector< std::string > _threadNames
List of thread names (the thread ID is the index)
Definition: Profiler.h:90
std::vector< ProfilingResult > _results
List of profiling results (of all threads)
Definition: Profiler.h:89
void profileThread(const std::string &name)
Definition: Profiler.cpp:148
uint64_t _sessionStart
Start timestamp of the session in microseconds.
Definition: Profiler.h:88
std::string filePath()
Definition: Profiler.h:77
static void writeString(const char *s, std::ofstream &stream)
Writes the length (32-bit) and the string (non-null-terminated) itself to the file stream.
Definition: Profiler.cpp:170
void recordResult(ProfilingResult result)
Definition: Profiler.cpp:135
std::mutex _mutex
Mutex for accessing profiling results and thread names.
Definition: Profiler.h:91
void beginSession(std::string filePath)
Definition: Profiler.cpp:25
A timer for profiling functions and scopes.
Definition: Profiler.h:102
const char * _name
Definition: Profiler.h:114
std::chrono::time_point< std::chrono::high_resolution_clock > _startPoint
Definition: Profiler.h:116
ProfilerTimer(const char *name)
Definition: Profiler.cpp:187
static thread_local uint32_t threadId
Definition: Profiler.h:111
static thread_local uint32_t threadDepth
Definition: Profiler.h:112
uint32_t _depth
Definition: Profiler.h:115
static constexpr uint32_t INVALID_THREAD_ID
Definition: Profiler.h:110
bool _running
Definition: Profiler.h:117
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
uint64_t end
End time in microseconds relative to the session start.
Definition: Profiler.h:48
uint64_t start
Start time in microseconds relative to the session start.
Definition: Profiler.h:47
uint32_t depth
Depth of the scope in it's thread's call stack.
Definition: Profiler.h:46
const char * name
Name of the profiled function/scope.
Definition: Profiler.h:45
uint32_t threadId
ID of the thread in which the scope was entered.
Definition: Profiler.h:49