Rewrote the profiler to make it simpler to use and more accurate.

git-svn-id: http://svn.purei.org/purei/trunk@1051 b36208d7-6611-0410-8bec-b1987f11c4a2
This commit is contained in:
jpd002 2012-12-23 21:35:04 +00:00
parent c56c249ff4
commit a5aaa0bea0
9 changed files with 151 additions and 208 deletions

View File

@ -445,7 +445,7 @@ void CDMAC::SetRegister(uint32 nAddress, uint32 nData)
{
#ifdef PROFILE
CProfiler::GetInstance().BeginZone(PROFILE_DMACZONE);
CProfilerZone profilerZone(PROFILE_DMACZONE);
#endif
switch(nAddress)
@ -839,10 +839,6 @@ void CDMAC::SetRegister(uint32 nAddress, uint32 nData)
DisassembleSet(nAddress, nData);
#endif
#ifdef PROFILE
CProfiler::GetInstance().EndZone();
#endif
}
void CDMAC::LoadState(CZipArchiveReader& archive)

View File

@ -6,7 +6,7 @@
#include "Profiler.h"
#include "Log.h"
#define LOG_NAME ("gif")
#define LOG_NAME ("gif")
#ifdef PROFILE
#define PROFILE_GIFZONE "GIF"
@ -208,7 +208,7 @@ uint32 CGIF::ProcessPacket(uint8* pMemory, uint32 nAddress, uint32 nEnd)
static CGSHandler::RegisterWriteList writeList;
#ifdef PROFILE
CProfiler::GetInstance().BeginZone(PROFILE_GIFZONE);
CProfilerZone profilerZone(PROFILE_GIFZONE);
#endif
#ifdef _DEBUG
@ -273,10 +273,6 @@ uint32 CGIF::ProcessPacket(uint8* pMemory, uint32 nAddress, uint32 nEnd)
}
}
#ifdef PROFILE
CProfiler::GetInstance().EndZone();
#endif
if(m_gs != NULL && writeList.size() != 0)
{
CGSHandler::RegisterWrite* writeListBuffer = new CGSHandler::RegisterWrite[writeList.size()];

View File

@ -2314,9 +2314,8 @@ void CPS2OS::sc_GetMemorySize()
void CPS2OS::SysCallHandler()
{
#ifdef PROFILE
CProfiler::GetInstance().EndZone();
CProfilerZone profilerZone(PROFILE_OTHERZONE);
#endif
uint32 searchAddress = m_ee.m_State.nCOP0[CCOP_SCU::EPC];
@ -2358,10 +2357,6 @@ void CPS2OS::SysCallHandler()
}
}
#ifdef PROFILE
CProfiler::GetInstance().BeginZone(PROFILE_EEZONE);
#endif
m_ee.m_State.nHasException = 0;
}

View File

