[Project64] Fix CPU profiling

This commit is contained in:
zilmar 2016-10-05 06:58:11 +11:00
parent 4be7465232
commit a278a2cde6
17 changed files with 120 additions and 113 deletions

View File

@ -209,7 +209,6 @@ public enum SettingsID
Debugger_ShowPifErrors,
Debugger_ShowDivByZero,
Debugger_GenerateLogFiles,
Debugger_ProfileCode,
Debugger_DisableGameFixes,
Debugger_AppLogLevel,
Debugger_AppLogFlush,

View File

@ -47,8 +47,6 @@ public enum SystemEvent
SysEvent_Interrupt_VI,
SysEvent_Interrupt_PI,
SysEvent_Interrupt_DP,
SysEvent_Profile_StartStop,
SysEvent_Profile_ResetLogs,
SysEvent_ResetFunctionTimes,
SysEvent_DumpFunctionTimes,
;

View File

@ -14,9 +14,9 @@
#include <Project64-core/N64System/N64Class.h>
CSystemEvents::CSystemEvents(CN64System * System, CPlugins * Plugins) :
m_System(System),
m_Plugins(Plugins),
m_bDoSomething(false)
m_System(System),
m_Plugins(Plugins),
m_bDoSomething(false)
{
}
@ -71,13 +71,6 @@ void CSystemEvents::ExecuteEvents()
case SysEvent_ResetCPU_Hard:
m_System->Reset(true, true);
break;
case SysEvent_Profile_StartStop:
case SysEvent_Profile_ResetLogs:
if (g_Recompiler)
{
g_Recompiler->ResetFunctionTimes();
}
break;
case SysEvent_ExecuteInterrupt:
g_Reg->DoIntrException(false);
break;
@ -121,6 +114,12 @@ void CSystemEvents::ExecuteEvents()
case SysEvent_ChangePlugins:
ChangePluginFunc();
break;
case SysEvent_ResetFunctionTimes:
if (g_Recompiler)
{
g_Recompiler->ResetFunctionTimes();
}
break;
case SysEvent_DumpFunctionTimes:
if (g_Recompiler)
{

View File

@ -49,8 +49,6 @@ enum SystemEvent
SysEvent_Interrupt_VI,
SysEvent_Interrupt_PI,
SysEvent_Interrupt_DP,
SysEvent_Profile_StartStop,
SysEvent_Profile_ResetLogs,
SysEvent_ResetFunctionTimes,
SysEvent_DumpFunctionTimes,
};

View File

