.NET eating memory (minimize then maximize the app)

1 view
Skip to first unread message

ali

unread,
Aug 21, 2003, 5:25:44 PM8/21/03
to
Hi,

We ran to a performance problem in Windows Forms
application that already another guy faced it. The problem
is, the application alocates a big memory (100 MB) at the
start point. If we minimize the app, and then maximize it,
it magically releases the memory (back to 5MB). again
allocates a big memory when go thro other Forms in the app
and releases it when just minimize & maximize it. so, same
we have to minize&Mazimize the app programaticaly after
any action.

You may see it in your application by monitoring Memory
consumer in process tab in windows task manager.

Here is the link for this problem that already posted:
http://www.dotnet247.com/247reference/msgs/15/77895.aspx

Any resolution for this problem?

Michael Giagnocavo [MVP]

unread,
Aug 21, 2003, 5:47:13 PM8/21/03
to
You can try calling Kernel32.dll!SetProcessWorkingSetSize. I believe
this will trim the working set for you.
-mike
MVP

"ali" <chad...@yahoo.com> wrote in message
news:0c1501c3682a$c7784910$a001...@phx.gbl...

ali

unread,
Aug 21, 2003, 6:13:44 PM8/21/03
to
Mike,
Thanks for the reply. However this does not compile in
.Net framwork.

This is what i put in Dispose() method of Form, but could
not recognize Kerne132.dll.

Kernel32.dll!SetProcessWorkingSetSize(hProcess, -1, -1)

Any thing else i missed?

>-----Original Message-----
>You can try calling Kernel32.dll!

>.
>

ali

unread,
Aug 21, 2003, 8:11:18 PM8/21/03
to
Mike
thanks. i got my answer from your tip.


>-----Original Message-----
>You can try calling Kernel32.dll!

>.
>

Michael Giagnocavo [MVP]

unread,
Aug 21, 2003, 8:27:17 PM8/21/03
to
You'll need to use the P/Invoke syntax:

using System.Runtime.InteropServices;

[DllImport("Kernel32.dll")]
public static extern SetProcessWorkingSetSize(IntPtr, int, int); //
At least I think that's the correct signature.

-mike
MVP

"ali" <chad...@yahoo.com> wrote in message

news:04f101c36831$7c45eef0$a401...@phx.gbl...

Niall

unread,
Aug 22, 2003, 3:02:36 AM8/22/03
to
Be aware that by minimising and remaximising your form, or by trimming the
working set, you are not actually deallocating memory. Windows just moves it
to virtual memory, and it will be loaded back in as needed. This is why you
have to reminimise your app after some time, because all the memory it was
using gets brought back into the physical memory.

This behaviour happens in all Win32 applications, you can see the same from
using notepad and watching its memory usage in the task manager. It just
seems to be more pronounced in .Net applications.

Niall

"ali" <chad...@yahoo.com> wrote in message

news:049501c36841$e8cc4550$a601...@phx.gbl...

Michael Giagnocavo [MVP]

unread,
Aug 22, 2003, 12:10:50 PM8/22/03
to
That's not correct. While it *might* do some virtual memory swapping,
it doesn't always do that. In my tests with some apps, I saw no
change in the virtual memory usage for the process (well, sometimes it
went down), and when restoring the window, in total, less RAM and
virtual memory were in use.
-mike
MVP


"Niall" <as...@me.com> wrote in message
news:OAW8esHa...@tk2msftngp13.phx.gbl...

Niall

unread,
Aug 24, 2003, 8:54:57 PM8/24/03
to
Are you just using task manager to get your numbers? It's not a great tool
for watching managed apps. If you use something like the .Net Memory
Profiler, you can cause the working set to be trimmed. The amount of
physical memory in use drops dramatically, but the amount of committed
memory remains the same. Now, I don't know too much about when windows
decides to actually page data out to the disk, but what I suspect is
happening is that the memory which is now not classed as part of the actual
physical memory usage is flagged as potential swap out data. If memory is
low or another process needs to use the memory, then it will be swapped out,
and then you will see your virtual memory usage increase.

From the memory profiler help file:

"Trim working set

