20% CPU when mouse moving, Why? |
Post Reply |
Author | |
Howard Farseer
Groupie Joined: 30 September 2007 Status: Offline Points: 30 |
Post Options
Thanks(0)
Posted: 08 July 2009 at 9:50am |
I've noticed the performance graded down when I move the mouse over the window of the program written with Toolkit. It takes up 20% CPU and even more. Most programs(not written with Toolkit) only take up 6%~10% CPU time. I would like to know why this happened and how to solve this problem. Thank you!
|
|
adrien
Senior Member Joined: 30 April 2007 Location: New Zealand Status: Offline Points: 449 |
Post Options
Thanks(0)
|
what sort of computer hardware are you running on?
In my experience, most programs don't show as using more than 1% (mostly sit on 0%), so if for you that's mostly 6 - 10% that implies quite an old / slow machine. |
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
All you need is while(1); and your CPU will rush. Hence, bad code = high CPU usage.
|
|
PokerMemento - http://www.pokermemento.com/
|
|
Howard Farseer
Groupie Joined: 30 September 2007 Status: Offline Points: 30 |
Post Options
Thanks(0)
|
Core Dua T2250, 1.73Ghz, Nvidia GeForce Go 7300. It's not that slow and I move the mouse very fast.
|
|
Howard Farseer
Groupie Joined: 30 September 2007 Status: Offline Points: 30 |
Post Options
Thanks(0)
|
This also happens to the sample programs of Toolkit: When mouse moving fast over the window, CPU usage runs very high, than none-Toolkit Pro programs. I have found the problem: The Ribbon Theme! CPU usage falls down after I have switch the Theme to native XP. |
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Is this true for all ribbon themes? Try "Scenic" for instance.
|
|
PokerMemento - http://www.pokermemento.com/
|
|
Oleg
Admin Group Joined: 21 May 2003 Location: United States Status: Offline Points: 11234 |
Post Options
Thanks(0)
|
So where you move mouse ? Around Ribbon ?
|
|
Oleg, Support Team
CODEJOCK SOFTWARE SOLUTIONS |
|
Howard Farseer
Groupie Joined: 30 September 2007 Status: Offline Points: 30 |
Post Options
Thanks(0)
|
Especially the Command bar area |
|
rdhd
Senior Member Joined: 13 August 2007 Location: United States Status: Offline Points: 886 |
Post Options
Thanks(0)
|
For what it's worth, I have a stackspy utility and it seems to show the app may be doing update UI during idle processing. Unfortunately most of the stacks I am catching start off with "ntdll.dll ????", which makes it tough since one cannot perform a good stack trace without the Windows symbols and the spy I have doesn't know about my Windows symbols dir.
The cpu definitely spikes when I move over any part of the command ribbon that is occupied by a group, whether I am on a control or in unoccupied areas of the group. If I move off of all groups, the cpu slows down.
Be aware that "old" UI apps that use toolbars normally have most of their commands on menus and toolbar buttons are usually the only commands that update the UI during idle processing. Menu enabling/disabling normally only occurs when the user drops one of the menus down. So if you are like us and have a lot of UI exposed on the command ribbon, the cpu usage will be higher if CJ updates the UI during idle processing. Moving the mouse will normally take an app out of the "idle" state and then right back into it after the mouse move messages are processed. And with today's faster machines, you really have to have a fast hand to keep the message processing occurring.
Also, I assume that CJ's command ribbon is getting the mouse move message and may be invoking the OnCmdMsg to do an update UI at that time. Oleg would know if CJ does update UI on mouse move, idle processing or perhaps both.
|
|
Oleg
Admin Group Joined: 21 May 2003 Location: United States Status: Offline Points: 11234 |
Post Options
Thanks(0)
|
Hi,
If you move around Ribbon or toolbar it select/unselect buttons and Toolbar have to redraw self.
|
|
Oleg, Support Team
CODEJOCK SOFTWARE SOLUTIONS |
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
I know this can happen if you return TRUE when handling WM_KICKIDLE. Just a thought.
|
|
PokerMemento - http://www.pokermemento.com/
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
It's definitely the drawing of the commandbar controls that does it. It seems the blue theme is worse than the others (20% vs ~15%).
I'm not sure this is an issue. The drawing sure needs some cycles... heavy PNG-blitting perhaps?
|
|
PokerMemento - http://www.pokermemento.com/
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
FYI, Word 2007 does the same. Though, it seems a little bit more optimized (< 15%). I wouldn't bother...
|
|
PokerMemento - http://www.pokermemento.com/
|
|
rdhd
Senior Member Joined: 13 August 2007 Location: United States Status: Offline Points: 886 |
Post Options
Thanks(0)
|
CPU usage on my app using V13.0 of CJ spikes to around 50%.
The system is being deluged with a timer that is triggered every 50ms. The timer is not being set when I move onto the command ribbon as long as I am in an unoccupied area. But move the mouse into the "tab" strip (not even over a tab) and the timer is set. Or move the mouse onto any group (don't have to move over a control) and it is set. The timer trips until the WM_MOUSELEAVE message is processed by the ribbon at which point CJ cancels the timer. The timer function being set is CXTPMouseManager::TrackMouseTimerProc and it is being set in CXTPMouseManager::TrackMouseLeave, which is called whenever the menubar base class (commandbar derived class) gets a mouse move (forwarded from the ribbon object).
At least that is what is happening in my app.
To see if this is what is happening on your system, start the debug version of your app and start spy++. Then use the FindWindow command of spy++ and drag the mouse over the command ribbon and select it. Click the "messages" radio button. Then activate your app and move the mouse over the ribbon so that it moves over the tab area or a group. Then just leave the mouse where it is (to avoid other messages being logged). I quickly see only a steady stream of WM_TIMER messages being reported by spy++ in the messages window.
Do NOT have the debugger attached to your app while you are spying on the app as the debugger and spy++ can cause a system deadlock when both attach to a process (not actually a deadlock but it can take forever to get the task manager activated after which you have to kill devenv.exe to get control of the system back).
Once you see the WM_TIMER messages in spy++, you will see "tmprc:" followed by a hex address on each WM_TIMER line in the message logging window. This is the address of the timer proc function that is being called. Then shut down spy++ and go back to Visual Studio and attach to your process. Once you are attached, go to the "Breakpoints" window and click the "New" dropdown and choose "Break at function". When the dialog appears, key in the hex address and then move the mouse over the tab or group area. You should start breaking at the function (you will actually break at a "jmp" instruction and then step one time in the disassembly window and you will be at the hex address you set the breakpoint at.
You may see the debugger tell you that there is no code for the breakpoint and you can choose the button that lets you see the disassembly window.
The timer does not affect the performance of my app since very little processing is occurring in the timer function being called. However any other processes running are affected. But only while your app has focus (timer is cancelled when the app looses focus) and you have the timer running while leaving the mouse over the ribbon window. I am sure customers will notice this and complain. At least ours will as we have had them do so in the past. Some customers have the "As long as I am not doing anything, neither should the app" mentality.
|
|
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
Hello;
I don't know whether it's the same issue, but a few years ago we had the same problems with applications using timers with short delay and GUI updates. We were able to reduce CPU usage from about 40% to 1% by overwriting CWinApp::IsIdleMessage and returning FALSE when it's a WM_TIMER message too: BOOL CXREngineApp::IsIdleMessage(MSG* pMsg) { return (CWinApp::IsIdleMessage(pMsg) && (pMsg->message!=WM_TIMER) && (pMsg->message!=EWM_DEVICESTATISTICS)); } |
|
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
|
rdhd
Senior Member Joined: 13 August 2007 Location: United States Status: Offline Points: 886 |
Post Options
Thanks(0)
|
mgampi's post looks very promising since in our app I have already detected that idle processing keeps running and the timer is going off every 50 ms. The MSDN says this: If an application has created a short timer, OnIdle will be called frequently, causing performance problems. To improve such an application's performance, override IsIdleMessage in the application's CWinApp-derived class to check for WM_TIMER messages. I don't have access to our source but as soon as I do I will see if we override the method, inherit from the CJ frame class or implemented our own. Then I'll add the above code to our implementation. Thanks mgampi for what I believe is the solution to the problem. CJ may want to try this in their ribbonsample (which I will also try when I get back to work) and if it solves the problem, add the same solution to their frame window classes.
|
|
Howard Farseer
Groupie Joined: 30 September 2007 Status: Offline Points: 30 |
Post Options
Thanks(0)
|
Thanks, but it doesn't work for me. what is EWM_DEVICESTATISTICS? |
|
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
Hi; it's an app specific message. You can ignore it! |
|
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
|
scottp
Groupie Joined: 16 October 2006 Status: Offline Points: 59 |
Post Options
Thanks(0)
|
I just tried this in my app (we have a timer 50ms timer) and it does make a difference.
While doing some futher reading I found the suggestion to also filter WM_MOUSEMOVE see this for more detail: http://www.eggheadcafe.com/conversation.aspx?messageid=32023078&threadid=32007742 BOOL CMyApp::IsIdleMessage(MSG* pMsg) { return (CWinApp::IsIdleMessage(pMsg) && (pMsg->message!=WM_TIMER) && (pMsg->message!=WM_MOUSEMOVE)); } This change appears to work OK and the CPU usage is really low. I am not sure if this might have some negative impacts on mouse handling code (for example mouse leave/enter notifications). |
|
Howard Farseer
Groupie Joined: 30 September 2007 Status: Offline Points: 30 |
Post Options
Thanks(0)
|
Yes! WM_MOUSEMOVE makes a big difference for me. Now the CPU usage is really low. Thanks scottp! |
|
tralfaz
Groupie Joined: 21 June 2009 Status: Offline Points: 36 |
Post Options
Thanks(0)
|
If the mouse is using the Intellipoint driver, disable it. There are some known problems with it. Namely, it generates random and frequent WM_PAINT messages.
|
|
XP Pro SP3 / VS2008 C++ / Xtreme CommandBars v13.1.0 |
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Just wondering what you guys made out of this. Is it worth putting this in my CJ-ribbon application?
"Default implementation filters out WM_PAINT message, redundant WM_MOUSEMOVE messages and system timer message used for caret blinking."
That not enough?
|
|
PokerMemento - http://www.pokermemento.com/
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Played a bit with Spy++ and RibbonControls demo. I sense a CJ window message is in fact the culprit: XTP_TTM_WINDOWFROMPOINT
So IsIdleMessage should look something like this (if this solution proves to be an improvement, CJ should derive CWinApp and let us use that class as base):
BOOL CXTPWinApp::IsIdleMessage(MSG* pMsg)
{ return (CWinApp::IsIdleMessage(pMsg) && (pMsg->message != WM_TIMER) &&
(pMsg->message != XTP_TTM_WINDOWFROMPOINT &&
(pMsg->message != XTP_TTM_SETIMAGE)); // Possibly, more messages than these should be added?
} |
|
PokerMemento - http://www.pokermemento.com/
|
|
Post Reply | |
Tweet
|
Forum Jump | Forum Permissions You cannot post new topics in this forum You cannot reply to topics in this forum You cannot delete your posts in this forum You cannot edit your posts in this forum You cannot create polls in this forum You cannot vote in polls in this forum |