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;