@ -31,33 +31,33 @@
#pragma warning(disable:4355) // Disable 'this' : used in base member initializer list
CN64System::CN64System(CPlugins * Plugins, bool SavesReadOnly, bool SyncSystem) :
CSystemEvents(this, Plugins),
m_EndEmulation(false),
m_SaveUsing((SAVE_CHIP_TYPE)g_Settings->LoadDword(Game_SaveChip)),
m_Plugins(Plugins),
m_SyncCPU(NULL),
m_SyncPlugins(NULL),
m_MMU_VM(SavesReadOnly),
m_TLB(this),
m_Reg(this, this),
m_Recomp(NULL),
m_InReset(false),
m_NextTimer(0),
m_SystemTimer(m_NextTimer),
m_bCleanFrameBox(true),
m_bInitialized(false),
m_RspBroke(true),
m_DMAUsed(false),
m_TestTimer(false),
m_NextInstruction(0),
m_JumpToLocation(0),
m_TLBLoadAddress(0),
m_TLBStoreAddress(0),
m_SyncCount(0),
m_thread(NULL),
m_hPauseEvent(true),
m_CheatsSlectionChanged(false),
m_SyncCpu(SyncSystem)
CSystemEvents(this, Plugins),
m_EndEmulation(false),
m_SaveUsing((SAVE_CHIP_TYPE)g_Settings->LoadDword(Game_SaveChip)),
m_Plugins(Plugins),
m_SyncCPU(NULL),
m_SyncPlugins(NULL),
m_MMU_VM(SavesReadOnly),
m_TLB(this),
m_Reg(this, this),
m_Recomp(NULL),
m_InReset(false),
m_NextTimer(0),
m_SystemTimer(m_NextTimer),
m_bCleanFrameBox(true),
m_bInitialized(false),
m_RspBroke(true),
m_DMAUsed(false),
m_TestTimer(false),
m_NextInstruction(0),
m_JumpToLocation(0),
m_TLBLoadAddress(0),
m_TLBStoreAddress(0),
m_SyncCount(0),
m_thread(NULL),
m_hPauseEvent(true),
m_CheatsSlectionChanged(false),
m_SyncCpu(SyncSystem)
{
WriteTrace(TraceN64System, TraceDebug, "Start");
uint32_t gameHertz = g_Settings->LoadDword(Game_ScreenHertz);
@ -149,8 +149,6 @@ void CN64System::ExternalEvent(SystemEvent action)
switch (action)
{
case SysEvent_Profile_StartStop:
case SysEvent_Profile_ResetLogs:
case SysEvent_ExecuteInterrupt:
case SysEvent_SaveMachineState:
case SysEvent_LoadMachineState:
@ -168,6 +166,7 @@ void CN64System::ExternalEvent(SystemEvent action)
case SysEvent_CloseCPU:
case SysEvent_ChangePlugins:
case SysEvent_PauseCPU_FromMenu:
case SysEvent_ResetFunctionTimes:
case SysEvent_DumpFunctionTimes:
QueueEvent(action);
break;
@ -1941,6 +1940,9 @@ void CN64System::DisplayRSPListCount()
void CN64System::RunRSP()
{
WriteTrace(TraceRSP, TraceDebug, "Start (SP Status %X)", m_Reg.SP_STATUS_REG);
PROFILE_TIMERS CPU_UsageAddr = m_CPU_Usage.StopTimer();
if ((m_Reg.SP_STATUS_REG & SP_STATUS_HALT) == 0)
{
if ((m_Reg.SP_STATUS_REG & SP_STATUS_BROKE) == 0)
@ -2007,14 +2009,11 @@ void CN64System::RunRSP()
EndTime.SetToNow();
uint32_t TimeTaken = (uint32_t)(EndTime.GetMicroSeconds() - StartTime.GetMicroSeconds());
if (bShowCPUPer())
switch (Task)
{
switch (Task)
{
case 1: m_CPU_Usage.RecordTime(Timer_RSP_Dlist, TimeTaken); break;
case 2: m_CPU_Usage.RecordTime(Timer_RSP_Alist, TimeTaken); break;
default: m_CPU_Usage.RecordTime(Timer_RSP_Unknown, TimeTaken); break;
}
case 1: m_CPU_Usage.RecordTime(Timer_RSP_Dlist, TimeTaken); break;
case 2: m_CPU_Usage.RecordTime(Timer_RSP_Alist, TimeTaken); break;
default: m_CPU_Usage.RecordTime(Timer_RSP_Unknown, TimeTaken); break;
}
}
@ -2033,6 +2032,11 @@ void CN64System::RunRSP()
g_Reg->CheckInterrupts();
}
}
if (bShowCPUPer())
{
m_CPU_Usage.StartTimer(CPU_UsageAddr);
}
WriteTrace(TraceRSP, TraceDebug, "Done (SP Status %X)", m_Reg.SP_STATUS_REG);
}
@ -2123,6 +2127,7 @@ void CN64System::RefreshScreen()
m_FPS.DisplayViCounter(FrameRate, 0);
m_bCleanFrameBox = true;
}
if (bShowCPUPer()) { m_CPU_Usage.StopTimer(); }
}
else if (bDisplayFrameRate())
{
@ -2139,7 +2144,6 @@ void CN64System::RefreshScreen()
if (bShowCPUPer())
{
m_CPU_Usage.StopTimer();
m_CPU_Usage.ShowCPU_Usage();
m_CPU_Usage.StartTimer(CPU_UsageAddr != Timer_None ? CPU_UsageAddr : Timer_R4300);
}

View File

@ -103,7 +103,7 @@ private:
//Recompiler has access to manipulate and call functions
friend CSystemTimer;
friend CRecompiler;
friend CMipsMemoryVM;
//Used for loading and potentially executing the CPU in its own thread.

View File

@ -28,6 +28,20 @@ void CProfiling::RecordTime(PROFILE_TIMERS timer, uint32_t TimeTaken)
m_Timers[timer] += TimeTaken;
}
uint64_t CProfiling::NonCPUTime(void)
{
uint64_t TotalTime = 0;
for (int i = 0; i < Timer_Max; i++)
{
if (i == Timer_R4300)
{
continue;
}
TotalTime += m_Timers[i];
}
return TotalTime;
}
PROFILE_TIMERS CProfiling::StartTimer(PROFILE_TIMERS TimerType)
{
PROFILE_TIMERS PreviousType = StopTimer();
@ -51,6 +65,7 @@ PROFILE_TIMERS CProfiling::StopTimer()
void CProfiling::ShowCPU_Usage()
{
PROFILE_TIMERS PreviousType = StopTimer();
uint64_t TotalTime = m_Timers[Timer_R4300] + m_Timers[Timer_RSP_Dlist] + m_Timers[Timer_RSP_Alist] + m_Timers[Timer_Idel];
if (m_CurrentDisplayCount > 0)
@ -66,9 +81,13 @@ void CProfiling::ShowCPU_Usage()
m_CurrentDisplayCount = MAX_FRAMES;
g_Notify->DisplayMessage(0, stdstr_f("r4300i: %d.%02d%% GFX: %d.%02d%% Alist: %d.%02d%% Idle: %d.%02d%%",
R4300 / 100, R4300 % 100,RSP_Dlist / 100, RSP_Dlist % 100,RSP_Alist / 100, RSP_Alist % 100,Idel / 100, Idel % 100).c_str());
R4300 / 100, R4300 % 100, RSP_Dlist / 100, RSP_Dlist % 100, RSP_Alist / 100, RSP_Alist % 100, Idel / 100, Idel % 100).c_str());
ResetTimers();
if (PreviousType != Timer_None)
{
StartTimer(PreviousType);
}
}
void CProfiling::ResetTimers()

