Implement JitIL profiling on linux. I also tried implementing __rdtsc using assembly and didn't really see a speed improvement so went with clock_gettime.

Also changed other gettimeofday calls to clock_gettime, which is supposedly more accurate.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6447 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Glenn Rice 2010-11-20 00:22:56 +00:00
parent d1264b3258
commit ef55177ed6
5 changed files with 56 additions and 66 deletions

View File

@ -492,15 +492,11 @@ namespace Common
if (timeout != INFINITE) if (timeout != INFINITE)
{ {
struct timeval now; struct timespec now;
gettimeofday(&now, NULL); clock_gettime(CLOCK_MONOTONIC_RAW, &now);
memset(&wait, 0, sizeof(wait)); memset(&wait, 0, sizeof(wait));
//TODO: timespec also has nanoseconds, but do we need them? wait.tv_nsec = now.tv_nsec + (timeout % 1000) * 1000000;
//as consequence, waiting is limited to seconds for now.
//the following just looks ridiculous, and probably fails for
//values 429 < ms <= 999 since it overflows the long.
//wait.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000);
wait.tv_sec = now.tv_sec + (timeout / 1000); wait.tv_sec = now.tv_sec + (timeout / 1000);
} }

View File

@ -60,8 +60,7 @@
#define INFINITE 0xffffffff #define INFINITE 0xffffffff
#endif #endif
//for gettimeofday and struct time(val|spec) //for clock_gettime and struct timespec
#include <sys/time.h>
#include <time.h> #include <time.h>
#endif #endif

View File

@ -21,8 +21,6 @@
#include <Windows.h> #include <Windows.h>
#include <mmsystem.h> #include <mmsystem.h>
#include <sys/timeb.h> #include <sys/timeb.h>
#else
#include <sys/time.h>
#endif #endif
#include "Common.h" #include "Common.h"
@ -37,9 +35,9 @@ u32 Timer::GetTimeMs()
#ifdef _WIN32 #ifdef _WIN32
return timeGetTime(); return timeGetTime();
#else #else
struct timeval t; struct timespec t;
(void)gettimeofday(&t, NULL); (void)clock_gettime(CLOCK_MONOTONIC_RAW, &t);
return((u32)(t.tv_sec * 1000 + t.tv_usec / 1000)); return ((u32)(t.tv_sec * 1000 + t.tv_nsec / 1000000));
#endif #endif
} }
@ -157,13 +155,6 @@ void Timer::RestoreResolution()
#endif #endif
} }
#ifdef __GNUC__
void _time64(u64* t)
{
*t = 0; //TODO
}
#endif
// Get the number of seconds since January 1 1970 // Get the number of seconds since January 1 1970
u64 Timer::GetTimeSinceJan1970() u64 Timer::GetTimeSinceJan1970()
{ {
@ -213,9 +204,9 @@ std::string Timer::GetTimeFormatted()
(void)::ftime(&tp); (void)::ftime(&tp);
sprintf(formattedTime, "%s:%03i", tmp, tp.millitm); sprintf(formattedTime, "%s:%03i", tmp, tp.millitm);
#else #else
struct timeval t; struct timespec t;
(void)gettimeofday(&t, NULL); (void)clock_gettime(CLOCK_REALTIME, &t);
sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_usec / 1000)); sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_nsec / 1000000));
#endif #endif
return std::string(formattedTime); return std::string(formattedTime);
@ -229,8 +220,8 @@ double Timer::GetDoubleTime()
struct timeb tp; struct timeb tp;
(void)::ftime(&tp); (void)::ftime(&tp);
#else #else
struct timeval t; struct timespec t;
(void)gettimeofday(&t, NULL); (void)clock_gettime(CLOCK_REALTIME, &t);
#endif #endif
// Get continuous timestamp // Get continuous timestamp
u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970(); u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970();
@ -246,7 +237,7 @@ double Timer::GetDoubleTime()
#ifdef _WIN32 #ifdef _WIN32
double ms = tp.millitm / 1000.0 / 1000.0; double ms = tp.millitm / 1000.0 / 1000.0;
#else #else
double ms = t.tv_usec / 1000.0 / 1000.0; double ms = t.tv_nsec / 1000000000.0;
#endif #endif
double TmpTime = Seconds + ms; double TmpTime = Seconds + ms;

View File