@ -66,6 +66,11 @@
#define VPU_LOG_BASE "./vpu_logs/"
#ifdef PROFILE
#define PROFILE_EEZONE "EE"
#define PROFILE_IOPZONE "IOP"
#endif
namespace filesystem = boost::filesystem;
CPS2VM::CPS2VM()
@ -84,8 +89,8 @@ CPS2VM::CPS2VM()
, m_executor(m_EE, 0x20000000)
, m_nStatus(PAUSED)
, m_nEnd(false)
, m_gs(NULL)
, m_pad(NULL)
, m_gs(NULL)
, m_pad(NULL)
, m_singleStepEe(false)
, m_singleStepIop(false)
, m_singleStepVu0(false)
@ -97,7 +102,7 @@ CPS2VM::CPS2VM()
, m_spuUpdateTicks(SPU_UPDATE_TICKS)
, m_pCDROM0(NULL)
, m_dmac(m_ram, m_spr, m_pVUMem0, m_EE)
, m_gif(m_gs, m_ram, m_spr)
, m_gif(m_gs, m_ram, m_spr)
, m_sif(m_dmac, m_ram, m_iop.m_ram)
, m_vif(m_gif, m_ram, m_spr, CVIF::VPUINIT(m_pMicroMem0, m_pVUMem0, &m_VU0), CVIF::VPUINIT(m_pMicroMem1, m_pVUMem1, &m_VU1))
, m_intc(m_dmac)
@ -135,7 +140,7 @@ CPS2VM::CPS2VM()
CAppConfig::GetInstance().RegisterPreferenceInteger(PREF_PS2_FRAMESKIP, PREF_PS2_FRAMESKIP_DEFAULT);
m_iopOs = std::make_shared<CIopBios>(m_iop.m_cpu, m_iop.m_ram, PS2::IOP_RAM_SIZE);
m_os = new CPS2OS(m_EE, m_ram, m_bios, m_gs, m_sif, *m_iopOs);
m_os = new CPS2OS(m_EE, m_ram, m_bios, m_gs, m_sif, *m_iopOs);
m_os->OnRequestInstructionCacheFlush.connect(boost::bind(&CPS2VM::FlushInstructionCache, this));
m_os->OnRequestLoadExecutable.connect(boost::bind(&CPS2VM::ReloadExecutable, this, _1, _2));
}
@ -156,30 +161,30 @@ CPS2VM::~CPS2VM()
void CPS2VM::CreateGSHandler(const CGSHandler::FactoryFunction& factoryFunction)
{
if(m_gs != NULL) return;
if(m_gs != NULL) return;
m_mailBox.SendCall(bind(&CPS2VM::CreateGsImpl, this, factoryFunction), true);
}
CGSHandler* CPS2VM::GetGSHandler()
{
return m_gs;
return m_gs;
}
void CPS2VM::DestroyGSHandler()
{
if(m_gs == NULL) return;
if(m_gs == NULL) return;
m_mailBox.SendCall(std::bind(&CPS2VM::DestroyGsImpl, this), true);
}
void CPS2VM::CreatePadHandler(const CPadHandler::FactoryFunction& factoryFunction)
{
if(m_pad != NULL) return;
if(m_pad != NULL) return;
m_mailBox.SendCall(std::bind(&CPS2VM::CreatePadHandlerImpl, this, factoryFunction), true);
}
void CPS2VM::DestroyPadHandler()
{
if(m_pad == NULL) return;
if(m_pad == NULL) return;
m_mailBox.SendCall(std::bind(&CPS2VM::DestroyPadHandlerImpl, this), true);
}
@ -303,7 +308,7 @@ void CPS2VM::LoadDebugTags(const char* packageName)
{
std::string packagePath = MakeDebugTagsPackagePath(packageName);
Framework::CStdStream stream(packagePath.c_str(), "rb");
boost::scoped_ptr<Framework::Xml::CNode> document(Framework::Xml::CParser::ParseDocument(stream));
boost::scoped_ptr<Framework::Xml::CNode> document(Framework::Xml::CParser::ParseDocument(stream));
Framework::Xml::CNode* tagsNode = document->Select(TAGS_SECTION_TAGS);
if(!tagsNode) return;
m_EE.m_Functions.Unserialize(tagsNode, TAGS_SECTION_EE_FUNCTIONS);
@ -500,9 +505,9 @@ void CPS2VM::ResetVM()
m_intc.Reset();
m_timer.Reset();
if(m_gs != NULL)
if(m_gs != NULL)
{
m_gs->Reset();
m_gs->Reset();
}
m_os->Initialize();
@ -553,7 +558,7 @@ void CPS2VM::DestroyVM()
void CPS2VM::SaveVMState(const char* sPath, unsigned int& result)
{
if(m_gs == NULL)
if(m_gs == NULL)
{
printf("PS2VM: GS Handler was not instancied. Cannot save state.\r\n");
result = 1;
@ -576,7 +581,7 @@ void CPS2VM::SaveVMState(const char* sPath, unsigned int& result)
archive.InsertFile(new CMemoryStateFile(STATE_MICROMEM1, m_pMicroMem1, PS2::MICROMEM1SIZE));
m_iop.SaveState(archive);
m_gs->SaveState(archive);
m_gs->SaveState(archive);
m_dmac.SaveState(archive);
m_intc.SaveState(archive);
m_sif.SaveState(archive);
@ -599,7 +604,7 @@ void CPS2VM::SaveVMState(const char* sPath, unsigned int& result)
void CPS2VM::LoadVMState(const char* sPath, unsigned int& result)
{
if(m_gs == NULL)
if(m_gs == NULL)
{
printf("PS2VM: GS Handler was not instancied. Cannot load state.\r\n");
result = 1;
@ -624,7 +629,7 @@ void CPS2VM::LoadVMState(const char* sPath, unsigned int& result)
archive.BeginReadFile(STATE_MICROMEM1 )->Read(m_pMicroMem1, PS2::MICROMEM1SIZE);
m_iop.LoadState(archive);
m_gs->LoadState(archive);
m_gs->LoadState(archive);
m_dmac.LoadState(archive);
m_intc.LoadState(archive);
m_sif.LoadState(archive);
@ -669,7 +674,7 @@ void CPS2VM::ResumeImpl()
void CPS2VM::DestroyImpl()
{
DELETEPTR(m_gs);
DELETEPTR(m_gs);
m_nEnd = true;
}
@ -682,28 +687,28 @@ void CPS2VM::CreateGsImpl(const CGSHandler::FactoryFunction& factoryFunction)
void CPS2VM::DestroyGsImpl()
{
m_gs->Release();
DELETEPTR(m_gs);
m_gs->Release();
DELETEPTR(m_gs);
}
void CPS2VM::CreatePadHandlerImpl(const CPadHandler::FactoryFunction& factoryFunction)
{
m_pad = factoryFunction();
m_pad = factoryFunction();
RegisterModulesInPadHandler();
}
void CPS2VM::DestroyPadHandlerImpl()
{
DELETEPTR(m_pad);
DELETEPTR(m_pad);
}
void CPS2VM::OnGsNewFrame()
{
m_frameNumber++;
bool drawFrame = (m_frameSkip == 0) ? true : (m_frameNumber % (m_frameSkip + 1)) == 0;
if(m_gs != NULL)
if(m_gs != NULL)
{
m_gs->SetEnabled(drawFrame);
m_gs->SetEnabled(drawFrame);
}
m_vif.SetEnabled(drawFrame);
}
@ -817,10 +822,10 @@ void CPS2VM::LoadBIOS()
void CPS2VM::RegisterModulesInPadHandler()
{
if(m_pad == NULL) return;
if(m_pad == NULL) return;
m_pad->RemoveAllListeners();
m_pad->InsertListener(m_iopOs->GetPadman());
m_pad->RemoveAllListeners();
m_pad->InsertListener(m_iopOs->GetPadman());
m_pad->InsertListener(&m_iop.m_sio2);
}
@ -856,7 +861,7 @@ void CPS2VM::FillFakeIopRam()
uint32 CPS2VM::IOPortReadHandler(uint32 nAddress)
{
#ifdef PROFILE
CProfiler::GetInstance().EndZone();
CProfilerZone profilerZone(PROFILE_OTHERZONE);
#endif
uint32 nReturn = 0;
@ -882,9 +887,9 @@ uint32 CPS2VM::IOPortReadHandler(uint32 nAddress)
}
else if(nAddress >= 0x12000000 && nAddress <= 0x1200108C)
{
if(m_gs != NULL)
if(m_gs != NULL)
{
nReturn = m_gs->ReadPrivRegister(nAddress);
nReturn = m_gs->ReadPrivRegister(nAddress);
}
}
else
@ -892,17 +897,13 @@ uint32 CPS2VM::IOPortReadHandler(uint32 nAddress)
printf("PS2VM: Read an unhandled IO port (0x%0.8X).\r\n", nAddress);
}
#ifdef PROFILE
CProfiler::GetInstance().BeginZone(PROFILE_EEZONE);
#endif
return nReturn;
}
uint32 CPS2VM::IOPortWriteHandler(uint32 nAddress, uint32 nData)
{
#ifdef PROFILE
CProfiler::GetInstance().EndZone();
CProfilerZone profilerZone(PROFILE_OTHERZONE);
#endif
if(nAddress >= 0x10000000 && nAddress <= 0x1000183F)
@ -937,9 +938,9 @@ uint32 CPS2VM::IOPortWriteHandler(uint32 nAddress, uint32 nData)
}
else if(nAddress >= 0x12000000 && nAddress <= 0x1200108C)
{
if(m_gs != NULL)
if(m_gs != NULL)
{
m_gs->WritePrivRegister(nAddress, nData);
m_gs->WritePrivRegister(nAddress, nData);
}
}
else
@ -947,10 +948,6 @@ uint32 CPS2VM::IOPortWriteHandler(uint32 nAddress, uint32 nData)
printf("PS2VM: Wrote to an unhandled IO port (0x%0.8X, 0x%0.8X, PC: 0x%0.8X).\r\n", nAddress, nData, m_EE.m_State.nPC);
}
#ifdef PROFILE
CProfiler::GetInstance().BeginZone(PROFILE_EEZONE);
#endif
return 0;
}
@ -1123,6 +1120,9 @@ bool CPS2VM::IsEeIdle() const
void CPS2VM::EmuThread()
{
#ifdef PROFILE
CProfiler::GetInstance().SetWorkThread();
#endif
while(1)
{
while(m_mailBox.IsPending())
@ -1178,14 +1178,14 @@ void CPS2VM::EmuThread()
m_intc.AssertLine(CINTC::INTC_LINE_VBLANK_START);
m_iop.NotifyVBlankStart();
if(m_gs != NULL)
if(m_gs != NULL)
{
m_gs->SetVBlank();
m_gs->SetVBlank();
}
if(m_pad != NULL)
if(m_pad != NULL)
{
m_pad->Update(m_ram);
m_pad->Update(m_ram);
}
}
else
@ -1193,9 +1193,9 @@ void CPS2VM::EmuThread()
m_vblankTicks += ONSCREEN_TICKS;
m_intc.AssertLine(CINTC::INTC_LINE_VBLANK_END);
m_iop.NotifyVBlankEnd();
if(m_gs != NULL)
if(m_gs != NULL)
{
m_gs->ResetVBlank();
m_gs->ResetVBlank();
}
}
}
@ -1206,10 +1206,21 @@ void CPS2VM::EmuThread()
m_eeExecutionTicks += tickStep;
m_iopExecutionTicks += tickStep / 8;
m_eeExecutionTicks -= ExecuteEe(m_singleStepEe ? 1 : m_eeExecutionTicks);
{
#ifdef PROFILE
CProfilerZone profilerZone(PROFILE_EEZONE);
#endif
m_eeExecutionTicks -= ExecuteEe(m_singleStepEe ? 1 : m_eeExecutionTicks);
}
unsigned int iopExecuted = m_iop.ExecuteCpu(m_singleStepIop ? 1 : m_iopExecutionTicks);
m_iopExecutionTicks -= iopExecuted;
unsigned int iopExecuted = 0;
{
#ifdef PROFILE
CProfilerZone profilerZone(PROFILE_IOPZONE);
#endif
iopExecuted = m_iop.ExecuteCpu(m_singleStepIop ? 1 : m_iopExecutionTicks);
m_iopExecutionTicks -= iopExecuted;
}
int executed = tickStep;
if(IsEeIdle() && m_iop.IsCpuIdle())

