JIT profiler: in block performance counter.

MemoryView: raw memory display.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@522 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
memberTwo.mb2 2008-09-13 20:58:24 +00:00
parent bec80af7d2
commit 0ba3948c42
9 changed files with 120 additions and 18 deletions

View File

@ -9,6 +9,7 @@ protected:
virtual ~DebugInterface() {}
public:
virtual const char *disasm(unsigned int /*address*/) {return "NODEBUGGER";}
virtual const char *getRawMemoryString(unsigned int /*address*/){return "NODEBUGGER";}
virtual int getInstructionSize(int /*instruction*/) {return 1;}
virtual bool isAlive() {return true;}

View File

@ -42,6 +42,25 @@ const char *PPCDebugInterface::disasm(unsigned int address)
return tmp;
}
const char *PPCDebugInterface::getRawMemoryString(unsigned int address)
{
if (Core::GetState() != Core::CORE_UNINITIALIZED)
{
if (address < 0xE0000000)
{
static char str[256] ={0};
if (sprintf(str,"%08X",readMemory(address))!=8) {
PanicAlert("getRawMemoryString -> WTF! ( as read somewhere;) )");
return ":(";
}
return str;
}
return "No RAM";
}
static const char tmp[] = "<unknown>";
return tmp;
}
unsigned int PPCDebugInterface::readMemory(unsigned int address)
{
return Memory::ReadUnchecked_U32(address);

View File

@ -12,6 +12,7 @@ class PPCDebugInterface : public DebugInterface
public:
PPCDebugInterface(){}
virtual const char *disasm(unsigned int address);
virtual const char *getRawMemoryString(unsigned int address);
virtual int getInstructionSize(int instruction) {return 4;}
virtual bool isAlive();
virtual bool isBreakpoint(unsigned int address);

View File

@ -398,6 +398,15 @@ namespace Jit64
if (Profiler::g_ProfileBlocks) {
ADD(32, M(&b.runCount), Imm8(1));
#ifdef _WIN32
b.ticCounter.QuadPart = 0;
b.ticStart.QuadPart = 0;
b.ticStop.QuadPart = 0;
#else
//TODO
#endif
// get start tic
PROFILER_QUERY_PERFORMACE_COUNTER(&b.ticStart);
}
//Start up the register allocators
@ -416,8 +425,18 @@ namespace Jit64
js.compilerPC = ops[i].address;
js.op = &ops[i];
js.instructionNumber = i;
if (i == (int)size - 1)
if (i == (int)size - 1) {
js.isLastInstruction = true;
if (Profiler::g_ProfileBlocks) {
// CAUTION!!! push on stack regs you use, do your stuff, then pop
PROFILER_VPUSH;
// get end tic
PROFILER_QUERY_PERFORMACE_COUNTER(&b.ticStop);
// tic counter += (end tic - start tic)
PROFILER_ADD_DIFF_LARGE_INTEGER(&b.ticCounter, &b.ticStop, &b.ticStart);
PROFILER_VPOP;
}
}
// const GekkoOpInfo *info = GetOpInfo();
// if (js.isLastInstruction)

View File

@ -18,6 +18,9 @@
#define _JITCACHE_H
#include "../Gekko.h"
#ifdef _WIN32
#include <windows.h> // -> LARGE_INTEGER
#endif
namespace Jit64
{
@ -52,6 +55,13 @@ namespace Jit64
u32 codeSize;
u32 originalSize;
int runCount; // for profiling.
#ifdef _WIN32
// we don't really need to save start and stop
// TODO (mb2): ticStart and ticStop -> "local var" mean "in block" ... low priority ;)
LARGE_INTEGER ticStart; // for profiling - time.
LARGE_INTEGER ticStop; // for profiling - time.
LARGE_INTEGER ticCounter; // for profiling - time.
#endif
const u8 *checkedEntry;
bool invalid;
int flags;

View File

@ -30,9 +30,9 @@ bool g_ProfileInstructions;
struct BlockStat
{
BlockStat(int bn, int c) : blockNum(bn), cost(c) {}
BlockStat(int bn, u64 c) : blockNum(bn), cost(c) {}
int blockNum;
int cost;
u64 cost;
bool operator <(const BlockStat &other) const {
return cost > other.cost;
@ -43,14 +43,25 @@ void WriteProfileResults(const char *filename) {
std::vector<BlockStat> stats;
stats.reserve(Jit64::GetNumBlocks());
u64 cost_sum = 0;
#ifdef _WIN32
u64 timecost_sum = 0;
LARGE_INTEGER countsPerSec;
QueryPerformanceFrequency(&countsPerSec);
#endif
for (int i = 0; i < Jit64::GetNumBlocks(); i++)
{
const Jit64::JitBlock *block = Jit64::GetBlock(i);
int cost = (block->originalSize / 4) * block->runCount; // rough heuristic. mem instructions should cost more.
u64 cost = (block->originalSize / 4) * block->runCount; // rough heuristic. mem instructions should cost more.
#ifdef _WIN32
u64 timecost = block->ticCounter.QuadPart; // Indeed ;)
#endif
if (block->runCount >= 1) { // Todo: tweak.
stats.push_back(BlockStat(i, cost));
}
cost_sum += cost;
#ifdef _WIN32
timecost_sum += timecost;
#endif
}
sort(stats.begin(), stats.end());
@ -59,14 +70,21 @@ void WriteProfileResults(const char *filename) {
PanicAlert("failed to open %s", filename);
return;
}
fprintf(f, "Profile\n");
fprintf(f, "origAddr\tblkName\tcost\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n");
for (unsigned int i = 0; i < stats.size(); i++)
{
const Jit64::JitBlock *block = Jit64::GetBlock(stats[i].blockNum);
if (block) {
std::string name = g_symbolDB.GetDescription(block->originalAddress);
double percent = 100 * (double)stats[i].cost / (double)cost_sum;
fprintf(f, "%08x - %s - %i (%f%%)\n", block->originalAddress, name.c_str(), stats[i].cost, percent);
double percent = 100.0 * (double)stats[i].cost / (double)cost_sum;
#ifdef _WIN32
double timePercent = 100.0 * (double)block->ticCounter.QuadPart / (double)timecost_sum;
fprintf(f, "%08x\t%s\t%llu\t%llu\t%llf\t%llf\t%lf\t%i\n",
block->originalAddress, name.c_str(), stats[i].cost, block->ticCounter.QuadPart, percent, timePercent, (double)block->ticCounter.QuadPart*1000.0/(double)countsPerSec.QuadPart, block->codeSize);
#else
fprintf(f, "%08x\t%s\t%llu\t???\t%llf\t???\t???\t%i\n",
block->originalAddress, name.c_str(), stats[i].cost, /*block->ticCounter.QuadPart,*/ percent, /*timePercent, (double)block->ticCounter.QuadPart*1000.0/(double)countsPerSec.QuadPart,*/ block->codeSize);
#endif
}
}
fclose(f);

View File

@ -19,6 +19,34 @@
#ifndef _PROFILER_H
#define _PROFILER_H
#ifdef _WIN32
#define PROFILER_QUERY_PERFORMACE_COUNTER(pt) \
LEA(32, EAX, M(pt)); PUSH(EAX); \
CALL(QueryPerformanceCounter)
// TODO: r64 way
// asm write : (u64) dt += t1-t0
#define PROFILER_ADD_DIFF_LARGE_INTEGER(pdt, pt1, pt0) \
MOV(32, R(EAX), M(pt1.LowPart)); \
SUB(32, R(EAX), M(pt0.LowPart)); \
MOV(32, R(ECX), M(pt1.HighPart)); \
SBB(32, R(ECX), M(pt0.HighPart)); \
ADD(32, R(EAX), M(pdt.LowPart)); \
MOV(32, R(EDX), M(pdt.HighPart)); \
ADC(32, R(EDX), R(ECX)); \
MOV(32, M(pdt.LowPart), R(EAX)); \
MOV(32, M(pdt.HighPart), R(EDX))
#define PROFILER_VPUSH PUSH(EAX);PUSH(ECX);PUSH(EDX)
#define PROFILER_VPOP POP(EDX);POP(ECX);POP(EAX)
#else
// TODO
#define PROFILER_QUERY_PERFORMACE_COUNTER(pt)
#define PROFILER_ADD_DIFF_LARGE_INTEGER(pdt, pt1, pt0)
#define PROFILER_VPUSH
#define PROFILER_VPOP
#endif
namespace Profiler
{
extern bool g_ProfileBlocks;

View File

@ -223,8 +223,9 @@ void CMemoryView::OnErase(wxEraseEvent& event)
void CMemoryView::OnPaint(wxPaintEvent& event)
{
wxPaintDC dc(this);
int fontSize = 8;
wxRect rc = GetClientRect();
wxFont font(7, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_LIGHT);
wxFont font(fontSize, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_LIGHT);
dc.SetFont(font);
struct branch
{
@ -254,7 +255,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
dc.SetPen(nullPen);
dc.SetBrush(bgBrush);
dc.DrawRectangle(0, 0, 16, rc.height);
dc.DrawRectangle(0, 0, rc.width, 5);
dc.DrawRectangle(0, 0, rc.width, 5+8);
// TODO - clean up this freaking mess!!!!!
int i;
@ -294,6 +295,10 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
dc.SetBrush(currentBrush);
dc.SetTextForeground(_T("#600000"));
dc.DrawText(temp, 17, rowY1);
char mem[256] = {0};
strcpy(mem, debugger->getRawMemoryString(address));
dc.SetTextForeground(_T("#000080"));
dc.DrawText(wxString::FromAscii(mem), 17+fontSize*(8), rowY1);
dc.SetTextForeground(_T("#000000"));
if (debugger->isAlive())
@ -347,7 +352,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
dc.SetTextForeground(_T("#000000"));
}
dc.DrawText(wxString::FromAscii(dis2), 126, rowY1);
dc.DrawText(wxString::FromAscii(dis2), 17+fontSize*(8+8+8), rowY1);
}
if (strcmp(dis, "blr"))
@ -359,7 +364,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
dc.SetTextForeground(_T("#8000FF"));
}
dc.DrawText(wxString::FromAscii(dis), 70, rowY1);
dc.DrawText(wxString::FromAscii(dis), 17+fontSize*(8+8), rowY1);
if (desc[0] == 0)
{
@ -372,7 +377,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
//UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE);
if (strlen(desc))
{
dc.DrawText(wxString::FromAscii(desc), 235, rowY1);
dc.DrawText(wxString::FromAscii(desc), 17+fontSize*(8+8+8+30), rowY1);
}
if (debugger->isBreakpoint(address))

View File

@ -70,14 +70,15 @@ CMemoryWindow::CMemoryWindow(wxWindow* parent, wxWindowID id,
{
wxBoxSizer* sizerBig = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* sizerRight = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
// didn't see anything usefull in the left part
//wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
DebugInterface* di = new PPCDebugInterface();
sizerLeft->Add(symbols = new wxListBox(this, IDM_SYMBOLLIST, wxDefaultPosition, wxSize(90, 100), 0, NULL, wxLB_SORT), 1, wxEXPAND);
//sizerLeft->Add(symbols = new wxListBox(this, IDM_SYMBOLLIST, wxDefaultPosition, wxSize(20, 100), 0, NULL, wxLB_SORT), 1, wxEXPAND);
memview = new CMemoryView(di, this, wxID_ANY);
sizerBig->Add(sizerLeft, 2, wxEXPAND);
sizerBig->Add(memview, 5, wxEXPAND);
//sizerBig->Add(sizerLeft, 1, wxEXPAND);
sizerBig->Add(memview, 20, wxEXPAND);
sizerBig->Add(sizerRight, 0, wxEXPAND | wxALL, 3);
sizerRight->Add(buttonGo = new wxButton(this, IDM_DEBUG_GO, _T("&Go")));
sizerRight->Add(addrbox = new wxTextCtrl(this, IDM_ADDRBOX, _T("")));
@ -85,8 +86,8 @@ CMemoryWindow::CMemoryWindow(wxWindow* parent, wxWindowID id,
SetSizer(sizerBig);
sizerLeft->SetSizeHints(this);
sizerLeft->Fit(this);
//sizerLeft->SetSizeHints(this);
//sizerLeft->Fit(this);
sizerRight->SetSizeHints(this);
sizerRight->Fit(this);
sizerBig->SetSizeHints(this);