Print Page | Close Window

20% CPU when mouse moving, Why?

Printed From: Codejock Forums
Category: Codejock Products
Forum Name: Toolkit Pro
Forum Description: Topics Related to Codejock Toolkit Pro
URL: http://forum.codejock.com/forum_posts.asp?TID=14705
Printed Date: 23 November 2024 at 11:37am
Software Version: Web Wiz Forums 12.04 - http://www.webwizforums.com


Topic: 20% CPU when mouse moving, Why?
Posted By: Howard Farseer
Subject: 20% CPU when mouse moving, Why?
Date 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!



Replies:
Posted By: adrien
Date Posted: 08 July 2009 at 7:02pm
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.

-------------
http://www.wingate.com - http://www.wingate.com


Posted By: znakeeye
Date Posted: 09 July 2009 at 2:57am
All you need is while(1); and your CPU will rush. Hence, bad code = high CPU usage.

-------------
PokerMemento - http://www.pokermemento.com/


Posted By: Howard Farseer
Date Posted: 09 July 2009 at 3:56am
Core Dua T2250, 1.73Ghz, Nvidia GeForce Go 7300. It's not that slow and I move the mouse very fast.


Posted By: Howard Farseer
Date Posted: 09 July 2009 at 4:21am
Originally posted by znakeeye znakeeye wrote:

All you need is while(1); and your CPU will rush. Hence, bad code = high CPU usage.

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.


Posted By: znakeeye
Date Posted: 09 July 2009 at 9:44am
Is this true for all ribbon themes? Try "Scenic" for instance.

-------------
PokerMemento - http://www.pokermemento.com/


Posted By: Oleg
Date Posted: 09 July 2009 at 11:33am
So where you move mouse ? Around Ribbon ?

-------------
Oleg, Support Team
CODEJOCK SOFTWARE SOLUTIONS


Posted By: Howard Farseer
Date Posted: 09 July 2009 at 12:32pm
Originally posted by oleg oleg wrote:

So where you move mouse ? Around Ribbon ?

Especially the Command bar area


Posted By: rdhd
Date Posted: 09 July 2009 at 7:05pm
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.


Posted By: Oleg
Date Posted: 10 July 2009 at 5:57am
Hi,
 
If you move around Ribbon or toolbar it select/unselect buttons and Toolbar have to redraw self.


-------------
Oleg, Support Team
CODEJOCK SOFTWARE SOLUTIONS


Posted By: znakeeye
Date Posted: 10 July 2009 at 6:33am
I know this can happen if you return TRUE when handling WM_KICKIDLE. Just a thought.

-------------
PokerMemento - http://www.pokermemento.com/


Posted By: znakeeye
Date Posted: 10 July 2009 at 6:38am
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/


Posted By: znakeeye
Date Posted: 10 July 2009 at 9:13am
FYI, Word 2007 does the same. Though, it seems a little bit more optimized (< 15%). I wouldn't bother...

-------------
PokerMemento - http://www.pokermemento.com/


Posted By: rdhd
Date Posted: 10 July 2009 at 10:04am
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.


Posted By: mgampi
Date Posted: 10 July 2009 at 5:16pm
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


Posted By: rdhd
Date Posted: 11 July 2009 at 9:29am

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.


Posted By: Howard Farseer
Date Posted: 11 July 2009 at 4:34pm
Originally posted by mgampi mgampi wrote:

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));
}



Thanks, but it doesn't work for me. what is EWM_DEVICESTATISTICS?


Posted By: mgampi
Date Posted: 13 July 2009 at 4:31am
Originally posted by Howard Farseer Howard Farseer wrote:

Thanks, but it doesn't work for me. what is EWM_DEVICESTATISTICS?

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


Posted By: scottp
Date Posted: 15 July 2009 at 3:31am
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).


Posted By: Howard Farseer
Date Posted: 16 July 2009 at 1:37pm
Originally posted by scottp scottp wrote:

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).


Yes! WM_MOUSEMOVE makes a big difference for me. Now the CPU usage is really low. Thanks scottp!


Posted By: tralfaz
Date Posted: 20 July 2009 at 9:42pm
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


Posted By: znakeeye
Date Posted: 10 August 2009 at 11:37am
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/


Posted By: znakeeye
Date Posted: 10 August 2009 at 11:51am

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/



Print Page | Close Window

Forum Software by Web Wiz Forums® version 12.04 - http://www.webwizforums.com
Copyright ©2001-2021 Web Wiz Ltd. - https://www.webwiz.net