Why would GetMessageW take up massive CPU usage in my WPF application?
Asked Answered
M

4

12

I've got a serious head-scratcher on my hands here. I'm investigating performance issues with a WPF component in our application.

Our .net application is very large, and almost entirely in windows forms. As part of a new initiative we rewrote one of our core components with a rich WPF ui. There is a lot of WinForms<-->WPF interop going on with this thing to glue it together, and I suspect that may be somehow related to what I'm seeing.

When I profile the slow operation in ANTS profiler, I see a lot of activity occurring inside the function UnsafeNativeMethods.IntGetMessageW. ANTS reports as much CPU activity going there as it does to all of our business logic and wpf rendering stuff combined. There is no managed code downline of that function that is using the cycles, so whatever IntGetMessageW is doing there is what I'm after.

I'm not particularly well-versed in win32 programming, but I know the basics of a message loop in that context. None of what I'm seeing here though is anything we do manually -- at no point in our code are we interacting directly with either the underlying messageloop itself, or any of the more complicated stuff that can be accessed on the WPF dispatcher.

Our WPF component in question here is written inheriting from Window (ie. it's not just a control/usercontrol), and we show it using ShowDialog out of our higher level logic that used to call ShowDialog on the old WinForms version of this component. There are some WindowsFormsIntegrationHost controls that we have used inside of the WPF component to preserve compatibility with some of our existing pieces that could not be rewritten in WPF.

I've been researching this for days, but have never found a whole lot to go on. I keep finding vaguely related postings that talk about input messages (mouse and keyboard), but I don't know what I can do to verify that; I've already tried butchering the code to remove every mouse/keyboard operation I could.

I'm having a hard time getting anywhere primarily because this line of code is completely isolated (not a parent or child of anything I can point out as actually coming from our code), and completely opaque about what it is doing.

Here is an image of an ANTS call graph of the ShowDialog function showing the path of calls to get here: alt text

I fully realize that this could be something that just has to be done as part of WPF (although other componenets we have written in WPF don't display this behavior), or that this is just a very strange bug in ANTS profiler, but at this point I need to verify it one way or another. If anyone can tell me what is or might be going on here -- or point me to some way I would be able to figure it out myself, I will direct all kinds of good karma your way.

UPDATE: In response to some discussion below, here is another view from ANTS -- this one better illustrates the confusion I am having (this is with the ANTS view in "CPU time" mode). I've hastily censored parts of our code, but none of the system related functions:

alt text

Thanks for looking!

Microcircuit answered 8/11, 2010 at 20:12 Comment(1)
That's typical performance for a WPF app. Anyone on the WPF/Silverlight team listening?Fiddlefaddle
L
1

I found this while searching for information on the same issue. I'll add what I know and see if it helps:

I'm running on a WinXP box - the WPF framework is more integrated in Vista and Win7 than it is in XP. Some of this could be due to how WPF runs "on top" of the XP desktop, rather than within it.

I'm running a pure native WPF application - with no WinForms or other code.

I ran into this trying to determine why simply scrolling a window would consume 100% CPU and stutter while doing it.

Running the AQtime performance profiler, I see that IntGetMessageW occupies the largest part of that 100% CPU usage. This is not due to IntGetMessageW waiting for a message, but something the function is actually doing.

The one thing I haven't looked into yet is that maybe IntGetMessageW has never been a fast method, and maybe WPF simply overuses it. It is possible that data bindings in WPF use the native Win32 message pump to update Dependency Properties within WPF. If that is the case, it could be that my window simply has too many bindings.

Library answered 15/12, 2010 at 21:30 Comment(0)
A
5

Yes, this is normal. Any GUI app is always executing GetMessageW(), waiting for Windows to send it a message. It isn't actually burning CPU cycles doing this, just blocked on an internal synchronization object until some kind of UI event is signaled.

This of course makes profiling UI apps difficult, you really need unit tests that test the subcomponents of your app.

Alaska answered 8/11, 2010 at 20:19 Comment(1)
This was the first thing I suspected, but what is confusing me is why ANTS doesn't show significant getmessage CPU activity for any of our other WPF components. In a different similarly complex component, an operation taking roughly the same overall time shows 0.02% CPU usage in IntGetMessageW, while in the above example almost 60% CPU usage is shown in ANTS.Microcircuit
I
3

When profiling an application, you need to differentiate between time spent in a method and CPU cycles consumed. Many profiling tools show you the overall time spent in a method - which in the case of somthing like GetMessageW is going to be quite high. All of the activity of the main thread of a GUI application will appear to happen within that method. That's not necessarily a problem, however ... this may simply be the main message pump waiting on a synchronization objects and not actually consuming cycles.

I would suggest you start by using the sampling feature in the ANTS profiler to identify the methods that are called most often and correlate those to the methods that are consuming the most CPU cycles. Once you've done that, you decide where to instrument your application to dive in further and get an idea of what the call graphs look like for the places that are most CPU intensive.

You should start by suspecting your own code first. It's rare that something like the WPF or Win32 infrastructure is responsible for poor performance or high CPU utilization. Likely, the problem lies somewhere in your implementation - it helps you get an overall sense of where CPU cycles are spent in your program.

I suggest that you also spend some time learning the capabilities of the profiler to be most effective. Profilers can be sophisticated and confusing tools until you understand what it is that they are trying to show you. The linked tutoral from RedGate should be a good place to start, if you haven't done so already. For example, the Timeline view may actually be a good place to start to see where high-CPU activity is occurring, and confining your analysis to those segments of executed code.

alt text

The Call Graph is another useful tool in ANTS, as it helps you drill into areas of the code that are most expensive. The key is to make sure you are looking at the overall cost and not just the overall time.

alt text

Ignoble answered 8/11, 2010 at 20:30 Comment(1)
I'm pretty familiar with ANTS, and it is set up to allow you to differentiate between viewing the CPU time and Wall Clock time spent in functions in the results. If ANTS is reporting these results the way it always has in the past (ie. as long as it's not misrepresenting the data somehow) then it is definately showing lots of CPU usage (I see around 50% in these results, with the other 50% going to our business logic). Is it possible for GetMessage to be doing CPU intensive tasks? I have included another image above showing more info from the results.Microcircuit
L
1

I found this while searching for information on the same issue. I'll add what I know and see if it helps:

I'm running on a WinXP box - the WPF framework is more integrated in Vista and Win7 than it is in XP. Some of this could be due to how WPF runs "on top" of the XP desktop, rather than within it.

I'm running a pure native WPF application - with no WinForms or other code.

I ran into this trying to determine why simply scrolling a window would consume 100% CPU and stutter while doing it.

Running the AQtime performance profiler, I see that IntGetMessageW occupies the largest part of that 100% CPU usage. This is not due to IntGetMessageW waiting for a message, but something the function is actually doing.

The one thing I haven't looked into yet is that maybe IntGetMessageW has never been a fast method, and maybe WPF simply overuses it. It is possible that data bindings in WPF use the native Win32 message pump to update Dependency Properties within WPF. If that is the case, it could be that my window simply has too many bindings.

Library answered 15/12, 2010 at 21:30 Comment(0)
H
0

Looks like your message pump is pumping a lot. Could be interesting to see what kind of message your message queue is filled of. Can you use Spy++ on your window to see what is going on?

Edit

I've misunderstood the problem.

Hans Passant is right, your program is just waiting on GetMessage for some event to process.

Health answered 8/11, 2010 at 20:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.