@ -153,24 +153,39 @@ ps_adds1
*/ */
#ifdef _WIN32
// For profiling // For profiling
// FIXME: This is currently for windows only. #include <time.h>
#ifdef _WIN32
#include <windows.h> #include <windows.h>
#include <intrin.h> #include <intrin.h>
#include <time.h> #else
namespace JitILProfiler { #include <memory>
struct Block { static inline u64 __rdtsc()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
return (ts.tv_sec * 100000000 + ts.tv_nsec);
}
#endif
namespace JitILProfiler
{
struct Block
{
u32 index; u32 index;
u64 codeHash; u64 codeHash;
u64 toalElapsed; u64 totalElapsed;
u64 numberOfCalls; u64 numberOfCalls;
Block() : index(0), codeHash(0), toalElapsed(0), numberOfCalls(0) { } Block() : index(0), codeHash(0), totalElapsed(0), numberOfCalls(0) { }
}; };
static std::vector<Block> blocks; static std::vector<Block> blocks;
static u32 blockIndex; static u32 blockIndex;
static u64 beginTime; static u64 beginTime;
static Block& Add(u64 codeHash) { static Block& Add(u64 codeHash)
{
const u32 blockIndex = blocks.size(); const u32 blockIndex = blocks.size();
blocks.push_back(Block()); blocks.push_back(Block());
Block& block = blocks.back(); Block& block = blocks.back();
@ -178,29 +193,34 @@ namespace JitILProfiler {
block.codeHash = codeHash; block.codeHash = codeHash;
return block; return block;
} }
// These functions need to be static function // These functions need to be static because they are called with
// because they are called with ABI_CallFunction(). // ABI_CallFunction().
static void Begin(u32 index) { static void Begin(u32 index)
{
blockIndex = index; blockIndex = index;
beginTime = __rdtsc(); beginTime = __rdtsc();
} }
static void End() { static void End()
{
const u64 endTime = __rdtsc(); const u64 endTime = __rdtsc();
const u64 duration = endTime - beginTime; const u64 duration = endTime - beginTime;
Block& block = blocks[blockIndex]; Block& block = blocks[blockIndex];
block.toalElapsed += duration; block.totalElapsed += duration;
++block.numberOfCalls; ++block.numberOfCalls;
} }
struct JitILProfilerFinalizer { struct JitILProfilerFinalizer
virtual ~JitILProfilerFinalizer() { {
virtual ~JitILProfilerFinalizer()
{
char buffer[1024]; char buffer[1024];
sprintf(buffer, "JitIL_profiling_%d.csv", time(NULL)); sprintf(buffer, "JitIL_profiling_%d.csv", (int)time(NULL));
FILE* file = fopen(buffer, "w"); FILE* file = fopen(buffer, "w");
setvbuf(file, NULL, _IOFBF, 1024 * 1024); setvbuf(file, NULL, _IOFBF, 1024 * 1024);
fprintf(file, "code hash,total elapsed,number of calls,elapsed per call\n"); fprintf(file, "code hash,total elapsed,number of calls,elapsed per call\n");
for (std::vector<Block>::iterator it = blocks.begin(), itEnd = blocks.end(); it != itEnd; ++it) { for (std::vector<Block>::iterator it = blocks.begin(), itEnd = blocks.end(); it != itEnd; ++it)
{
const u64 codeHash = it->codeHash; const u64 codeHash = it->codeHash;
const u64 totalElapsed = it->toalElapsed; const u64 totalElapsed = it->totalElapsed;
const u64 numberOfCalls = it->numberOfCalls; const u64 numberOfCalls = it->numberOfCalls;
const double elapsedPerCall = totalElapsed / (double)numberOfCalls; const double elapsedPerCall = totalElapsed / (double)numberOfCalls;
fprintf(file, "%016llx,%lld,%lld,%f\n", codeHash, totalElapsed, numberOfCalls, elapsedPerCall); fprintf(file, "%016llx,%lld,%lld,%f\n", codeHash, totalElapsed, numberOfCalls, elapsedPerCall);
@ -210,31 +230,15 @@ namespace JitILProfiler {
} }
}; };
std::auto_ptr<JitILProfilerFinalizer> finalizer; std::auto_ptr<JitILProfilerFinalizer> finalizer;
static void Init() { static void Init()
{
finalizer = std::auto_ptr<JitILProfilerFinalizer>(new JitILProfilerFinalizer); finalizer = std::auto_ptr<JitILProfilerFinalizer>(new JitILProfilerFinalizer);
} }
static void Shutdown() { static void Shutdown()
{
finalizer.reset(); finalizer.reset();
} }
}; };
#else
namespace JitILProfiler {
// FIXME: Dummy functions for linux. Please implement them.
struct Block {
u32 index;
u64 codeHash;
u64 toalElapsed;
u64 numberOfCalls;
Block() : index(0), codeHash(0), toalElapsed(0), numberOfCalls(0) { }
};
static Block dummyBlock;
static Block& Add(u64 codeHash) { return dummyBlock; }
static void Begin(u32 index) { }
static void End() { }
static void Init() { }
static void Shutdown() { }
};
#endif
static int CODE_SIZE = 1024*1024*32; static int CODE_SIZE = 1024*1024*32;

View File

@ -39,7 +39,7 @@ elseif(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin"))
set(LIBS ${LIBS} clrun) set(LIBS ${LIBS} clrun)
endif() endif()
add_library(Plugin_VideoSoftware SHARED ${SRCS}) add_library(Plugin_VideoSoftware MODULE ${SRCS})
target_link_libraries(Plugin_VideoSoftware ${LIBS}) target_link_libraries(Plugin_VideoSoftware ${LIBS})
install(TARGETS Plugin_VideoSoftware install(TARGETS Plugin_VideoSoftware
LIBRARY DESTINATION ${plugindir} LIBRARY DESTINATION ${plugindir}