[C++] BeginPaint takes too much CPU time - any alternative?

Started by
9 comments, last by iMalc 16 years, 1 month ago
My app has two areas, inside the main window there is one child-window OpenGL with one object and the other is child-window DataPanel where i would like to display the coordinates object in OpenGL window. Since these coordinates are changing constantly, i set a timer of 20ms which triggers InvalidateRect for DataPanel, and consequently updates all the coordinates. All works well, but i am extremely surprised that it takes so much CPU time. For example, even if between BeginPaint() and EndPaint() i put no code at all, it will take 25% of my processor time (i have 1.83Ghz dual core). Isnt this too much for merely refreshing some data? If i comment out InvalidateRect, it takes from 0-1%. case WM_TIMER: { InvalidateRect(hwnd, NULL, 1); break; } case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); // code EndPaint(hwnd, &ps); break; } Any comments, suggestion, alternative solutions are very much appreciated, Boris
Advertisement
How are you computing this "25% processor time"? Hopefully you are not trying to use the values reported in the Windows Task Manager for benchmarking. These numbers only indicate how much of the available CPU time as reported by the process scheduler is being consumed by each process. It has nothing to do with the performance of the process. The only thing it is telling you is that when you process your paint event, your application is consuming more of the available CPU time than when you don't process your paint event, which should be a big "duh" moment.
"When you die, if you get a choice between going to regular heaven or pie heaven, choose pie heaven. It might be a trick, but if it's not, mmmmmmm, boy."
How to Ask Questions the Smart Way.
What if you comment out the BeginPaint() and EndPaint() calls?

And anyway, you're rendering at about 50FPS (WM_TIMER is a low priority message and isn't always going to be sent at the speed you request, so you shouldn't be using it if you need precise timing), what's wrong with using up 25% of the CPU?

And what is in your "// code" section?
If I comment out BeginPaint() and EndPaint() calls, but leave InvalidateRect() uncommented, it still takes around 25%. I agree that 50FPS is a lot and if i reduce that to 10FPS, CPU usage for this process drops to about 7-10%. I would like this redrawing to take as less CPU time as possible, so it would have more time for computing other functions, which will be quite demanding for CPU.

As for code section, for now it is only this:

case WM_TIMER:
{
InvalidateRect(hwnd, NULL, 1);
break;
}
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &ps);
color = GetSysColor(COLOR_BTNFACE);
SetBkColor(hdc, color);
TextOut(hdc, 20, 20, positionr, lstrlen(positionr));
TextOut(hdc, 20, 40, rotationr, lstrlen(rotationr));
TextOut(hdc, 20, 135, positionv, lstrlen(positionv));
TextOut(hdc, 20, 155, rotationv, lstrlen(rotationv));
EndPaint(hwnd, &ps);
break;
}
Rather than render text manually, could you use standard Windows GUI controls such as labels and edit boxes to display the values? This will be many times faster than TextOut() and you won't need a WM_PAINT event at all.
"When you die, if you get a choice between going to regular heaven or pie heaven, choose pie heaven. It might be a trick, but if it's not, mmmmmmm, boy."
How to Ask Questions the Smart Way.
When you call InvalidateRect with TRUE for the last parameter that means you are saying that you want BeginPaint to send a WM_ERASEBKGND notification (and possibly others) before returning. That's likely where your time is being spent.
-Mike
... You aren't by any chance running a quad-core machine and causing a tight loop somehow? :/
Why are you using WM_TIMER?
Quote:Original post by Anon Mike
When you call InvalidateRect with TRUE for the last parameter that means you are saying that you want BeginPaint to send a WM_ERASEBKGND notification (and possibly others) before returning. That's likely where your time is being spent.
Yes, that seems likely.

I would not expect the code that is currently in the WM_PAINT handler to cause CPU usage of more than say 1% when run at 50fps. You must be doing something wrong.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Thanks everyone for answers - I changed InvalidateRect TRUE to FALSE, but there was no change, so i guess i had a tight main loop, because when i put Sleep(5) in the loop the time taken decreases to 0-1%, which seems normal to me. Is the problem of tight loops usually solved with Sleep() or is there another approach?

// main loop
while(!done)
{
Sleep(5);
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
done=TRUE;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
DrawGLScene();
SwapBuffers(hDCgl);
}
}

This topic is closed to new replies.

Advertisement