I have solved my memory
issue on my Windows VPS. My scenario:
Windows 2003 VPS on Virtuozzo with 384 MB of
RAM, Smartermail enterprise configured for IIS website.
My issue was that the IIS
worker process, w3wp.exe, would skyrocket to 170 MB of memory usage as soon as
the first person connected to the webmail. Over the course of a day, the
process would not hand memory back to the OS, my system would slow down and
eventually crash with the following events in the application log:
Event Type: Warning
Event Source: ASP.NET 2.0.50727.0
Event Category: Web Event
Event ID: 1309
Description: Event code:
3005 Event message: An unhandled exception has occurred...
And
Event Type: Error
Event Source: .NET Runtime
Event Category: None
Event ID: 0
Description:... .NET
Runtime version : 2.0.50727.1433 - Application Error.
The short story is,
modifying the Aspnet.config file with <gcServer enabled=”false”/> solved
my issue. (Microsoft article ID 911716)
The long story is – The .NET
language runtime environment absolves the developer from worrying about
tracking and freeing memory. Instead the developer can focus on what the code
is supposed to do, while garbage collection manages memory for the .NET
application. On a multiprocessor system garbage collection will consume a lot
of memory because it creates one heap per processor for parallel collections.
Thus, the w3wp.exe process will start and quickly consume a large amount of
memory on a multiprocessor system.
The catch – how often does
a system have 4 processors (as seen in Task Manager) and 384 MB of physical
memory? With Virtuozzo this may be more common than you think. I learned about
Virtuozzo when I researched Windows hosting to find an inexpensive VPS. Whereas
VMWare and Virtual Server will virtualize the hardware, creating a completely
separate environment for the guest OS, Virtuozzo runs the virtual private
servers as instances of the base (or hardware) OS. Apparently I am seeing the 4
processors that exist on the base OS. And so is ASP.NET. Thus ASP.NET created
one heap per processor, immediately consuming 170 MB of memory on my 384 MB
VPS.
Modifying the Aspnet.config
file to force .NET to work in Workstation mode (using only one heap) reduced
memory of w3wp.exe to 55 MB upon start.
Most people with
multiprocessor systems have gigabytes of memory and probably don’t care that
w3wp.exe consumes what it does. In fact, your performance will be improved by
running the garbage collector in server mode.
Finally, you may be asking,
why didn’t Asp.net give memory back when the OS needs it, as it should?? Apparently
garbage collection will reduce the committed bytes of memory but not actually
give the memory back to the OS. This results in performance improvements for
.NET. The garbage collection will give memory back when a low memory
notification event occurs, which is when a threshold of X MB is left on the
system. Apparently the threshold is too low and garbage collection is not quick
to respond.
As I read through my many
Microsoft KB articles, I finally realized that the exception information in the
1309 event “Exception type: OutOfMemoryException” really meant I was out of
memory. The w3wp.exe was not giving it back to the OS. At least not quick
enough to prevent application errors and services failing.
References –
Excellent overview of .NET
memory usage with the good and the bad,
http://weblogs.asp.net/pwilson/archive/2004/02/14/73033.aspx
Garbage Collection:
Automatic Memory Management in the Microsoft .NET Framework
http://msdn.microsoft.com/msdnmag/issues/1100/gci/
How to modify the
Aspnet.config for Workstation mode of Garbage Collection
http://support.microsoft.com/kb/911716
Side note: In the properties
for the SmarterMail application pool, setting the “recycle worker processes at
the following times” isn’t a bad idea. This is more graceful than a iisreset or
reboot to clean up memory. I have mine with one time in the middle of the
night.