I'm trying to profile lag in my framework; since I use MinGW, gprof doesn't work with DLLs (for me it even gave me garbage information like an initialization function running thousands of times instead of just once), and gperftools's profiler isn't supported on Windows (yet), I tried rolling my own profiling code inspired by Cygwin's:
// 10 may 2015
#include "uipriv_windows.h"
static FILE *fprof = NULL;
static DWORD WINAPI profilerThread(LPVOID th)
{
HANDLE thread = (HANDLE) th;
LARGE_INTEGER counter;
CONTEXT ctxt;
// TODO check for errors
if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL) == 0)
complain("error setting thread priority in profilerThread()");
for (;;) {
if (SuspendThread(thread) == (DWORD) (-1))
complain("error suspending thread in profilerThread()");
QueryPerformanceCounter(&counter);
ZeroMemory(&ctxt, sizeof (CONTEXT));
ctxt.ContextFlags = CONTEXT_CONTROL;
if (GetThreadContext(thread, &ctxt) == 0)
complain("error getting thread context in profilerThread()");
fprintf(fprof, "%I64X %I64d\n",
(DWORD64) (ctxt.Eip),
counter.QuadPart);
fflush(fprof);
if (ResumeThread(thread) == (DWORD) (-1))
complain("error resuming thread in profilerThread()");
Sleep(100);
}
return 0;
}
void initprofiler(HANDLE thread)
{
fprof = fopen("profiler.out", "w");
if (fprof == NULL) {
fprintf(stderr, "error opening profiler output file\n");
abort();
}
if (CreateThread(NULL, 0, profilerThread, thread, 0, NULL) == NULL)
complain("error creating profiler thread");
}
However, the profiles this returns are useless:
F77B0C03 3571425665428
F77B0C03 3571426671982
F77B0C03 3571427677119
F77B0C03 3571428683227
F77B0C03 3571429689442
F77B0C03 3571430696476
F77B0C03 3571431702590
F77B0C03 3571432708622
This particular value is on wine, which redirects to __kernel_vsyscall+0x3
. Real Windows has something like 7C90E514
instead, which redirects to ntdll!KeFastSystemCallRet
.
I'm guessing (given a wine stack trace) this is because it's stuck in GetMessage()
.
If I change the sleep duration from 100 to 1, I get more meaningful values occasionally.
Is there something I'm missing? Is there a better profiling option, or do I have this fundamentally wrong in some way?
Thanks.