View File

@ -18,7 +18,7 @@ public:
CProfiling();
void RecordTime(PROFILE_TIMERS timer, uint32_t time);
uint64_t TimerTime(PROFILE_TIMERS timer);
uint64_t NonCPUTime(void);
//recording timing against current timer, returns the address of the timer stopped
PROFILE_TIMERS StartTimer(PROFILE_TIMERS TimerType);

View File

@ -151,7 +151,7 @@ void CRecompiler::RecompilerMain_VirtualTable()
WriteTrace(TraceRecompiler, TraceError, "failed to allocate PCCompiledFunc");
g_Notify->FatalError(MSG_MEM_ALLOC_ERROR);
}
memset(table, 0, sizeof(PCCompiledFunc) * (0x1000 >> 2));
memset(table, 0, sizeof(PCCompiledFunc)* (0x1000 >> 2));
if (g_System->bSMM_Protect())
{
WriteTrace(TraceRecompiler, TraceError, "Create Table (%X): Index = %d", table, PC >> 0xC);
@ -697,11 +697,21 @@ void CRecompiler::RecompilerMain_Lookup_validate_TLB()
if (bRecordExecutionTimes())
{
uint64_t PreNonCPUTime = g_System->m_CPU_Usage.NonCPUTime();
HighResTimeStamp StartTime, EndTime;
StartTime.SetToNow();
(info->Function())();
EndTime.SetToNow();
uint64_t PostNonCPUTime = g_System->m_CPU_Usage.NonCPUTime();
uint64_t TimeTaken = EndTime.GetMicroSeconds() - StartTime.GetMicroSeconds();
if (PostNonCPUTime >= PreNonCPUTime)
{
TimeTaken -= PostNonCPUTime - PreNonCPUTime;
}
else
{
TimeTaken -= PostNonCPUTime;
}
FUNCTION_PROFILE::iterator itr = m_BlockProfile.find(info->Function());
if (itr == m_BlockProfile.end())
{
@ -710,7 +720,7 @@ void CRecompiler::RecompilerMain_Lookup_validate_TLB()
std::pair<FUNCTION_PROFILE::iterator, bool> res = m_BlockProfile.insert(FUNCTION_PROFILE::value_type(info->Function(), data));
itr = res.first;
}
WriteTrace(TraceN64System, TraceNotice, "EndTime: %X StartTime: %X TimeTaken: %X", (uint32_t)EndTime.GetMicroSeconds(), (uint32_t)StartTime.GetMicroSeconds(), (uint32_t)TimeTaken);
WriteTrace(TraceN64System, TraceNotice, "EndTime: %X StartTime: %X TimeTaken: %X", (uint32_t)(EndTime.GetMicroSeconds() & 0xFFFFFFFF), (uint32_t)(StartTime.GetMicroSeconds() & 0xFFFFFFFF), (uint32_t)TimeTaken);
itr->second.TimeTaken += TimeTaken;
}
else
@ -1093,13 +1103,13 @@ void CRecompiler::ClearRecompCode_Virt(uint32_t Address, int length, REMOVE_REAS
}
break;
case FuncFind_PhysicalLookup:
{
uint32_t pAddr = 0;
if (g_TransVaddr->TranslateVaddr(Address, pAddr))
{
ClearRecompCode_Phys(pAddr, length, Reason);
}
}
{
uint32_t pAddr = 0;
if (g_TransVaddr->TranslateVaddr(Address, pAddr))
{
ClearRecompCode_Phys(pAddr, length, Reason);
}
}
break;
default:
g_Notify->BreakPoint(__FILE__, __LINE__);
@ -1147,4 +1157,4 @@ void CRecompiler::DumpFunctionTimes()
void CRecompiler::ResetFunctionTimes()
{
m_BlockProfile.clear();
}
}

