1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
4 #include "CryProfilingSystem.h"
5 #include "BootProfiler.h"
6 #include <CrySystem/IConsole.h>
7 #include <CryThreading/IThreadManager.h>
9 #if CRY_PLATFORM_WINDOWS
13 // CryMemoryManager.cpp
14 extern int64
CryMemoryGetThreadAllocatedSize();
16 // debugging of profiler
18 #define CRY_PROFILER_ASSERT(...) if(!(__VA_ARGS__)) __debugbreak(); //assert(__VA_ARGS__)
20 #define CRY_PROFILER_ASSERT(...)
23 // measuring the overhead also increases the overhead (by ~0.5ms main thread time)
24 #define CRY_PROFILER_MEASURE_OVERHEAD 1
26 #define PROF_CVAR_THREAD "profile_exclusiveThreadId"
27 threadID
CCryProfilingSystem::s_exclusiveThread
= 0;
28 #define PROF_CVAR_VERBOSITY "profile_verbosity"
29 int CCryProfilingSystem::s_verbosity
= 10;
30 #define PROF_CVAR_SUBSYSTEM "profile_subsystemMask"
31 int64
CCryProfilingSystem::s_subsystemFilterMask
= 0;
32 float CCryProfilingSystem::profile_peak_tolerance
= 0;
33 int CCryProfilingSystem::profile_value
= TIME
;
35 #define CRY_PROFILER_MAX_DEPTH 64
36 // tracks nesting level of profiling sections
37 static thread_local
int tls_profilingStackDepth
= 0;
38 static thread_local SProfilingSection
* tls_currentSections
[CRY_PROFILER_MAX_DEPTH
];
40 //! RAII struct for measuring profiling overhead
41 struct CCryProfilingSystem::AutoTimer
43 AutoTimer(CCryProfilingSystem
* _pProfSystem
) :
44 timeStamp(CryGetTicks())
45 #if CRY_PROFILER_MEASURE_OVERHEAD
46 , overheadAccumulator(&_pProfSystem
->m_profilingOverhead
.m_accumulator
)
50 #if CRY_PROFILER_MEASURE_OVERHEAD
53 CryInterlockedAdd(overheadAccumulator
, CryGetTicks() - timeStamp
);
57 const int64 timeStamp
;
59 #if CRY_PROFILER_MEASURE_OVERHEAD
61 int64
* overheadAccumulator
;
65 static int64
GetFrequency_ProfilerInternal()
68 if (QueryPerformanceFrequency(&freq
))
71 CryWarning(VALIDATOR_MODULE_SYSTEM
, VALIDATOR_WARNING
, "Couldn't determine performance counter frequency! Profiling times will likely be wrong.");
75 CCryProfilingSystem::CCryProfilingSystem()
77 , m_trackingPaused(false)
79 , m_lastTotalPageFaults(0)
80 , m_MsPerTick(1000.0f
/ GetFrequency_ProfilerInternal())
81 , m_pBootProfiler(nullptr)
83 assert(s_pInstance
== nullptr);
87 CCryProfilingSystem::~CCryProfilingSystem()
90 s_pInstance
= nullptr;
93 void CCryProfilingSystem::ProfilingSystemFilterCvarChangedCallback(ICVar
* pCvar
)
95 if (s_pInstance
== nullptr)
98 if (strcmp(PROF_CVAR_SUBSYSTEM
, pCvar
->GetName()) == 0)
99 s_pInstance
->s_subsystemFilterMask
= pCvar
->GetI64Val();
100 else if (strcmp(PROF_CVAR_VERBOSITY
, pCvar
->GetName()) == 0)
101 s_pInstance
->s_verbosity
= pCvar
->GetIVal();
102 else if (strcmp(PROF_CVAR_THREAD
, pCvar
->GetName()) == 0)
103 s_pInstance
->s_exclusiveThread
= (threadID
)pCvar
->GetI64Val();
106 assert(!"Unrecognized CVar!");
109 s_pInstance
->ReapplyTrackerFilter();
112 void CCryProfilingSystem::FilterSubsystemCommand(IConsoleCmdArgs
* args
)
114 if (s_pInstance
== nullptr)
117 if (args
->GetArgCount() < 3)
119 CryLog("Too few arguments. Usage: %s [0,1] System1 System2 ..", args
->GetArg(0));
124 if (strcmp("0", args
->GetArg(1)) == 0)
126 else if (strcmp("1", args
->GetArg(1)) == 0)
130 CryLog("First argument has to be 0 or 1.");
134 int64 changeMask
= 0;
135 for (int arg
= 2; arg
< args
->GetArgCount(); ++arg
)
138 for (int subsystemId
= 0; subsystemId
< EProfiledSubsystem::PROFILE_LAST_SUBSYSTEM
; ++subsystemId
)
140 if (stricmp(args
->GetArg(arg
), s_pInstance
->GetModuleName((EProfiledSubsystem
)subsystemId
)) == 0)
142 changeMask
|= int64(1) << subsystemId
;
148 CryLog("Unknown Subsystem name '%s'.", args
->GetArg(arg
));
153 ICVar
* pCvar
= gEnv
->pConsole
->GetCVar(PROF_CVAR_SUBSYSTEM
);
154 int64 newMask
= enable
? (pCvar
->GetI64Val() | changeMask
) : (pCvar
->GetI64Val() & ~changeMask
);
156 CryLog("Subsystem mask is now set to 0x%" PRIx64
".", newMask
);
160 void CCryProfilingSystem::FilterThreadCommand(struct IConsoleCmdArgs
* args
)
162 if (s_pInstance
== nullptr)
165 if (args
->GetArgCount() != 2)
167 CryLog("Incorrect number of arguments. Usage: %s ThreadName", args
->GetArg(0));
171 threadID tid
= gEnv
->pThreadManager
->GetThreadId(args
->GetArg(1));
174 ICVar
* pCvar
= gEnv
->pConsole
->GetCVar(PROF_CVAR_THREAD
);
175 pCvar
->Set((int64
)tid
);
178 CryLog("Thread not found.");
181 void CCryProfilingSystem::StopPofilingCommand(struct IConsoleCmdArgs
* args
)
187 void CCryProfilingSystem::RegisterCVars()
189 REGISTER_INT64_CB(PROF_CVAR_SUBSYSTEM
, 0, VF_BITFIELD
,
190 "Set the bitmask for filtering out subsystems from profiling. Set a bit to 1 to exclude to corresponding system from the profile."
191 , ProfilingSystemFilterCvarChangedCallback
);
193 REGISTER_INT64_CB(PROF_CVAR_THREAD
, 0, VF_NULL
,
194 "Allows filtering the profiling based on thread id. Only the thread with the given id will be included in the profile."
195 , ProfilingSystemFilterCvarChangedCallback
);
196 REGISTER_COMMAND("profile_exclusiveThread", FilterThreadCommand
, VF_NULL
,
197 "Allows filtering the profiling based on thread name. Only the thread with the given name will be included in the profile.");
199 ICVar
* pVerbosityVar
= REGISTER_INT_CB(PROF_CVAR_VERBOSITY
, s_verbosity
, VF_NULL
,
200 "Sets the depth up to which profiling information will be gathered.\n"
201 "Higher values lead to more detailed profiling information, but also slightly increase performance costs."
202 , ProfilingSystemFilterCvarChangedCallback
);
203 pVerbosityVar
->SetMaxValue(CRY_PROFILER_MAX_DEPTH
);
205 string filterSubsystemHelp
= "Allows to turn on/off the profiling filter for subsystems by name. First parameter indicates if you want to enable or disable filtering."
206 " Use 1 to enable filtering, i.e. exclude the subsystem from profiling; otherwise use 0. After that you can give the names of the subsystems you want to set the filter for.\n"
207 "E.g. 'profile_filterSubsystem 1 AI Renderer' will exclude the AI and rendering systems from profiling.\n"
208 "Available subsystem names are: ";
209 for (int subsystemId
= 0; subsystemId
< EProfiledSubsystem::PROFILE_LAST_SUBSYSTEM
; ++subsystemId
)
211 filterSubsystemHelp
.append(GetModuleName((EProfiledSubsystem
) subsystemId
));
212 if (subsystemId
!= EProfiledSubsystem::PROFILE_LAST_SUBSYSTEM
- 1)
213 filterSubsystemHelp
.append(", ");
216 REGISTER_COMMAND("profile_filterSubsystem", FilterSubsystemCommand
, VF_NULL
, filterSubsystemHelp
.c_str());
217 REGISTER_COMMAND("profile_stop", StopPofilingCommand
, VF_NULL
, "Terminates the profiling session. (Cannot be restarted. Use the 'Scroll Lock' key for un/pausing.)");
219 REGISTER_CVAR(profile_peak_tolerance
, 5.0f
, VF_NULL
, "Profiler Peaks Tolerance in Milliseconds."
220 " If the self time of a section in one frame exceeds its average by more than the tolerance a peak is logged.");
223 ICVar
* pvar
= REGISTER_CVAR(profile_value
, TIME
, VF_NULL
,
224 "Allows to set the value that should be profiled. Set to 0 for time and to 1 for allocated memory.\n"
225 "Only use time profiling with the 'profile X' commands. Otherwise, e.g. Bootprofiler and Statoscope would give unexpected results.");
226 pvar
->SetMinValue(TIME
);
227 pvar
->SetMaxValue(MEMORY
);
231 void CCryProfilingSystem::Stop()
233 AutoTimer
timer(this);
234 AutoWriteLock
autoLock(m_trackerLock
);
238 stl::free_container(m_activeTrackers
);
239 stl::free_container(m_excludedTrackers
);
240 stl::free_container(m_FrameListeners
);
241 m_pBootProfiler
= nullptr;
245 bool CCryProfilingSystem::IsStopped() const
250 void CCryProfilingSystem::PauseRecording(bool pause
)
252 // actual pausing is triggered at frame end
256 bool CCryProfilingSystem::IsPaused() const
258 return m_trackingPaused
;
261 void CCryProfilingSystem::StartThread() {}
263 void CCryProfilingSystem::EndThread() {}
265 void CCryProfilingSystem::AddFrameListener(ICryProfilerFrameListener
* pListener
)
267 AutoWriteLock
autoLock(m_trackerLock
);
270 m_FrameListeners
.push_back(pListener
);
274 void CCryProfilingSystem::SetBootProfiler(CBootProfiler
* pProf
)
276 m_pBootProfiler
= pProf
;
279 void CCryProfilingSystem::RemoveFrameListener(ICryProfilerFrameListener
* pListener
)
281 AutoTimer
timer(this);
282 AutoWriteLock
autoLock(m_trackerLock
);
283 stl::find_and_erase(m_FrameListeners
, pListener
);
286 void CCryProfilingSystem::DescriptionCreated(SProfilingSectionDescription
* pDesc
)
288 pDesc
->color_argb
= GenerateColorBasedOnName(pDesc
->szEventname
);
291 void CCryProfilingSystem::DescriptionDestroyed(SProfilingSectionDescription
* pDesc
)
293 AutoTimer
timer(this);
294 AutoWriteLock
lock(m_trackerLock
);
296 SProfilingSectionTracker
* pTracker
= (SProfilingSectionTracker
*) pDesc
->customData
;
300 if (pTracker
->isActive
)
301 erased
= stl::find_and_erase(m_activeTrackers
, pTracker
);
303 erased
= stl::find_and_erase(m_excludedTrackers
, pTracker
);
304 CRY_PROFILER_ASSERT(erased
);
306 SProfilingSectionTracker
* tmp
= pTracker
;
307 pTracker
= pTracker
->pNextThreadTracker
;
310 pDesc
->customData
= 0;
313 SProfilingSectionTracker
* CCryProfilingSystem::AddTracker(const SProfilingSectionDescription
* pDesc
, threadID tid
)
315 AutoWriteLock
autoLock(m_trackerLock
);
317 // look up to ensure there is not already a tracker for the current thread
318 SProfilingSectionTracker
* pTracker
= (SProfilingSectionTracker
*)pDesc
->customData
;
319 while (pTracker
&& pTracker
->threadId
!= tid
)
320 pTracker
= pTracker
->pNextThreadTracker
;
325 // didn't find any, so create one
326 pTracker
= new SProfilingSectionTracker(pDesc
, tid
);
328 pTracker
->isActive
= !IsExcludedByFilter(pTracker
);
329 if (pTracker
->isActive
)
330 m_activeTrackers
.push_back(pTracker
);
332 m_excludedTrackers
.push_back(pTracker
);
334 // link new tracker into list
335 pTracker
->pNextThreadTracker
= (SProfilingSectionTracker
*) pDesc
->customData
;
336 pDesc
->customData
= (uintptr_t) pTracker
;
341 bool CCryProfilingSystem::StartSection(SProfilingSection
* pSection
)
345 AutoTimer
timer(this);
347 if (tls_profilingStackDepth
>= s_verbosity
)
350 #if CRY_PROFILER_COMBINE_JOB_TRACKERS
351 const threadID currentTID
= (gEnv
->pJobManager
&& JobManager::IsWorkerThread()) ? CRY_PROFILER_JOB_THREAD_ID
: CryGetCurrentThreadId();
353 const threadID currentTID
= CryGetCurrentThreadId();
356 SProfilingSectionTracker
* pTracker
= nullptr;
358 AutoReadLock
autoLock(m_trackerLock
);
360 // look for tracker in the description's custom data
361 pTracker
= (SProfilingSectionTracker
*)pSection
->pDescription
->customData
;
362 while (pTracker
&& pTracker
->threadId
!= currentTID
)
363 pTracker
= pTracker
->pNextThreadTracker
;
365 // did not find a tracker, so create a new one
366 if (pTracker
== nullptr)
368 // AddTracker() write-locks internally
369 m_trackerLock
.RUnlock();
370 pTracker
= AddTracker(pSection
->pDescription
, currentTID
);
371 m_trackerLock
.RLock();
374 CRY_PROFILER_ASSERT(pTracker
);
376 // no tracking on excluded sections
377 if (!pTracker
->isActive
)
379 if (!m_trackingPaused
)
382 // use section custom data to store tracker, so we don't have to look it up again later
383 pSection
->customData
= (uintptr_t) pTracker
;
385 if(profile_value
== MEMORY
)
386 pSection
->startValue
= CryMemoryGetThreadAllocatedSize();
388 pSection
->startValue
= timer
.timeStamp
;
390 #if defined(ENABLE_LOADING_PROFILER)
392 m_pBootProfiler
->OnSectionStart(*pSection
);
395 tls_currentSections
[tls_profilingStackDepth
] = pSection
;
396 ++tls_profilingStackDepth
;
400 void CCryProfilingSystem::EndSection(SProfilingSection
* pSection
)
404 AutoTimer
timer(this);
406 // We need to finish sections that were started before pausing, so we pop before checking for m_trackingPaused
407 --tls_profilingStackDepth
;
408 CRY_PROFILER_ASSERT(tls_profilingStackDepth
>= 0);
409 CRY_PROFILER_ASSERT(tls_currentSections
[tls_profilingStackDepth
] == pSection
);
411 // calculate measurements
412 SProfilingSectionEnd sectionEnd
;
413 if (profile_value
== MEMORY
)
415 sectionEnd
.totalValue
= CryMemoryGetThreadAllocatedSize() - pSection
->startValue
;
416 sectionEnd
.selfValue
= sectionEnd
.totalValue
- pSection
->childExcludeValue
;
420 sectionEnd
.totalValue
= timer
.timeStamp
- pSection
->startValue
;
421 CRY_PROFILER_ASSERT(sectionEnd
.totalValue
>= 0);
423 sectionEnd
.selfValue
= sectionEnd
.totalValue
- pSection
->childExcludeValue
;
424 CRY_PROFILER_ASSERT(sectionEnd
.selfValue
>= 0);
427 #if defined(ENABLE_LOADING_PROFILER)
429 m_pBootProfiler
->OnSectionEnd(*pSection
, sectionEnd
);
432 if (!m_trackingPaused
)
434 SProfilingSection
* const pParentSection
= tls_profilingStackDepth
> 0 ? tls_currentSections
[tls_profilingStackDepth
- 1] : nullptr;
435 SProfilingSectionTracker
* const pTracker
= (SProfilingSectionTracker
*)pSection
->customData
;
436 #if CRY_PROFILER_COMBINE_JOB_TRACKERS
437 CRY_PROFILER_ASSERT(pTracker
->threadId
== CryGetCurrentThreadId() || (JobManager::IsWorkerThread() && pTracker
->threadId
== CRY_PROFILER_JOB_THREAD_ID
));
439 CRY_PROFILER_ASSERT(pTracker
->threadId
== CryGetCurrentThreadId());
442 if (pParentSection
!= nullptr)
444 pParentSection
->childExcludeValue
+= sectionEnd
.totalValue
;
448 pTracker
->totalValue
+= sectionEnd
.totalValue
;
449 pTracker
->selfValue
+= sectionEnd
.selfValue
;
450 if (profile_value
== MEMORY
)
451 pTracker
->peakSelfValue
= max(pTracker
->peakSelfValue
, SMemoryUpdateTraits::ToFloat(sectionEnd
.selfValue
));
453 pTracker
->peakSelfValue
= max(pTracker
->peakSelfValue
, STickUpdateTraits::ToFloat(sectionEnd
.selfValue
));
457 void CCryProfilingSystem::StartFrame()
461 #if defined(ENABLE_LOADING_PROFILER)
462 AutoTimer
timer(this);
465 m_pBootProfiler
->OnFrameStart();
469 void CCryProfilingSystem::EndFrame()
473 AutoTimer
timer(this);
475 const float blendFactor
= gEnv
->pTimer
->GetProfileFrameBlending();
477 #if CRY_PLATFORM_WINDOWS
478 typedef BOOL(WINAPI
* TGetProcessMemoryInfo
)(HANDLE
, PPROCESS_MEMORY_COUNTERS
, DWORD
);
479 static TGetProcessMemoryInfo pfGetProcessMemoryInfo
= nullptr;
480 static bool s_missingPsapiDll
= false;
482 if (!pfGetProcessMemoryInfo
)
484 if (!s_missingPsapiDll
)
486 HMODULE hPsapiModule
= ::LoadLibraryA("psapi.dll");
489 pfGetProcessMemoryInfo
= (TGetProcessMemoryInfo
)(::GetProcAddress(hPsapiModule
, "GetProcessMemoryInfo"));
492 s_missingPsapiDll
= true;
496 if (pfGetProcessMemoryInfo
)
498 PROCESS_MEMORY_COUNTERS pc
;
499 pfGetProcessMemoryInfo(GetCurrentProcess(), &pc
, sizeof(pc
));
500 m_pageFaultsPerFrame
= pc
.PageFaultCount
- m_lastTotalPageFaults
;
501 m_pageFaultsPerFrame
.CommitSample
<SCountUpdateTraits
>(blendFactor
);
502 m_lastTotalPageFaults
= pc
.PageFaultCount
;
506 m_profilingOverhead
.CommitSample
<STickUpdateTraits
>(blendFactor
);
507 if (!m_trackingPaused
)
509 { AutoWriteLock
autoLock(m_trackerLock
);
510 for (SProfilingSectionTracker
* pTracker
: m_activeTrackers
)
511 CommitFrame(pTracker
, blendFactor
);
513 for (SProfilingSectionTracker
* pTracker
: m_activeTrackers
)
514 CheckForPeak(timer
.timeStamp
, pTracker
);
517 { AutoReadLock
autoLock(m_trackerLock
);
518 for (ICryProfilerFrameListener
* pProfiler
: m_FrameListeners
)
519 pProfiler
->OnFrameEnd(timer
.timeStamp
, this);
521 for (SProfilingSectionTracker
* pTracker
: m_activeTrackers
)
522 pTracker
->peakSelfValue
= 0;
526 #if defined(ENABLE_LOADING_PROFILER)
528 m_pBootProfiler
->OnFrameEnd();
531 // pause was requested or no one is listening for the results
532 m_trackingPaused
= m_willPause
|| m_FrameListeners
.empty();
535 void CCryProfilingSystem::RecordMarker(SProfilingMarker
* pMarker
)
537 if (!m_enabled
|| m_pBootProfiler
== nullptr)
539 AutoTimer
timer(this);
541 if (IsExcludedByFilter(pMarker
))
544 if(pMarker
->pDescription
->color_argb
== 0)
546 pMarker
->pDescription
->color_argb
= GenerateColorBasedOnName(pMarker
->pDescription
->szMarkername
);
549 #if defined(ENABLE_LOADING_PROFILER)
550 m_pBootProfiler
->OnMarker(timer
.timeStamp
, *pMarker
);
554 const CCryProfilingSystem::TrackerList
* CCryProfilingSystem::GetActiveTrackers() const
556 return &m_activeTrackers
;
559 const CCryProfilingSystem::PeakList
* CCryProfilingSystem::GetPeakRecords() const
564 void CCryProfilingSystem::CheckForPeak(int64 time
, SProfilingSectionTracker
* pTracker
)
566 float average
= pTracker
->selfValue
.Average();
567 float peakValue
= pTracker
->selfValue
.Latest();
569 if ((peakValue
- average
) > profile_peak_tolerance
)
572 peak
.pTracker
= pTracker
;
573 peak
.peakValue
= peakValue
;
574 peak
.averageValue
= average
;
575 peak
.variance
= pTracker
->selfValue
.Variance();
576 peak
.count
= pTracker
->count
;
578 peak
.pageFaults
= m_pageFaultsPerFrame
.CurrentRaw();
579 peak
.frame
= gEnv
->nMainFrameID
;
580 peak
.timeSeconds
= time
* m_MsPerTick
* 0.001f
;
581 peak
.waiting
= pTracker
->pDescription
->isWaiting
;
583 m_peaks
.push_front_overwrite(peak
);
587 void CCryProfilingSystem::CommitFrame(SProfilingSectionTracker
* pTracker
, float blendFactor
)
589 pTracker
->count
.CommitSample
<SCountUpdateTraits
>(blendFactor
);
590 if(profile_value
== TIME
)
592 pTracker
->selfValue
.CommitSample
<STickUpdateTraits
>(blendFactor
);
593 pTracker
->totalValue
.CommitSample
<STickUpdateTraits
>(blendFactor
);
597 pTracker
->selfValue
.CommitSample
<SMemoryUpdateTraits
>(blendFactor
);
598 pTracker
->totalValue
.CommitSample
<SMemoryUpdateTraits
>(blendFactor
);
602 bool CCryProfilingSystem::IsExcludedByFilter(const SProfilingSectionTracker
* pTracker
) const
604 if ((int64(1) << (uint8
) pTracker
->pDescription
->subsystem
) & s_subsystemFilterMask
)
607 if (s_exclusiveThread
!= 0 && pTracker
->threadId
!= s_exclusiveThread
)
613 bool CCryProfilingSystem::IsExcludedByFilter(const SProfilingMarker
* pMarker
) const
615 if ((int64(1) << (uint8
)pMarker
->pDescription
->subsystem
) & s_subsystemFilterMask
)
618 if (s_exclusiveThread
!= 0 && pMarker
->threadId
!= s_exclusiveThread
)
624 void CCryProfilingSystem::ReapplyTrackerFilter()
626 AutoTimer
timer(this);
628 TrackerList activeTrackers
;
629 TrackerList excludedTrackers
;
631 { AutoReadLock
autoLock(m_trackerLock
);
633 activeTrackers
.reserve(m_activeTrackers
.size() + m_excludedTrackers
.size());
634 excludedTrackers
.reserve(m_activeTrackers
.size() + m_excludedTrackers
.size());
636 for (SProfilingSectionTracker
* pTracker
: m_activeTrackers
)
638 pTracker
->isActive
= !IsExcludedByFilter(pTracker
);
639 if (pTracker
->isActive
)
640 activeTrackers
.push_back(pTracker
);
642 excludedTrackers
.push_back(pTracker
);
645 const float blendFactor
= gEnv
->pTimer
->GetProfileFrameBlending();
646 for (SProfilingSectionTracker
* pTracker
: m_excludedTrackers
)
648 pTracker
->isActive
= !IsExcludedByFilter(pTracker
);
649 if (pTracker
->isActive
)
651 CommitFrame(pTracker
, blendFactor
);
652 activeTrackers
.push_back(pTracker
);
655 excludedTrackers
.push_back(pTracker
);
659 { AutoWriteLock
autoLock(m_trackerLock
);
661 m_activeTrackers
= activeTrackers
;
662 m_excludedTrackers
= excludedTrackers
;
666 void CCryProfilingSystem::AcquireReadAccess()
668 m_trackerLock
.RLock();
671 void CCryProfilingSystem::ReleaseReadAccess()
673 m_trackerLock
.RUnlock();
676 CCryProfilingSystem
* CCryProfilingSystem::s_pInstance
= nullptr;
678 bool CCryProfilingSystem::StartSectionStatic(SProfilingSection
* pSection
)
680 return s_pInstance
->StartSection(pSection
);
683 void CCryProfilingSystem::EndSectionStatic(SProfilingSection
* pSection
)
685 s_pInstance
->EndSection(pSection
);
688 void CCryProfilingSystem::RecordMarkerStatic(SProfilingMarker
* pMarker
)
690 s_pInstance
->RecordMarker(pMarker
);
693 const char* CCryProfilingSystem::GetModuleName(const SProfilingSectionTracker
* pTracker
) const
695 return GetModuleName(pTracker
->pDescription
->subsystem
);
698 const CSamplerStats
<TProfilingCount
>& CCryProfilingSystem::PageFaultsPerFrame() const
700 return m_pageFaultsPerFrame
;