View File

@ -41,10 +41,6 @@ enum PS2VM_MSG
PS2VM_MSG_RESET,
};
#ifdef PROFILE
#define PROFILE_EEZONE "EE"
#endif
#define PREF_PS2_HOST_DIRECTORY ("ps2.host.directory")
#define PREF_PS2_MC0_DIRECTORY ("ps2.mc0.directory")
#define PREF_PS2_MC1_DIRECTORY ("ps2.mc1.directory")

View File

@ -1,12 +1,8 @@
#include "Profiler.h"
using namespace std;
using namespace boost;
#ifdef PROFILE
CProfiler::CProfiler() :
m_OtherZone("Other")
CProfiler::CProfiler()
{
}
@ -18,131 +14,94 @@ CProfiler::~CProfiler()
void CProfiler::BeginIteration()
{
m_nCurrentTime = clock();
Reset();
m_currentTime = clock();
}
void CProfiler::EndIteration()
{
mutex::scoped_lock Lock(m_Mutex);
m_Stats.clear();
for(ZoneMap::const_iterator itZone = m_Zones.begin();
itZone != m_Zones.end();
itZone++)
{
m_Stats.push_back((*itZone));
}
m_Stats.push_back(m_OtherZone);
std::lock_guard<std::mutex> mutexLock(m_mutex);
}
void CProfiler::BeginZone(const char* sName)
void CProfiler::BeginZone(const char* name)
{
clock_t nTime;
nTime = clock();
assert(std::this_thread::get_id() == m_workThreadId);
clock_t nTime = clock();
{
mutex::scoped_lock Lock(m_Mutex);
CZone& Zone = GetCurrentZone();
Zone.AddTime(nTime - m_nCurrentTime);
ZoneMap::iterator itZone;
itZone = m_Zones.find(sName);
if(itZone == m_Zones.end())
{
string sZoneName(sName);
m_Zones.insert(sZoneName, new CZone(sName));
itZone = m_Zones.find(sName);
}
m_ZoneStack.push_back(&(*itZone));
std::lock_guard<std::mutex> mutexLock(m_mutex);
AddTimeToCurrentZone(nTime - m_currentTime);
m_zoneStack.push(name);
}
m_nCurrentTime = clock();
m_currentTime = clock();
}
void CProfiler::EndZone()
{
clock_t nTime;
nTime = clock();
assert(std::this_thread::get_id() == m_workThreadId);
clock_t nTime = clock();
{
mutex::scoped_lock Lock(m_Mutex);
std::lock_guard<std::mutex> mutexLock(m_mutex);
if(m_ZoneStack.size() == 0)
if(m_zoneStack.size() == 0)
{
throw exception("Currently not inside any zone.");
throw std::runtime_error("Currently not inside any zone.");
}
CZone& Zone = GetCurrentZone();
Zone.AddTime(nTime - m_nCurrentTime);
m_ZoneStack.pop_back();
AddTimeToCurrentZone(nTime - m_currentTime);
m_zoneStack.pop();
}
m_nCurrentTime = clock();
m_currentTime = clock();
}
CProfiler::ZoneList CProfiler::GetStats()
CProfiler::ZoneMap CProfiler::GetStats()
{
mutex::scoped_lock Lock(m_Mutex);
return m_Stats;
std::lock_guard<std::mutex> mutexLock(m_mutex);
return m_zones;
}
void CProfiler::Reset()
{
mutex::scoped_lock Lock(m_Mutex);
std::lock_guard<std::mutex> mutexLock(m_mutex);
std::for_each(std::begin(m_zones), std::end(m_zones), [] (ZoneMap::value_type& zonePair) { zonePair.second = 0; });
}
for(ZoneMap::iterator itZone = m_Zones.begin();
itZone != m_Zones.end();
itZone++)
void CProfiler::SetWorkThread()
{
#ifdef _DEBUG
m_workThreadId = std::this_thread::get_id();
#endif
}
void CProfiler::AddTimeToCurrentZone(clock_t time)
{
std::string currentZoneName = (m_zoneStack.size() == 0) ? PROFILE_OTHERZONE : m_zoneStack.top();
auto zoneIterator = m_zones.find(currentZoneName);
if(zoneIterator == std::end(m_zones))
{
(*itZone).Reset();
m_zones.insert(ZoneMap::value_type(currentZoneName, 0));
zoneIterator = m_zones.find(currentZoneName);
}
zoneIterator->second += time;
}
CProfiler::CZone& CProfiler::GetCurrentZone()
//////////////////////////////////////////////////////////////////////////
//CProfilerZone
CProfilerZone::CProfilerZone(const char* name)
: m_name(name)
{
if(m_ZoneStack.size() == 0)
{
return m_OtherZone;
}
else
{
return **(m_ZoneStack.rbegin());
}
CProfiler::GetInstance().BeginZone(name);
}
CProfiler::CZone::CZone(const char* sName)
CProfilerZone::~CProfilerZone()
{
m_sName = sName;
m_nTime = 0;
}
void CProfiler::CZone::AddTime(clock_t nTime)
{
m_nTime += nTime;
}
const char* CProfiler::CZone::GetName() const
{
return m_sName.c_str();
}
clock_t CProfiler::CZone::GetTime() const
{
return m_nTime;
}
void CProfiler::CZone::Reset()
{
m_nTime = 0;
CProfiler::GetInstance().EndZone();
}
#endif