This button can be used to trim the working set of the selected process. All
physical memory is swapped out to the paging file, module or memory mapped
file. It effectively sets the used physical memory to zero. As soon as
memory is needed, it will be swapped back into physical memory.

By trimming the working set, it is possible to find the physical memory
requirements of the process. Since all memory is swapped out, the physical
memory presented is only the physical memory used after trimming the working
set, any memory used only for startup of the process will not be included. "

Every time I've seen people talk about trimming the working set, it's been
said that it just moves things out of physical memory. Perhaps there's
someone here who knows more about it than I do who can clarify this.

Niall

"Michael Giagnocavo [MVP]" <mggU...@Atrevido.net> wrote in message
news:ub1P2nM...@tk2msftngp13.phx.gbl...

Pavel Lebedinsky

unread,
Aug 26, 2003, 2:56:03 AM8/26/03
to
A couple of points:

First, trimming the working set doesn't actually write the
pages to disk. Typically the pages are moved to a "standby list"
and the next time the process tries to access them they
will be "soft-faulted" back into the working set (as opposed
to a "hard" page fault which requires reading the page
from disk). You can see all this in perfmon if you monitor
working set, page faults and disk reads/writes.

Second, emptying the working set (by minimizing the app or
by calling SetProcessWorkingSetSize) does nothing to improve
performance. In fact, it's likely to make things worse
by causing lots of (soft) page faults when the process tries to
access the trimmed pages.

If your app has a 300 MB working set it doesn't mean
the OS or other applications can't use that memory.
In fact the OS will trim your working set as necessary.
By calling SetProcessWorkingSetSize(-1, -1) you tell
the OS to empty your working set regardless of other
factors, and often this is not the best thing to do.

Now obviously a 100 MB working set is better than 300 MB
but the right way to achieve this is to reduce the number of
object allocations and/or code that is brought into the process.
Emptying the working set is cheating - it makes your process
look nice in task manager, but it doesn't "free" any
memory or make things more efficient in any way.

All this applies equally to managed and unmanaged code
by the way. Managed garbage collection and working sets
are totally unrelated concepts.

Niall

unread,
Aug 26, 2003, 7:21:13 PM8/26/03
to
Thanks pavel, that cleared a few things up for me.

Niall

"Pavel Lebedinsky" <m_...@hotmail.com> wrote in message
news:uVRTs85a...@TK2MSFTNGP10.phx.gbl...

Michael Giagnocavo [MVP]

unread,
Aug 27, 2003, 11:28:51 AM8/27/03
to
I'm going by the task manager to see what is reported as "owned" by a
process. As Pavel pointed out, this does not improve performance.
Only do this when a customer complains about "oh, it has a memory
leak" because they do not understand how the system works.

Also, I was referring to Win32 apps in general (such as Outlook
Express, which had 19MB Physical, 8 Virtual. Minimizing it and
restoring it changed to 5MB physical, 8 virtual), not just .NET apps.

-mike


"Niall" <as...@me.com> wrote in message

news:%23m1%23iMqaD...@tk2msftngp13.phx.gbl...

Mark

unread,
Aug 29, 2003, 11:54:14 AM8/29/03
to
"Pavel Lebedinsky" <m_...@hotmail.com> wrote in news:uVRTs85aDHA.1640
@TK2MSFTNGP10.phx.gbl:

> If your app has a 300 MB working set it doesn't mean
> the OS or other applications can't use that memory.
>

This is important. Memory in the working set *DOES NOT* correspond directly
to physical memory.

I.E. if you have 256mb of memory in a machine, you can have more than a
total working set size across all processes of more than 256mb. Working set
and "in use" are not the same.

If your customers are confused, do developers everywhere a favor and
educate them, don't hurt your app's performance to make them feel warm and
fuzzy.

Mark

Jon Rista

unread,
Aug 31, 2003, 5:08:27 AM8/31/03
to
Pavel has it right. The "working set" for an application is the memory that
is most likely going to be needed by the application in recent time. By
minimizing the working set of your application, your just temporarily
lowering the amount of data the application has immediate access to.