View File

@ -18,11 +18,11 @@ public:
CDebugSettings();
virtual ~CDebugSettings();
static inline bool bHaveDebugger(void) { return m_bHaveDebugger; }
static inline bool bLogX86Code(void) { return m_bLogX86Code; }
static inline bool bShowTLBMisses(void) { return m_bShowTLBMisses; }
static inline bool bShowDivByZero(void) { return m_bShowDivByZero; }
static inline bool bRecordExecutionTimes(void) { return m_RecordExecutionTimes; }
static inline bool bHaveDebugger(void) { return m_bHaveDebugger; }
static inline bool bLogX86Code(void) { return m_bLogX86Code; }
static inline bool bShowTLBMisses(void) { return m_bShowTLBMisses; }
static inline bool bShowDivByZero(void) { return m_bShowDivByZero; }
inline static bool bRecordExecutionTimes(void) { return m_RecordExecutionTimes; }
private:
static void StaticRefreshSettings(CDebugSettings * _this)

View File

@ -14,7 +14,6 @@
int32_t CN64SystemSettings::m_RefCount = 0;
bool CN64SystemSettings::m_bShowCPUPer;
bool CN64SystemSettings::m_bProfiling;
bool CN64SystemSettings::m_bBasicMode;
bool CN64SystemSettings::m_bLimitFPS;
bool CN64SystemSettings::m_bShowDListAListCount;
@ -28,10 +27,7 @@ CN64SystemSettings::CN64SystemSettings()
g_Settings->RegisterChangeCB(UserInterface_BasicMode, NULL, RefreshSettings);
g_Settings->RegisterChangeCB(UserInterface_ShowCPUPer, NULL, RefreshSettings);
g_Settings->RegisterChangeCB(UserInterface_DisplayFrameRate, NULL, RefreshSettings);
g_Settings->RegisterChangeCB(Debugger_ProfileCode, NULL, RefreshSettings);
g_Settings->RegisterChangeCB(Debugger_ShowDListAListCount, NULL, RefreshSettings);
g_Settings->RegisterChangeCB(GameRunning_LimitFPS, NULL, RefreshSettings);
RefreshSettings(NULL);
@ -46,10 +42,7 @@ CN64SystemSettings::~CN64SystemSettings()
g_Settings->UnregisterChangeCB(UserInterface_BasicMode, NULL, RefreshSettings);
g_Settings->UnregisterChangeCB(UserInterface_DisplayFrameRate, NULL, RefreshSettings);
g_Settings->UnregisterChangeCB(UserInterface_ShowCPUPer, NULL, RefreshSettings);
g_Settings->UnregisterChangeCB(Debugger_ProfileCode, NULL, RefreshSettings);
g_Settings->UnregisterChangeCB(Debugger_ShowDListAListCount, NULL, RefreshSettings);
g_Settings->UnregisterChangeCB(GameRunning_LimitFPS, NULL, RefreshSettings);
}
}
@ -58,9 +51,7 @@ void CN64SystemSettings::RefreshSettings(void *)
{
m_bBasicMode = g_Settings->LoadBool(UserInterface_BasicMode);
m_bDisplayFrameRate = g_Settings->LoadBool(UserInterface_DisplayFrameRate);
m_bShowCPUPer = g_Settings->LoadBool(UserInterface_ShowCPUPer);
m_bProfiling = g_Settings->LoadBool(Debugger_ProfileCode);
m_bShowDListAListCount = g_Settings->LoadBool(Debugger_ShowDListAListCount);
m_bLimitFPS = g_Settings->LoadBool(GameRunning_LimitFPS);
}

