Memory leak in DockSite

Docking/MDI for WPF Forum

Posted 10 years ago by SeongTae Jeong
Version: 9.1.0500
Platform: .NET 3.5
Environment: Windows Vista (32-bit)
Avatar
Steps to reproduce the problem,

1. Run "Actipro Software WPF Studio - Sample Browser"
2. Select "Docking & MDI" in "Choose a Product Family" panel.
3. Select "Tabbed MDI-Only" in "Docking & MDI QuickStarts" panel.
4. click a button "Run External Sample" in the right panel.

5. Press "Ctrl + N" to add a new tab window "Many times" (for example, 100 windows)
6. Press "Ctrl + F4" many times to close all tab windows totally.

7. Do repeat step 5 and step 6, then monitor "Memory(Private Working Set) column" in your "Windows Task Manager". You cannot miss it that total memory is increasing.

Of course, after closing a sample "Tabbed MDI-Only" window, the memory seems to be cleaned up. But... in my circumstances, my window provides a basic host environment, thus cannot be closed.

Comments (5)

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
You cannot use task manager to monitor memory for .NET apps because the .NET garbage collector decides when to collect memory and sometimes it chooses to delay the collection.

We use the memory profiler from (memprofiler.com) and that tells you what types are referenced etc. When I profile with that and add a bunch of ducments, then close them out, add more, close them and leave nothing left, I can see that we no longer reference any document windows. And by looking at types that are added/removed between my profiler snapshots, everything is cleaned up properly.

So in this case, it is the garbage collector not kicking in yet and is NOT a memory leak by us.


Actipro Software Support

Posted 10 years ago by SeongTae Jeong
Avatar
You mean... you have no miss on that, but only Garbage Collector have a bug?
Then, have you ever issued this bugs to Microsoft on their connect web site?

I knew that,,, even if I use only .NET code, some memory leaks can be occurred. Lots of mistakes by .NET programmers make their program instable.

Another "even", if I make a small DockSite control, Can it also make system's private memory increased? You bet?

I think,

At least, you have to use divide & conquer strategy on your product, and you have to know which points of the problem exists exactly. At that time, If not your fault definitely, report to Microsoft to make a patch on Garbage Collector, which can also make an effect on your product's stablilty. Is this wrong request for you? (Remember, I report this bug to you with repro steps)

Anyway, I'm disappointed at your decision on shifting your fault to others. (I admit! it might be your fault or not. Once again, are you sure it is not your fault?)

Another "Anyway", Thanks for your quick response. :)
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
We are not saying there is an MS bug at all. We are saying that .NET memory allocation and release is not straightforward as you think. The task manager in Windows is NOT a good way to look for memory leaks as it is not reliable in searching for them. Memory leaks in .NET can only be found properly by using profilers like what one I mentioned because they tell you which objects are retained in memory with each snapshot you take.

When I profiled that QuickStart, our objects were being released properly even though that task manager showed increased memory. Again, this is due to how .NET manages memory and is not a bug. Basically if your system had gotten to a point where it required more memory, .NET would respond and would release some of that memory that was claimed.

There are a ton of articles on the web that talk about how garbage collection and memory release work in detail. Here's one of the first hits I found when I googled it that explains the scenario pretty well:
http://weblogs.asp.net/pwilson/archive/2004/02/14/73033.aspx

Hope that helps.


Actipro Software Support

Posted 10 years ago by SeongTae Jeong
Avatar
OK. Long time no see. :)
I've been too busy to reply your thread.

First off, I'm a big fan of .NET Framework. So I've already understood the knowledge of the link "http://weblogs.asp.net/pwilson/archive/2004/02/14/73033.aspx"

But, You missed an important thing!

GC manages its own heaps, and allocates .NET Objects there, however its heaps are allocated as private bytes, which can be monitored by Task Manager.

Let me show an example of memory leak by using Actipro DockSite.

This sample code is very simple as follows,
<Window x:Class="WpfApplication2.Window1"
    xmlns:docking="clr-namespace:ActiproSoftware.Windows.Controls.Docking;assembly=ActiproSoftware.Docking.Wpf30"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <docking:DockSite Name="applicationViewSite">
        <docking:SplitContainer>
            <docking:Workspace>
                <docking:TabbedMdiHost />
            </docking:Workspace>
            <docking:ToolWindowContainer>
                <docking:ToolWindow Title="Tool Window 1">
                    <Button Click="Button_Click">
                        <TextBlock TextWrapping="Wrap">Do test!</TextBlock>
                    </Button>
                </docking:ToolWindow>
            </docking:ToolWindowContainer>
        </docking:SplitContainer>
    </docking:DockSite>
</Window>
        public void Button_Click(object sender, RoutedEventArgs e)
        {
            while (true)
            {
                ToolWindow toolWindow = new ToolWindow(this.applicationViewSite);

                toolWindow.Title = "Test";

                toolWindow.Content = new UserControl();
                toolWindow.MoveToMdi();
                toolWindow.Activate(true);

                applicationViewSite.Documents[0].Content = null;
                applicationViewSite.Documents[0].Close();
            }
        }
After building, then execute this sample and press the button titled 'Do test!'.

As you can see, this sample do nothing, except of adding and removing dummy UserControl in the DockSite.

Performance monitor tools have shown the result,

[Figure 1. Memory leak to 1.2GB]
http://www.sysnet.pe.kr/syswebres/bbs/actipro_dock_site_mem_leak_1.png
[Figure 2. Memory leak to 1.5GB]
http://www.sysnet.pe.kr/syswebres/bbs/actipro_dock_site_mem_leak_2.png
[Figure 3. Memory leak to 1.7GB]
http://www.sysnet.pe.kr/syswebres/bbs/actipro_dock_site_mem_leak_3.png

Now, imagine the next [Figure 4].
If you are right, memory has to be fallen and risen again and again. At least the sample applicaion must not be exited.

unfortunately,

[Figure 4. Out-of-memory]
http://www.sysnet.pe.kr/syswebres/bbs/actipro_dock_site_mem_leak_4.png

What do you think? This application has no memory leak?


*** The web site "www.sysnet.pe.kr" will be running at KST 9:00 ~ 24:00.

[Modified at 07/12/2009 07:42 PM]

[Modified at 07/12/2009 07:43 PM]
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi SeongTae,

Your sample isn't an accurate test... let me explain. Per the documentation of Docking/MDI (specifically the "Lifecycle and Docking Management" topic), closing a tool window still keeps it registered with the DockSite. You must call Destroy instead.

I changed your code to this:
//applicationViewSite.Documents[0].Content = null;
//applicationViewSite.Documents[0].Close();
ToolWindow tw = applicationViewSite.Documents[0] as ToolWindow;
tw.Content = null;
tw.Destroy();
Also I limited the while loop to 1000 iterations and showed a MessageBox when complete. When I did all that and profiled the application, I did no see any ToolWindow controls building up in memory as you would see if your code was left as is. So that means all our references are being removed to ToolWindows if you call Destroy() (as opposed to Close()), which is correct per our design.


Actipro Software Support

The latest build of this product (v2019.1 build 0681) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.