The problem with minimizing the working set is that it will cause a greater
number of page faults to load the needed data back into the working set.
Page faults are a negative thing for an application, since extra cpu cycles
are needed to move data from the hard disk or or the "soft-fault" area (as
Pavel so eloquently put it ;) ), into physical memory. Of course, moving
data from a soft-fault area is faster than moving it from the hard disk, a
penalty is still incurred, and performance of your application will go down.

Something that I only recently found out is that windows has several
different "types" of memory for an application. There is data that can only
be held in physical memory, data that can only be held in virtual memory and
never in physical memory, and there is data that can be "paged" out of
physical memory to virtual memory and back. Windows will maintain a full
working set of all your data in virtual memory at all times, save
non-pagable data. What that means is that your virtual memory usage will
normally be equal to or greater than your physical memory usage. When you
minimize your working set, windows clears out data from your applications
working set as low as possible, leaving only non-pagable data and data that
was most recently accessed. When this cleared data is needed again, a
page-fault occurrs, and windows copies the data from virtual memory into
physical memory. Some applications have large non-pagable data regions, and
these applications often have smaller virtual memory allocations than their
physical memory allocations (just in case you wondered. ;)).

It seems that .NET applications try to keep as large a working set as
possible, with as much data in memory at any given moment as possible, to
reduce page-faults. For some reason I have yet to figure out, .NET
page-faults a lot more than non-managed applications, which is a source of
performance drag for all .NET apps. By calling SetProcessWorkingSetSize(),
your only going to increase an already too-large number of page-faults,
dragging the performance of your application down even more. Unlike C++,
where you manually manage memory, .NET apps have automatic memory management
through the GC and the .NET runtime. Its generally best to let the framework
handle memory management for you to maintain the best performance with a
.NET app. The GC and .NET runtime will automatically manage the working set
of a .NET application based on how much physical memory is available on a
system. An application that uses 300 megs (of physical memory) on one system
may use only 50 megs on another. Memory management in .NET is probably one
of the prime areas where Microsoft will be optimizing and perfecting the
framework, and hopefully future releases of the framework will offer better
performance with less page-faults than .NET 1.0 and 1.1.

I'll be posting a question about this subject in this newsgroup, as I have a
.NET application that is incurring millions of page-faults and which has
very poor performance. I can't quite figure out why so many page-faults are
beeing incurred, and I am hoping someone with more knowledge of .NET's
memory management will have some tips for me.

Jon Rista

"Pavel Lebedinsky" <m_...@hotmail.com> wrote in message
news:uVRTs85a...@TK2MSFTNGP10.phx.gbl...

Jim Hogg

unread,
Sep 2, 2003, 6:50:16 PM9/2/03
to
As Pavel explained, OS working-set trimming is not the solution to the
original problem. It makes available pages from your process for
potential use by other processes. But if you want to actually
continue running your app, you're actually making it worse! -- as you
soft-fault the pages back from the free-list.

Note that WS-trimming does not call the CLR garbage collector.

But going back to the original question -- why do you believe there's
a problem? The CLR memory manager senses what else is running on the
machine. If it's quiet, it will use more RAM on your behalf. If you
start another app that competes for memory (even a conventional,
unmanaged app), the CLR memory manager will cut back its use. Maybe
it's just this effect you are observing?

If you want to experiment, try GC.Collect -- this will force a Garbage
Collection. ie. it will locate live objects, and enqueue Finalizers
for any just-died objects. But it might, or might not, perform a
compaction -- again, depending upon whether it senses plenty of memory
available. But normally, you should not have to tweak around with
this call.


Jim

==========


"Michael Giagnocavo [MVP]" <mggU...@Atrevido.net> wrote in message news:<unVO0CLb...@TK2MSFTNGP10.phx.gbl>...

Michael Giagnocavo [MVP]

unread,
Sep 3, 2003, 10:29:59 AM9/3/03
to
I only suggest that to improve the "appearance" of having a bloated
app. *I* don't mind how the memory is managed, but the original
question was something along the lines of "minimize and maximize
programmatically".

-mike
MVP

"Jim Hogg" <jim...@microsoft.com> wrote in message
news:aa9233b6.03090...@posting.google.com...

Reply all
Reply to author
Forward
0 new messages