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>
10
14
15#if defined(JPH_EXTERNAL_PROFILE)
16
18
19#ifdef JPH_SHARED_LIBRARY
21using ProfileStartMeasurementFunction = void (*)(const char *inName, uint32 inColor, uint8 *ioUserData);
22using ProfileEndMeasurementFunction = void (*)(uint8 *ioUserData);
23
24JPH_EXPORT extern ProfileStartMeasurementFunction ProfileStartMeasurement;
25JPH_EXPORT extern ProfileEndMeasurementFunction ProfileEndMeasurement;
26#endif // JPH_SHARED_LIBRARY
27
33class alignas(16) ExternalProfileMeasurement : public NonCopyable
34{
35public:
37#ifdef JPH_SHARED_LIBRARY
38 JPH_INLINE ExternalProfileMeasurement(const char *inName, uint32 inColor = 0) { ProfileStartMeasurement(inName, inColor, mUserData); }
39 JPH_INLINE ~ExternalProfileMeasurement() { ProfileEndMeasurement(mUserData); }
40#else
41 ExternalProfileMeasurement(const char *inName, uint32 inColor = 0);
42 ~ExternalProfileMeasurement();
43#endif
44
45private:
46 uint8 mUserData[64];
47};
48
50
52// Macros to do the actual profiling
54
56JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
57
58// Dummy implementations
59#define JPH_PROFILE_START(name)
60#define JPH_PROFILE_END()
61#define JPH_PROFILE_THREAD_START(name)
62#define JPH_PROFILE_THREAD_END()
63#define JPH_PROFILE_NEXTFRAME()
64#define JPH_PROFILE_DUMP(...)
65
66// Scope profiling measurement
67#define JPH_PROFILE_TAG2(line) profile##line
68#define JPH_PROFILE_TAG(line) JPH_PROFILE_TAG2(line)
69
79#define JPH_PROFILE(...) ExternalProfileMeasurement JPH_PROFILE_TAG(__LINE__)(__VA_ARGS__)
80
81// Scope profiling for function
82#define JPH_PROFILE_FUNCTION() JPH_PROFILE(JPH_FUNCTION_NAME)
83
85
86#elif defined(JPH_PROFILE_ENABLED)
87
89
90class ProfileSample;
91class ProfileThread;
92
95{
96public:
98
100 Profiler() { UpdateReferenceTime(); }
101
103 void NextFrame();
104
107 void Dump(const string_view &inTag = string_view());
108
110 void AddThread(ProfileThread *inThread);
111
113 void RemoveThread(ProfileThread *inThread);
114
116 uint64 GetProcessorTicksPerSecond() const;
117
120
121private:
123 struct ThreadSamples
124 {
125 String mThreadName;
126 ProfileSample * mSamplesBegin;
127 ProfileSample * mSamplesEnd;
128 };
129
131 class Aggregator
132 {
133 public:
135 Aggregator(const char *inName) : mName(inName) { }
136
138 void AccumulateMeasurement(uint64 inCyclesInCallWithChildren)
139 {
140 mCallCounter++;
141 mTotalCyclesInCallWithChildren += inCyclesInCallWithChildren;
142 mMinCyclesInCallWithChildren = min(inCyclesInCallWithChildren, mMinCyclesInCallWithChildren);
143 mMaxCyclesInCallWithChildren = max(inCyclesInCallWithChildren, mMaxCyclesInCallWithChildren);
144 }
145
147 bool operator < (const Aggregator &inRHS) const
148 {
149 return mTotalCyclesInCallWithChildren > inRHS.mTotalCyclesInCallWithChildren;
150 }
151
153 const char * mName;
154
156 uint32 mCallCounter = 0;
157 uint64 mTotalCyclesInCallWithChildren = 0;
158 uint64 mMinCyclesInCallWithChildren = 0xffffffffffffffffUL;
159 uint64 mMaxCyclesInCallWithChildren = 0;
160 };
161
162 using Threads = Array<ThreadSamples>;
163 using Aggregators = Array<Aggregator>;
164 using KeyToAggregator = UnorderedMap<const char *, size_t>;
165
167 static void sAggregate(int inDepth, uint32 inColor, ProfileSample *&ioSample, const ProfileSample *inEnd, Aggregators &ioAggregators, KeyToAggregator &ioKeyToAggregator);
168
170 void UpdateReferenceTime();
171
173 void DumpInternal();
174 void DumpChart(const char *inTag, const Threads &inThreads, const KeyToAggregator &inKeyToAggregators, const Aggregators &inAggregators);
175
176 std::mutex mLock;
177 uint64 mReferenceTick;
178 uint64 mReferenceTime;
179 Array<ProfileThread *> mThreads;
180 bool mDump = false;
181 String mDumpTag;
182};
183
184// Class that contains the information of a single scoped measurement
197
200{
201public:
203
205 inline ProfileThread(const string_view &inThreadName);
206 inline ~ProfileThread();
207
208 static const uint cMaxSamples = 65536;
209
213
214#ifdef JPH_SHARED_LIBRARY
215 JPH_EXPORT static void sSetInstance(ProfileThread *inInstance);
217#else
218 static inline void sSetInstance(ProfileThread *inInstance) { sInstance = inInstance; }
219 static inline ProfileThread *sGetInstance() { return sInstance; }
220
221private:
222 static thread_local ProfileThread *sInstance;
223#endif
224};
225
228{
229public:
231 inline ProfileMeasurement(const char *inName, uint32 inColor = 0);
232 inline ~ProfileMeasurement();
233
234private:
235 ProfileSample * mSample;
236 ProfileSample mTemp;
237
238 static bool sOutOfSamplesReported;
239};
240
242
243#include "Profiler.inl"
244
246// Macros to do the actual profiling
248
250JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
251
252
253#define JPH_PROFILE_START(name) do { Profiler::sInstance = new Profiler; JPH_PROFILE_THREAD_START(name); } while (false)
254
256#define JPH_PROFILE_END() do { JPH_PROFILE_THREAD_END(); delete Profiler::sInstance; Profiler::sInstance = nullptr; } while (false)
257
259#define JPH_PROFILE_THREAD_START(name) do { if (Profiler::sInstance) ProfileThread::sSetInstance(new ProfileThread(name)); } while (false)
260
262#define JPH_PROFILE_THREAD_END() do { delete ProfileThread::sGetInstance(); ProfileThread::sSetInstance(nullptr); } while (false)
263
265#define JPH_PROFILE_TAG2(line) profile##line
266#define JPH_PROFILE_TAG(line) JPH_PROFILE_TAG2(line)
267#define JPH_PROFILE(...) ProfileMeasurement JPH_PROFILE_TAG(__LINE__)(__VA_ARGS__)
268
270#define JPH_PROFILE_FUNCTION() JPH_PROFILE(JPH_FUNCTION_NAME)
271
273#define JPH_PROFILE_NEXTFRAME() Profiler::sInstance->NextFrame()
274
276#define JPH_PROFILE_DUMP(...) Profiler::sInstance->Dump(__VA_ARGS__)
277
279
280#else
281
283// Dummy profiling instructions
285
287JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
288
289#define JPH_PROFILE_START(name)
290#define JPH_PROFILE_END()
291#define JPH_PROFILE_THREAD_START(name)
292#define JPH_PROFILE_THREAD_END()
293#define JPH_PROFILE(...)
294#define JPH_PROFILE_FUNCTION()
295#define JPH_PROFILE_NEXTFRAME()
296#define JPH_PROFILE_DUMP(...)
297
299
300#endif
std::uint8_t uint8
Definition Core.h:501
#define JPH_EXPORT
Definition Core.h:275
#define JPH_SUPPRESS_WARNINGS_STD_BEGIN
Definition Core.h:430
#define JPH_SUPPRESS_WARNINGS_STD_END
Definition Core.h:443
std::uint64_t uint64
Definition Core.h:504
unsigned int uint
Definition Core.h:500
#define JPH_NAMESPACE_END
Definition Core.h:425
#define JPH_CLANG_SUPPRESS_WARNING(w)
Definition Core.h:302
std::uint32_t uint32
Definition Core.h:503
#define JPH_EXPORT_GCC_BUG_WORKAROUND
Definition Core.h:279
#define JPH_NAMESPACE_BEGIN
Definition Core.h:419
#define JPH_OVERRIDE_NEW_DELETE
Macro to override the new and delete functions.
Definition Memory.h:50
std::basic_string< char, std::char_traits< char >, STLAllocator< char > > String
Definition STLAllocator.h:107
#define JPH_SUPPRESS_WARNING_POP
Definition ShaderCore.h:38
#define JPH_SUPPRESS_WARNING_PUSH
Definition ShaderCore.h:37
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:228
Definition Profiler.h:186
uint32 mColor
Color to use for this sample.
Definition Profiler.h:191
uint64 mEndCycle
Cycle counter at end of measurement.
Definition Profiler.h:195
JPH_OVERRIDE_NEW_DELETE const char * mName
User defined name of this item.
Definition Profiler.h:190
uint8 mDepth
Calculated depth.
Definition Profiler.h:192
uint64 mStartCycle
Cycle counter at start of measurement.
Definition Profiler.h:194
Collects all samples of a single thread.
Definition Profiler.h:200
ProfileSample mSamples[cMaxSamples]
Buffer of samples.
Definition Profiler.h:211
uint mCurrentSample
Next position to write a sample to.
Definition Profiler.h:212
~ProfileThread()
Definition Profiler.inl:17
JPH_OVERRIDE_NEW_DELETE ProfileThread(const string_view &inThreadName)
Constructor.
Definition Profiler.inl:11
static ProfileThread * sGetInstance()
Definition Profiler.h:219
String mThreadName
Name of the thread that we're collecting information for.
Definition Profiler.h:210
static void sSetInstance(ProfileThread *inInstance)
Definition Profiler.h:218
static const uint cMaxSamples
Definition Profiler.h:208
Singleton class for managing profiling information.
Definition Profiler.h:95
JPH_OVERRIDE_NEW_DELETE Profiler()
Constructor.
Definition Profiler.h:100
static Profiler * sInstance
Singleton instance.
Definition Profiler.h:119
Definition UnorderedMap.h:31