[Built-in lightning rod] dropshadoweffect causes memory spikes
Zhou yinhui
Since learning WPF, I know that "bitmap effect" is not a fuel-saving Lamp, but I only know that it takes a lot of CPU time, and it seems inefficient, however, in a special hardware environment, memory spikes may occur.
This is the case. I wrote a smallProgramA Japanese friend who looks pretty good, but is not abnormal, tests my program in an abnormal hardware environment and says, "after a period of operation, the program will crash ". when I remotely run VNC, I found that every small operation (or even a click) of the program will increase the memory by several Mb. At this speed, the system will crash soon, And nnd
However, the depressing thing is that I cannot reproduce this bug, and it cannot be reproduced on both the development team and the test team's machine (but on the Japanese side, this bug is completely reproduced )... memory leaks cannot be reproduced, so funny... more funny things are coming soon
Finally, I found that the following display configuration was used in Japan: Three monitors were connected to the host, and the first one was an ordinary screen, the second and third screens are medical high-definition screens (the legendary resolution is super high, of course, the price is also super expensive). When these two screens are connected, my program will end up. first, eliminate the problem of single multi-screen, because my development machine is dual-screen, and then I ruled out the problem of high-screen, because the normal screen is disabled, and when the high-screen is used, everything is OK.
After a series of troubleshooting, the strange conclusion is: when the common screen and HD screen are enabled at the same time, and my program window is displayed on the ordinary screen, the memory is soaring, and the final result is sharp, everything else OK...
Why can this problem be reproduced in such a strange environment.
Okay, now I admit it's myself.CodeBad. The memory is leaked. Fortunately, I have. Net memory Profile & ants memory profiler.
After some hard work, the two memory tools I considered as "artifacts" did not give me any answer: in terms of the change curve, the memory has increased a lot (hundreds of megabytes at will), but the memory usage and change rate of various types of objects in the memory snapshot are very normal, dizzy, where is the lost memory ~~
I began to suspect that P/invoke and other memory loss, because the program has a large number of Win32 API Platform calls, And then I commented out the code... unfortunately, the answer is no.
No, let's try again: feature pruning, which is often used, which makes it easier for us to narrow down the scope of code. because the coupling between the UI Layer and the background code is very low, you can directly comment out the XAML code on the UI Layer, and the function can be well laid out without changing the logic code, therefore, it is easier to crop functions. my program is almost ruined, and the problem still exists...
Another strange problem is that, for example, if we locate a complicated function a, it will lead to problems and then start tracking from, after B-> C-> D is circled for a long time, it will reach a simple code such as: This. width = mywidth; there is no problem if you comment on this simple code. Otherwise, it will lead to problems. Are there any events caused by changing the width, or is the problem caused by overwriting the control re-painting? This little hope will soon be erased, and the control has been extracted to be simple enough, with almost no code... play with me...
In general, when I'm desperate, I will use my big trick: I guess
I have always believed that writing a program depends on inspiration (of course, based on your basic knowledge ). I guess it is the problem caused by that control first. Of course, I don't doubt my code. I doubt Microsoft's code. This is not arrogant, but an experience value, I have made a lot of headless issues, and the root cause is Microsoft code. If you have the opportunity to play with Microsoft's RichTextBox Control and add a Japanese Atok input method, you will believe what I said (it will lead to death ). so I guess viewbox, a drawing panel in the program is placed in viewbox (to achieve the zoom function). Well, cut the drawing board out of the panel.
Haha, OK. It's okay to cut the drawing board out of the Panel. Is it so lucky for me to guess it...
For verification, I made a simple demo about viewbox and put it on the machine in Japan. No problem, I'm dizzy.
Then I noticed that in the source program, viewbox is placed in a scrollviewer, and this scrollviewer has its own template...
Repeat the canvas into the viewbox and press the knife in scrollviewer. I was surprised to find that:
In this scrollviewer control template, there is actually a dropshadoweffect, which is a day-killing. in addition, this effect does not see the shadow effect in our program, and our program does not need this effect, so it has never been noticed.
Delete! The whole world is quiet ~
To prove that this does cause problems, I made a simple demo,
< Window X: Class = "Dropshadoweffectmomeryleakdemo. window1"
Xmlns = "Http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Xmlns: x = "Http://schemas.microsoft.com/winfx/2006/xaml"
Title = "Window1" Height = "300" Width = "300" >
< Canvas X: Name = "Canvas" >
< Canvas. Effect >
<
Dropshadoweffect
/>
</ Canvas. Effect >
< Button Width = "100" Height = "30" Content = "Click me" Click = "Button_click" />
<! -- The following code can be ignored. I just put some common controls to make the memory leakage more obvious. -->
< Rectangle Fill = "White" Stroke = "Black" Width = "53" Height = "43" Canvas. Left = "37" Canvas. Top = "71" />
< Rectangle Fill = "# Ffaf8c8c" Stroke = "Black" Width = "54" Height = "72" Canvas. Left = "158" Canvas. Top = "42" />
< Rectangle Fill = "White" Stroke = "Black" Width = "54" Height = "47" Canvas. Left = "117" Canvas. Top = "130" />
< Rectangle Fill = "# Ff21cb63" Stroke = "Black" Width = "44" Height = "65" Canvas. Left = "212" Canvas. Top = "130" />
< Rectangle Fill = "White" Stroke = "Black" Width = "42" Height = "49" Canvas. Left = "58" Canvas. Top = "177" />
< Rectangle Fill = "White" Stroke = "Black" Width = "53" Height = "45" Canvas. Left = "171" Canvas. Top = "195" />
< Rectangle Fill = "# Ffde13ee" Stroke = "Black" Width = "70" Height = "69" Canvas. Left = "224" Canvas. Top = "30" />
< Rectangle Fill = "White" Stroke = "Black" Width = "21" Height = "43" Canvas. Left = "100" Canvas. Top = "42" />
< Rectangle Fill = "White" Stroke = "Black" Width = "21" Height = "22" Canvas. Left = "171" Canvas. Top = "8" />
< Rectangle Fill = "White" Stroke = "Black" Width = "37" Height = "43" Canvas. Left = "117" Canvas. Top = "71" />
< Rectangle Fill = "White" Stroke = "Black" Width = "41" Height = "33" Canvas. Left = "49" Canvas. Top = "130" />
< Rectangle Fill = "# Ffff2b2b" Stroke = "Black" Width = "54" Height = "31" Canvas. Left = "100" Canvas. Top = "195" />
</ Canvas >
</ Window >
When you click the button, perform the following operations:
Private Void Button_click ( Object Sender, routedeventargs E)
{
For ( Int I = 0 ; I < Canvas. Children. Count; I ++ )
{
VaR C = (Frameworkelement) canvas. Children [I];
C. Width + = 1 ;
C. Height + = 1 ;
}
}
On my development machine (or on your machine), when you click the button continuously, the memory will increase, but the growth will be slow. In a short time, the memory will be released, therefore, the memory is basically maintained at 10 MB (18756 kb in the figure ):
In the special environment in Japan, the situation is completely different (99340 K, and fun is that the first display with a yellow desktop background and the second display with a blue background, dragging window1 to the second display shows normal memory performance ):
Well, life is about tossing
PS: two graphics cards are inserted on this machine: NVIDIA Quadro fx370 and vrengine smd5.