View File

@ -1,60 +1,61 @@
#ifndef _PROFILER_H_
#define _PROFILER_H_
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/thread.hpp>
#include <string>
#include <list>
#include <ctime>
#include <map>
#include <stack>
#include <thread>
#include "Singleton.h"
#ifdef PROFILE
#define PROFILE_OTHERZONE "Other"
class CProfiler : public CSingleton<CProfiler>
{
public:
typedef std::map<std::string, clock_t> ZoneMap;
friend CSingleton;
class CZone
{
public:
CZone(const char*);
void AddTime(clock_t);
const char* GetName() const;
clock_t GetTime() const;
void Reset();
private:
std::string m_sName;
clock_t m_nTime;
};
typedef std::list<CZone> ZoneList;
void BeginIteration();
void EndIteration();
void BeginZone(const char*);
void EndZone();
ZoneList GetStats();
ZoneMap GetStats();
void Reset();
void SetWorkThread();
private:
typedef std::stack<std::string> ZoneStack;
CProfiler();
virtual ~CProfiler();
CZone& GetCurrentZone();
void AddTimeToCurrentZone(clock_t);
typedef boost::ptr_map<std::string, CZone> ZoneMap;
typedef std::list<CZone*> ZoneStack;
std::mutex m_mutex;
clock_t m_currentTime;
ZoneMap m_zones;
ZoneStack m_zoneStack;
#ifdef _DEBUG
std::thread::id m_workThreadId;
#endif
};
boost::mutex m_Mutex;
CZone m_OtherZone;
clock_t m_nCurrentTime;
ZoneMap m_Zones;
ZoneStack m_ZoneStack;
ZoneList m_Stats;
class CProfilerZone
{
public:
CProfilerZone(const char*);
~CProfilerZone();
private:
const char* m_name;
};
#endif

