Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
Profiler.h
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
8#include <mutex>
9#include <chrono>
11
15
16#if defined(JPH_EXTERNAL_PROFILE)
17
19
20#ifdef JPH_SHARED_LIBRARY
22using ProfileStartMeasurementFunction = void (*)(const char *inName, uint32 inColor, uint8 *ioUserData);
23using ProfileEndMeasurementFunction = void (*)(uint8 *ioUserData);
24
25JPH_EXPORT extern ProfileStartMeasurementFunction ProfileStartMeasurement;
26JPH_EXPORT extern ProfileEndMeasurementFunction ProfileEndMeasurement;
27#endif // JPH_SHARED_LIBRARY
28
34class alignas(16) ExternalProfileMeasurement : public NonCopyable
35{
36public:
38#ifdef JPH_SHARED_LIBRARY
39 JPH_INLINE ExternalProfileMeasurement(const char *inName, uint32 inColor = 0) { ProfileStartMeasurement(inName, inColor, mUserData); }
40 JPH_INLINE ~ExternalProfileMeasurement() { ProfileEndMeasurement(mUserData); }
41#else
42 ExternalProfileMeasurement(const char *inName, uint32 inColor = 0);
43 ~ExternalProfileMeasurement();
44#endif
45
46private:
47 uint8 mUserData[64];
48};
49
51
53// Macros to do the actual profiling
55
56JPH_SUPPRESS_WARNING_PUSH
57JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
58
59// Dummy implementations
60#define JPH_PROFILE_START(name)
61#define JPH_PROFILE_END()
62#define JPH_PROFILE_THREAD_START(name)
63#define JPH_PROFILE_THREAD_END()
64#define JPH_PROFILE_NEXTFRAME()
65#define JPH_PROFILE_DUMP(...)
66
67// Scope profiling measurement
68#define JPH_PROFILE_TAG2(line) profile##line
69#define JPH_PROFILE_TAG(line) JPH_PROFILE_TAG2(line)
70
80#define JPH_PROFILE(...) ExternalProfileMeasurement JPH_PROFILE_TAG(__LINE__)(__VA_ARGS__)
81
82// Scope profiling for function
83#define JPH_PROFILE_FUNCTION() JPH_PROFILE(JPH_FUNCTION_NAME)
84
85JPH_SUPPRESS_WARNING_POP
86
87#elif defined(JPH_PROFILE_ENABLED)
88
90
91class ProfileSample;
92class ProfileThread;
93
96{
97public:
99
101 Profiler() { UpdateReferenceTime(); }
102
104 void NextFrame();
105
108 void Dump(const string_view &inTag = string_view());
109
111 void AddThread(ProfileThread *inThread);
112
114 void RemoveThread(ProfileThread *inThread);
115
118
119private:
121 struct ThreadSamples
122 {
123 String mThreadName;
124 ProfileSample * mSamplesBegin;
125 ProfileSample * mSamplesEnd;
126 };
127
129 class Aggregator
130 {
131 public:
133 Aggregator(const char *inName) : mName(inName) { }
134
136 void AccumulateMeasurement(uint64 inCyclesInCallWithChildren)
137 {
138 mCallCounter++;
139 mTotalCyclesInCallWithChildren += inCyclesInCallWithChildren;
140 mMinCyclesInCallWithChildren = min(inCyclesInCallWithChildren, mMinCyclesInCallWithChildren);
141 mMaxCyclesInCallWithChildren = max(inCyclesInCallWithChildren, mMaxCyclesInCallWithChildren);
142 }
143
145 bool operator < (const Aggregator &inRHS) const
146 {
147 return mTotalCyclesInCallWithChildren > inRHS.mTotalCyclesInCallWithChildren;
148 }
149
151 const char * mName;
152
154 uint32 mCallCounter = 0;
155 uint64 mTotalCyclesInCallWithChildren = 0;
156 uint64 mMinCyclesInCallWithChildren = 0xffffffffffffffffUL;
157 uint64 mMaxCyclesInCallWithChildren = 0;
158 };
159
160 using Threads = Array<ThreadSamples>;
161 using Aggregators = Array<Aggregator>;
162 using KeyToAggregator = UnorderedMap<const char *, size_t>;
163
165 static void sAggregate(int inDepth, uint32 inColor, ProfileSample *&ioSample, const ProfileSample *inEnd, Aggregators &ioAggregators, KeyToAggregator &ioKeyToAggregator);
166
168 void UpdateReferenceTime();
169
171 uint64 GetProcessorTicksPerSecond() const;
172
174 void DumpInternal();
175 void DumpChart(const char *inTag, const Threads &inThreads, const KeyToAggregator &inKeyToAggregators, const Aggregators &inAggregators);
176
177 std::mutex mLock;
178 uint64 mReferenceTick;
179 std::chrono::high_resolution_clock::time_point mReferenceTime;
180 Array<ProfileThread *> mThreads;
181 bool mDump = false;
182 String mDumpTag;
183};
184
185// Class that contains the information of a single scoped measurement
187{
188public:
190
191 const char * mName;
194 uint8 mUnused[3];
197};
198
201{
202public:
204
206 inline ProfileThread(const string_view &inThreadName);
207 inline ~ProfileThread();
208
209 static const uint cMaxSamples = 65536;
210
214
215#ifdef JPH_SHARED_LIBRARY
216 JPH_EXPORT static void sSetInstance(ProfileThread *inInstance);
218#else
219 static inline void sSetInstance(ProfileThread *inInstance) { sInstance = inInstance; }
220 static inline ProfileThread *sGetInstance() { return sInstance; }
221
222private:
223 static thread_local ProfileThread *sInstance;
224#endif
225};
226
229{
230public:
232 inline ProfileMeasurement(const char *inName, uint32 inColor = 0);
233 inline ~ProfileMeasurement();
234
235private:
236 ProfileSample * mSample;
237 ProfileSample mTemp;
238
239 static bool sOutOfSamplesReported;
240};
241
243
244#include "Profiler.inl"
245
247// Macros to do the actual profiling
249
250JPH_SUPPRESS_WARNING_PUSH
251JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
252
253
254#define JPH_PROFILE_START(name) do { Profiler::sInstance = new Profiler; JPH_PROFILE_THREAD_START(name); } while (false)
255
257#define JPH_PROFILE_END() do { JPH_PROFILE_THREAD_END(); delete Profiler::sInstance; Profiler::sInstance = nullptr; } while (false)
258
260#define JPH_PROFILE_THREAD_START(name) do { if (Profiler::sInstance) ProfileThread::sSetInstance(new ProfileThread(name)); } while (false)
261
263#define JPH_PROFILE_THREAD_END() do { delete ProfileThread::sGetInstance(); ProfileThread::sSetInstance(nullptr); } while (false)
264
266#define JPH_PROFILE_TAG2(line) profile##line
267#define JPH_PROFILE_TAG(line) JPH_PROFILE_TAG2(line)
268#define JPH_PROFILE(...) ProfileMeasurement JPH_PROFILE_TAG(__LINE__)(__VA_ARGS__)
269
271#define JPH_PROFILE_FUNCTION() JPH_PROFILE(JPH_FUNCTION_NAME)
272
274#define JPH_PROFILE_NEXTFRAME() Profiler::sInstance->NextFrame()
275
277#define JPH_PROFILE_DUMP(...) Profiler::sInstance->Dump(__VA_ARGS__)
278
279JPH_SUPPRESS_WARNING_POP
280
281#else
282
284// Dummy profiling instructions
286
287JPH_SUPPRESS_WARNING_PUSH
288JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
289
290#define JPH_PROFILE_START(name)
291#define JPH_PROFILE_END()
292#define JPH_PROFILE_THREAD_START(name)
293#define JPH_PROFILE_THREAD_END()
294#define JPH_PROFILE(...)
295#define JPH_PROFILE_FUNCTION()
296#define JPH_PROFILE_NEXTFRAME()
297#define JPH_PROFILE_DUMP(...)
298
299JPH_SUPPRESS_WARNING_POP
300
301#endif
std::uint8_t uint8
Definition: Core.h:453
#define JPH_EXPORT
Definition: Core.h:236
#define JPH_SUPPRESS_WARNINGS_STD_BEGIN
Definition: Core.h:383
#define JPH_SUPPRESS_WARNINGS_STD_END
Definition: Core.h:395
std::uint64_t uint64
Definition: Core.h:456
unsigned int uint
Definition: Core.h:452
#define JPH_NAMESPACE_END
Definition: Core.h:378
#define JPH_CLANG_SUPPRESS_WARNING(w)
Definition: Core.h:263
std::uint32_t uint32
Definition: Core.h:455
#define JPH_EXPORT_GCC_BUG_WORKAROUND
Definition: Core.h:240
#define JPH_NAMESPACE_BEGIN
Definition: Core.h:372
#define JPH_OVERRIDE_NEW_DELETE
Macro to override the new and delete functions.
Definition: Memory.h:31
std::basic_string< char, std::char_traits< char >, STLAllocator< char > > String
Definition: STLAllocator.h:107
std::unordered_map< Key, T, Hash, KeyEqual, STLAllocator< pair< const Key, T > > > UnorderedMap
Definition: UnorderedMap.h:13
Definition: Array.h:36
Class that makes another class non-copyable. Usage: Inherit from NonCopyable.
Definition: NonCopyable.h:11
Create this class on the stack to start sampling timing information of a particular scope.
Definition: Profiler.h:229
Definition: Profiler.h:187
uint32 mColor
Color to use for this sample.
Definition: Profiler.h:192
uint64 mEndCycle
Cycle counter at end of measurement.
Definition: Profiler.h:196
JPH_OVERRIDE_NEW_DELETE const char * mName
User defined name of this item.
Definition: Profiler.h:191
uint8 mDepth
Calculated depth.
Definition: Profiler.h:193
uint64 mStartCycle
Cycle counter at start of measurement.
Definition: Profiler.h:195
Collects all samples of a single thread.
Definition: Profiler.h:201
ProfileSample mSamples[cMaxSamples]
Buffer of samples.
Definition: Profiler.h:212
uint mCurrentSample
Next position to write a sample to.
Definition: Profiler.h:213
~ProfileThread()
Definition: Profiler.inl:17
static ProfileThread * sGetInstance()
Definition: Profiler.h:220
String mThreadName
Name of the thread that we're collecting information for.
Definition: Profiler.h:211
static void sSetInstance(ProfileThread *inInstance)
Definition: Profiler.h:219
static const uint cMaxSamples
Definition: Profiler.h:209
Singleton class for managing profiling information.
Definition: Profiler.h:96
JPH_OVERRIDE_NEW_DELETE Profiler()
Constructor.
Definition: Profiler.h:101
static Profiler * sInstance
Singleton instance.
Definition: Profiler.h:117