I've looked at many posts here regarding PeekMessage and WM_MOUSEMOVE, but so far I have not found anything that relates to performance.
Long story short; I'm doing PC game development and yesterday I noticed that I could bring our application from a stable 500+ FPS (in a menu) to single digits FPS (as low as 6), only by moving the mouse around fast.
After a few hours of digging and profiling, I discovered that the source was PeekMessage(). Not DispatchMessage() for that message, just the peek. I measured calling that function alone clocking in at 1-2 ms very frequently (multiple times per frame). If you combine that with fast mouse movement, pumping the messagequeue could cost me upwards of 1000-2000ms per frame rendered. Sounds ridiculous, but I actually downloaded a super basic DirectX sample from MS and tested out the same thing there, with the same results.
The whole sample is too big to paste here, but if you'd like to try, download the sample at: http://code.msdn.microsoft.com/Direct3D-Tutorial-Win32-829979ef
and make the following changes;
typedef unsigned __int64 QWORD; // 64-bit unsigned.
DOUBLE GSecondsPerCycle;
void appInitTiming(void)
{
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
GSecondsPerCycle = 1.0 / Frequency.QuadPart;
}
QWORD appCycles()
{
LARGE_INTEGER Cycles;
QueryPerformanceCounter(&Cycles);
return Cycles.QuadPart;
}
int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow )
{
UNREFERENCED_PARAMETER( hPrevInstance );
UNREFERENCED_PARAMETER( lpCmdLine );
if( FAILED( InitWindow( hInstance, nCmdShow ) ) )
return 0;
if( FAILED( InitDevice() ) )
{
CleanupDevice();
return 0;
}
appInitTiming();
// Main message loop
MSG msg = {0};
while( WM_QUIT != msg.message )
{
QWORD StartCycles = appCycles();
BOOL hasMsg = PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE );
const QWORD DeltaCycles = appCycles() - StartCycles;
double deltaMS = DeltaCycles * GSecondsPerCycle * 1000.0;
if (deltaMS > 1/* || msg.message == 512*/)
{
std::ostringstream os;
os << "SlowPeekMsg ID: " << msg.message << ", time: " << deltaMS << "ms" << std::endl;
std::string buffer(os.str());
OutputDebugStringA(buffer.c_str());
}
if(hasMsg)
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
Render();
}
}
CleanupDevice();
return ( int )msg.wParam;
}