View File

@ -124,11 +124,6 @@ uint32 CSIF::ReceiveDMA5(uint32 srcAddress, uint32 size, uint32 unused, bool isT
uint32 CSIF::ReceiveDMA6(uint32 nSrcAddr, uint32 nSize, uint32 nDstAddr, bool isTagIncluded)
{
#ifdef PROFILE
CProfiler::GetInstance().BeginZone(PROFILE_SIFZONE);
#endif
assert(!isTagIncluded);
//Humm, this is kinda odd, but it ors the address with 0x20000000
@ -139,10 +134,6 @@ uint32 CSIF::ReceiveDMA6(uint32 nSrcAddr, uint32 nSize, uint32 nDstAddr, bool is
//This should be the arguments for the call command
//Just save the source address for later use
m_nDataAddr = nSrcAddr;
#ifdef PROFILE
CProfiler::GetInstance().EndZone();
#endif
return nSize;
}
else if(nDstAddr == CMD_RECVADDR)
@ -190,10 +181,6 @@ uint32 CSIF::ReceiveDMA6(uint32 nSrcAddr, uint32 nSize, uint32 nDstAddr, bool is
break;
}
#ifdef PROFILE
CProfiler::GetInstance().EndZone();
#endif
return nSize;
}
else

View File

@ -118,7 +118,7 @@ uint32 CVIF::ProcessDMAPacket(unsigned int vpuNumber, uint32 address, uint32 qwc
#endif
#ifdef PROFILE
CProfiler::GetInstance().BeginZone(PROFILE_VIFZONE);
CProfilerZone profilerZone(PROFILE_VIFZONE);
#endif
m_stream[vpuNumber]->SetDmaParams(address, qwc * 0x10);
@ -129,10 +129,6 @@ uint32 CVIF::ProcessDMAPacket(unsigned int vpuNumber, uint32 address, uint32 qwc
m_pVPU[vpuNumber]->ProcessPacket(*m_stream[vpuNumber]);
#ifdef PROFILE
CProfiler::GetInstance().EndZone();
#endif
uint32 remainingSize = m_stream[vpuNumber]->GetRemainingDmaTransferSize();
assert((remainingSize & 0x0F) == 0);
remainingSize /= 0x10;
@ -201,12 +197,18 @@ bool CVIF::IsVu1WaitingForProgramEnd() const
void CVIF::ExecuteVu0(bool singleStep)
{
if(!IsVu0Running()) return;
#ifdef PROFILE
CProfilerZone profilerZone(PROFILE_VIFZONE);
#endif
m_pVPU[0]->Execute(singleStep);
}
void CVIF::ExecuteVu1(bool singleStep)
{
if(!IsVu1Running()) return;
#ifdef PROFILE
CProfilerZone profilerZone(PROFILE_VIFZONE);
#endif
m_pVPU[1]->Execute(singleStep);
}