GC on a Session Variable

G

Gonenc Ercan

Hi,

I ve ended up debugging a ASP.NET project (with about 380 files on the
project .NET Framework 1.0 on IIS 5.0) which has a memory leak... The memory
rises too fast. With about 25-30 active sessions (average) the memory rises
about 300 MB's in an hour. I've checked the database (SQL Server 2000) and
seen that there are lots of sleeping connections. (about 400!!!) I thought
somewhere in the code they left the connection open, so decided to log every
closing of the connection. I found out that connection is never closed...
The connection object is kept in session . (for each session at least 3
connection is opened and 1 connection is stored session) What I am
wondering is; could it be the connection object filling up the memory? Since
it is kept in the session and never disposed would it stop the GC from
collecting the other session variables? I ve found out that there are
Placeholders in the session too... could it be the case that the connection
is holding the placeholders from being collected.

Does asp.net open a new instance for each new session? If it is, when does
that instance killed? at session time out?

I cant close the connection cause the project is too big and online database
objects are used in almost each file. I did put a con.close() at Session on
end but it doesnt seem to be firing cause I am also logging to text file in
Session on end and it does nt seem to log anything.

Another interesting thing is that the machine has 2 GB physical memory but
when the memory reaches 0.8 - 1 GB I get the System.OutofMemoryException.
Why is that? why cant the Application use the free 1 GB?

Gonenc
 
A

Alvin Bruney

The connection object is kept in session . (for each session at least 3
connection is opened and 1 connection is stored session)
For a web app, this is a cardinal sin, which is one of the reasons why the
application is not scaling properly. Just opening a bare bones connection
takes 40kb of data on the average so do the math. Connections stored in
session have references, garbage collection cannot occur while this
reference exists therefor memory is leaked.

What's a sleeping connection?

Something else concerns me. Is connection pooling on? The pooling mechanism
works on exact connection string matches so for example if you were building
out your connection string or modifying it in anyway, connection pooling
would not work and connections would pile up in memory.
 
A

Alvin Bruney

I hit send by mistake, sorry i wasnt done yet.
I found out that connection is never closed...
Connections are never closed when connection pooling is on. They are just
flagged as closed and sent to the pool to wait it out so if you opened and
closed 5 connections on the same connection string, you are really using the
same object from the pool. If you muck with the connection string or
connection pooling is off, you are using 5 different objects. The
application will fail to scale.
Does asp.net open a new instance for each new session? If it is, when does
that instance killed? at session time out?
Session should be cleared at session end but by default that is 20 minutes.
If you have large objects in session, memory can quickly pile up. Also check
your datasets to see if you are nulling them out after using them. It's easy
to write a web application, its difficult to master the art of building a
well behaved web application.
 
G

Gonenc Ercan

thanx for the quick reply Alvin... First of all I did not write the code...
I am just trying to keep it running, my company bought such a bad code from
a "software company"... I did not actually check if the connection pooling
is on... it must be on from default right? I did check the connection
string. All the connections are opened with the exact same connection
string. But since the connection is never actually closed I think it never
does make it back to the connection pool. What I meant by connection is
never closed is, there is no con.Close() statement!!! (I ve added to Session
on end at global.asax but i am not sure that it is firing in each session)

All the DB operations are done with datareaders, no datasets... I did try
null ing each datareader on the project after using it but it did not help
at all... Sleeping connections are the connections in SQL Server (I checked
it from SQL Server enterprise manager) with the sleeping status.. I saw a
connection opened 12 hours ago.. Either it is pooled and reused or it is
unreferenced and kept open? (but it will eventually timeout and 12 hours is
too much for a timeout? right? )
Connections stored in session have references, garbage collection cannot occur while this
reference exists therefor memory is leaked.

Does the GC collect an object which contains an object which is referenced.
So in this case; Session contains a connection which is referenced, so
session stays in the memory to? So instead of 40 KB of the connection I end
up with a leak much more higher...

I still cant understand why out of memory exception is thrown while there is
1 GB physical memory available... Does IIS 5.0 and framework 1.0 have a bug
like this? Is there a limit on ASP.NET applications?
It's easy to write a web application, its difficult to master the art of building a
well behaved web application.

tell me about it... I have being debugging this problem for 2 weeks... I
even thought of writing the whole project from scratch and found out that
the software is written from scratch by the seller company... (I will
install the new version, but I have to keep the old one up for a while... )
I think this is just a perfect example of what you have said...



Thanx

Gonenc
 
A

Alvin Bruney

string. But since the connection is never actually closed I think it never
does make it back to the connection pool.
There are very few instances when this is good. Connections, as rule, should
be closed immediately after they are used. It's not a good idea to wait
until session_end because, there are a few instances when session_end does
not get called. Is there a good reason for these connections to remain open?
If not, manually close the connection after it is used or put a using
declaration around the connection object like so.
using( oledbconnection db = new oledbconnection())
{
//use it here
}// it gets closed and disposed automatically here whether or not an
exception occurs.

Sleeping connections are not always the fault of the code. In my case,
sleeping connections were actually the fault of the informix engine and it
required a service pack to patch it up. You may want to make sure your
database engine is correctly plugged and patched first before touching your
code.
So in this case; Session contains a connection which is referenced, so
session stays in the memory to? So instead of 40 KB of the connection I end
up with a leak much more higher...
The session doesn't stay in memory but rather the object stored in session
remains. If this object is a dataset, you are leaking serious memory because
it will persist until the application domain unloads or the reference is
removed, whichever happens first.

You may want to check the size of your memory allocation on the server to
see what it is set to. In addition, you may want to aggressively lower the
memory recycle property of IIS. By default it will recycle the app after 60%
consumption. I've set mine to 40% because I don't want the appserver to
crawl to a halt when memory becomes an issue. Also, the task manager does
not correctly report memory consumption. It's just a ruff estimate. You need
a more potent tool like memory profiler available from microsoft. In
addition to that, you need to start doing some sort of instrumentation on
the webserver - monitoring memory consumption using perfmon logs to get a
clearer picture of just what is going on. That's all I can think of for the
moment. I've had similar leaky apps, and it boils down to plain old elbow
grease to solve it.
 
E

Eric Newton

I have to second Alvin on this, keeping connection references in Session is
a horrid idea and whoever designed it obviously didnt understand anything
about ASP.Net

That point said, you're gonna need to do some rewriting, in the sense of
explicitly opening and closing connections when used.
 
A

Alvin Bruney

I figure the technology is new and not every programmer knows best
practices. Learning takes a while, in that while, the software suffers and
so does the client. Which is why customers don't think highly of developers
either.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top