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:
parent
d1264b3258
commit
ef55177ed6
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
|
|
Loading…
Reference in New Issue