From ef55177ed6a6509d725cae39739c1bd68e6c4b30 Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Sat, 20 Nov 2010 00:22:56 +0000 Subject: [PATCH] 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 --- Source/Core/Common/Src/Thread.cpp | 10 +-- Source/Core/Common/Src/Thread.h | 3 +- Source/Core/Common/Src/Timer.cpp | 27 +++---- .../Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp | 80 ++++++++++--------- .../Plugin_VideoSoftware/CMakeLists.txt | 2 +- 5 files changed, 56 insertions(+), 66 deletions(-) diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index e06c91170a..2788a4583e 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -492,15 +492,11 @@ namespace Common if (timeout != INFINITE) { - struct timeval now; - gettimeofday(&now, NULL); + struct timespec now; + clock_gettime(CLOCK_MONOTONIC_RAW, &now); memset(&wait, 0, sizeof(wait)); - //TODO: timespec also has nanoseconds, but do we need them? - //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_nsec = now.tv_nsec + (timeout % 1000) * 1000000; wait.tv_sec = now.tv_sec + (timeout / 1000); } diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index b39e22c5a1..6f179e795e 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -60,8 +60,7 @@ #define INFINITE 0xffffffff #endif -//for gettimeofday and struct time(val|spec) -#include +//for clock_gettime and struct timespec #include #endif diff --git a/Source/Core/Common/Src/Timer.cpp b/Source/Core/Common/Src/Timer.cpp index 67bb6874b4..d4d9897006 100644 --- a/Source/Core/Common/Src/Timer.cpp +++ b/Source/Core/Common/Src/Timer.cpp @@ -21,8 +21,6 @@ #include #include #include -#else -#include #endif #include "Common.h" @@ -37,9 +35,9 @@ u32 Timer::GetTimeMs() #ifdef _WIN32 return timeGetTime(); #else - struct timeval t; - (void)gettimeofday(&t, NULL); - return((u32)(t.tv_sec * 1000 + t.tv_usec / 1000)); + struct timespec t; + (void)clock_gettime(CLOCK_MONOTONIC_RAW, &t); + return ((u32)(t.tv_sec * 1000 + t.tv_nsec / 1000000)); #endif } @@ -157,13 +155,6 @@ void Timer::RestoreResolution() #endif } -#ifdef __GNUC__ -void _time64(u64* t) -{ - *t = 0; //TODO -} -#endif - // Get the number of seconds since January 1 1970 u64 Timer::GetTimeSinceJan1970() { @@ -213,9 +204,9 @@ std::string Timer::GetTimeFormatted() (void)::ftime(&tp); sprintf(formattedTime, "%s:%03i", tmp, tp.millitm); #else - struct timeval t; - (void)gettimeofday(&t, NULL); - sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_usec / 1000)); + struct timespec t; + (void)clock_gettime(CLOCK_REALTIME, &t); + sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_nsec / 1000000)); #endif return std::string(formattedTime); @@ -229,8 +220,8 @@ double Timer::GetDoubleTime() struct timeb tp; (void)::ftime(&tp); #else - struct timeval t; - (void)gettimeofday(&t, NULL); + struct timespec t; + (void)clock_gettime(CLOCK_REALTIME, &t); #endif // Get continuous timestamp u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970(); @@ -246,7 +237,7 @@ double Timer::GetDoubleTime() #ifdef _WIN32 double ms = tp.millitm / 1000.0 / 1000.0; #else - double ms = t.tv_usec / 1000.0 / 1000.0; + double ms = t.tv_nsec / 1000000000.0; #endif double TmpTime = Seconds + ms; diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index 655e53969b..8079a00164 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -153,24 +153,39 @@ ps_adds1 */ -#ifdef _WIN32 + // For profiling -// FIXME: This is currently for windows only. +#include + +#ifdef _WIN32 #include #include -#include -namespace JitILProfiler { - struct Block { +#else +#include +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; u64 codeHash; - u64 toalElapsed; + u64 totalElapsed; u64 numberOfCalls; - Block() : index(0), codeHash(0), toalElapsed(0), numberOfCalls(0) { } + Block() : index(0), codeHash(0), totalElapsed(0), numberOfCalls(0) { } }; static std::vector blocks; static u32 blockIndex; static u64 beginTime; - static Block& Add(u64 codeHash) { + static Block& Add(u64 codeHash) + { const u32 blockIndex = blocks.size(); blocks.push_back(Block()); Block& block = blocks.back(); @@ -178,29 +193,34 @@ namespace JitILProfiler { block.codeHash = codeHash; return block; } - // These functions need to be static function - // because they are called with ABI_CallFunction(). - static void Begin(u32 index) { + // These functions need to be static because they are called with + // ABI_CallFunction(). + static void Begin(u32 index) + { blockIndex = index; beginTime = __rdtsc(); } - static void End() { + static void End() + { const u64 endTime = __rdtsc(); const u64 duration = endTime - beginTime; Block& block = blocks[blockIndex]; - block.toalElapsed += duration; + block.totalElapsed += duration; ++block.numberOfCalls; } - struct JitILProfilerFinalizer { - virtual ~JitILProfilerFinalizer() { + struct JitILProfilerFinalizer + { + virtual ~JitILProfilerFinalizer() + { 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"); setvbuf(file, NULL, _IOFBF, 1024 * 1024); fprintf(file, "code hash,total elapsed,number of calls,elapsed per call\n"); - for (std::vector::iterator it = blocks.begin(), itEnd = blocks.end(); it != itEnd; ++it) { + for (std::vector::iterator it = blocks.begin(), itEnd = blocks.end(); it != itEnd; ++it) + { const u64 codeHash = it->codeHash; - const u64 totalElapsed = it->toalElapsed; + const u64 totalElapsed = it->totalElapsed; const u64 numberOfCalls = it->numberOfCalls; const double elapsedPerCall = totalElapsed / (double)numberOfCalls; fprintf(file, "%016llx,%lld,%lld,%f\n", codeHash, totalElapsed, numberOfCalls, elapsedPerCall); @@ -210,31 +230,15 @@ namespace JitILProfiler { } }; std::auto_ptr finalizer; - static void Init() { + static void Init() + { finalizer = std::auto_ptr(new JitILProfilerFinalizer); } - static void Shutdown() { + static void Shutdown() + { 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; diff --git a/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt b/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt index 17de58c67b..4235fe0ac1 100644 --- a/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt +++ b/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt @@ -39,7 +39,7 @@ elseif(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) set(LIBS ${LIBS} clrun) endif() -add_library(Plugin_VideoSoftware SHARED ${SRCS}) +add_library(Plugin_VideoSoftware MODULE ${SRCS}) target_link_libraries(Plugin_VideoSoftware ${LIBS}) install(TARGETS Plugin_VideoSoftware LIBRARY DESTINATION ${plugindir}