View File

@ -16,22 +16,20 @@ protected:
CN64SystemSettings();
virtual ~CN64SystemSettings();
inline static bool bBasicMode(void) { return m_bBasicMode; }
inline static bool bDisplayFrameRate(void) { return m_bDisplayFrameRate; }
inline static bool bShowCPUPer(void) { return m_bShowCPUPer; }
inline static bool bProfiling(void) { return m_bProfiling; }
inline static bool bShowDListAListCount(void) { return m_bShowDListAListCount; }
inline static bool bLimitFPS(void) { return m_bLimitFPS; }
inline static bool bBasicMode(void) { return m_bBasicMode; }
inline static bool bDisplayFrameRate(void) { return m_bDisplayFrameRate; }
inline static bool bShowCPUPer(void) { return m_bShowCPUPer; }
inline static bool bShowDListAListCount(void) { return m_bShowDListAListCount; }
inline static bool bLimitFPS(void) { return m_bLimitFPS; }
private:
static void RefreshSettings(void *);
static bool m_bShowCPUPer;
static bool m_bProfiling;
static bool m_bBasicMode;
static bool m_bLimitFPS;
static bool m_bShowDListAListCount;
static bool m_bDisplayFrameRate;
static bool m_bShowCPUPer;
static bool m_bBasicMode;
static bool m_bLimitFPS;
static bool m_bShowDListAListCount;
static bool m_bDisplayFrameRate;
static int32_t m_RefCount;
};

View File

@ -11,10 +11,9 @@
#include "stdafx.h"
#include "RecompilerSettings.h"
int CRecompilerSettings::m_RefCount = 0;
int CRecompilerSettings::m_RefCount = 0;
bool CRecompilerSettings::m_bShowRecompMemSize;
bool CRecompilerSettings::m_bProfiling;
bool CRecompilerSettings::m_bShowRecompMemSize;
CRecompilerSettings::CRecompilerSettings()
{
@ -22,7 +21,6 @@ CRecompilerSettings::CRecompilerSettings()
if (m_RefCount == 1)
{
g_Settings->RegisterChangeCB(Debugger_ShowRecompMemSize, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->RegisterChangeCB(Debugger_ProfileCode, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
RefreshSettings();
}
@ -34,12 +32,10 @@ CRecompilerSettings::~CRecompilerSettings()
if (m_RefCount == 0)
{
g_Settings->UnregisterChangeCB(Debugger_ShowRecompMemSize, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->UnregisterChangeCB(Debugger_ProfileCode, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
}
}
void CRecompilerSettings::RefreshSettings()
{
m_bShowRecompMemSize = g_Settings->LoadBool(Debugger_ShowRecompMemSize);
m_bProfiling = g_Settings->LoadBool(Debugger_ProfileCode);
}

View File

@ -18,9 +18,7 @@ public:
CRecompilerSettings();
virtual ~CRecompilerSettings();
static bool bShowRecompMemSize(void) { return m_bShowRecompMemSize; }
static bool bProfiling(void) { return m_bProfiling; }
static inline bool bShowRecompMemSize(void) { return m_bShowRecompMemSize; }
private:
static void StaticRefreshSettings(CRecompilerSettings * _this)
@ -32,7 +30,6 @@ private:
//Settings that can be changed on the fly
static bool m_bShowRecompMemSize;
static bool m_bProfiling;
static int32_t m_RefCount;
};

View File

@ -214,7 +214,6 @@ enum SettingID
Debugger_ShowPifErrors,
Debugger_ShowDivByZero,
Debugger_GenerateLogFiles,
Debugger_ProfileCode,
Debugger_DisableGameFixes,
Debugger_AppLogLevel,
Debugger_AppLogFlush,

View File

@ -37,7 +37,7 @@
CSettings * g_Settings = NULL;
CSettings::CSettings() :
m_NextAutoSettingId(0x200000)
m_NextAutoSettingId(0x200000)
{
}
@ -312,7 +312,6 @@ void CSettings::AddHowToHandleSetting(const char * BaseDirectory)
AddHandler(Debugger_RecordExecutionTimes, new CSettingTypeApplication("Debugger", "Record Execution Times", false));
AddHandler(Debugger_DebugLanguage, new CSettingTypeApplication("Debugger", "Debug Language", false));
AddHandler(Debugger_ShowDivByZero, new CSettingTypeApplication("Debugger", "Show Div by zero", false));
AddHandler(Debugger_ProfileCode, new CSettingTypeApplication("Debugger", "Profile Code", (uint32_t)false));
AddHandler(Debugger_AppLogFlush, new CSettingTypeApplication("Logging", "Log Auto Flush", (uint32_t)false));
AddHandler(Debugger_GenerateLogFiles, new CSettingTypeApplication("Debugger", "Generate Log Files", false));

View File

@ -6,9 +6,9 @@
#include <commdlg.h>
CMainMenu::CMainMenu(CMainGui * hMainWindow) :
CBaseMenu(),
m_ResetAccelerators(true),
m_Gui(hMainWindow)
CBaseMenu(),
m_ResetAccelerators(true),
m_Gui(hMainWindow)
{
ResetMenu();
@ -20,7 +20,7 @@ CMainMenu::CMainMenu(CMainGui * hMainWindow) :
m_ChangeUISettingList.push_back(UserInterface_AlwaysOnTop);
m_ChangeSettingList.push_back(UserInterface_ShowCPUPer);
m_ChangeSettingList.push_back(Logging_GenerateLog);
m_ChangeSettingList.push_back(Debugger_ProfileCode);
m_ChangeSettingList.push_back(Debugger_RecordExecutionTimes);
m_ChangeSettingList.push_back(Debugger_ShowTLBMisses);
m_ChangeSettingList.push_back(Debugger_ShowUnhandledMemory);
m_ChangeSettingList.push_back(Debugger_ShowPifErrors);
@ -479,10 +479,10 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI
break;
case ID_OPTIONS_SETTINGS: OnSettings(hWnd); break;
case ID_PROFILE_PROFILE:
g_Settings->SaveBool(Debugger_ProfileCode, !g_Settings->LoadBool(Debugger_ProfileCode));
g_BaseSystem->ExternalEvent(SysEvent_Profile_StartStop);
g_Settings->SaveBool(Debugger_RecordExecutionTimes, !g_Settings->LoadBool(Debugger_RecordExecutionTimes));
g_BaseSystem->ExternalEvent(SysEvent_ResetFunctionTimes);
break;
case ID_PROFILE_RESETCOUNTER: g_BaseSystem->ExternalEvent(SysEvent_Profile_ResetLogs); break;
case ID_PROFILE_RESETCOUNTER: g_BaseSystem->ExternalEvent(SysEvent_ResetFunctionTimes); break;
case ID_PROFILE_GENERATELOG: g_BaseSystem->ExternalEvent(SysEvent_DumpFunctionTimes); break;
case ID_DEBUG_SHOW_TLB_MISSES:
g_Settings->SaveBool(Debugger_ShowTLBMisses, !g_Settings->LoadBool(Debugger_ShowTLBMisses));
@ -996,8 +996,8 @@ void CMainMenu::FillOutMenu(HMENU hMenu)
MenuItemList DebugProfileMenu;
if (bHaveDebugger())
{
Item.Reset(ID_PROFILE_PROFILE, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Profile Code");
if (g_Settings->LoadBool(Debugger_ProfileCode)) { Item.SetItemTicked(true); }
Item.Reset(ID_PROFILE_PROFILE, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Record Execution Times");
if (g_Settings->LoadBool(Debugger_RecordExecutionTimes)) { Item.SetItemTicked(true); }
DebugProfileMenu.push_back(Item);
Item.Reset(ID_PROFILE_RESETCOUNTER, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Reset Counters");
if (!CPURunning) { Item.SetItemEnabled(false); }