Memory leak in ASP.NET web site


J

Jon Davis

I'm reposting this because I really need some advice.

I have a web app that makes many queries to the database on every page. In
order to save development effort, I've consolidated all database querying to
methods in a single static class, so whenever I need data, I pass a SQL
string to a method and I am passed a datareader or else individual values
(string, integer, etc).

There is a horrible memory leak in this application. Just one page load
results in a loss of about 50 MB. I COULD LIVE WITH THIS if only the memory
would be restored as soon as the web page response is finished, as I just
added another 512 MB of RAM to the server and there is never more than two
or three users hitting the site at the same time (there may be more users at
the same time, but within page load time frame there's never more than two
or three). I'm watching the Task Manager report memory usage skyrocketing
from 250 or so all the way up to 800MB in one user session, and it is never
restored until SQL Server and IIS services are restarted. SQL server takes
up about 1/3 of the excessive memory loss, and IIS takes up about 2/3 of the
excessive memory loss.

Here is what I have done to try to resolve this matter.

1. All generic functions that create datareaders to retrieve individual
values from them now forcefully close the datareader (but not necessarily
the connection).

2. All database connections and datareaders are stored into ArrayList
objects which are stored in the Session. (Dangerous, I know! ... but please
follow me.)

3. All web pages that utilize these database functions inherit from a
CommonPage class. I have created a deconstructor in CommonPage that goes
through all the objects in the connections and datareader ArrayLists in the
Session and *closes* them and removes them from the ArrayLists.

4. An "AppUser" object, stored in the Session object, had been created with
a cache so that the data retrieved from the database would remain in memory
to speed up page loads. The cache is now destroyed in the CurrentPage
deconstructor.

5. The garbage collector is executed in the deconstructor.

Nothing is being stored in the Application collection.

The end result of the above is SOME savings of RAM on the development
machine (about 20% less loss), but little no change on the server for some
reason, though I'm not sure. The development machine is running XP Pro and
the server is 2003. In any case, a person still cannot go through the entire
web site (a web-based survey) without crashing the server.

I have been pulling my hair out for a week or two trying to figure out what
the cause of this mess is. This is very important to me.

Please help, anybody!

Jon
 
Ad

Advertisements

A

ASP.Confused

In your page_load function toss this at the end of it...

GC.Collect()

It's called a garbage collector (good name.)
 
A

ASP.Confused

Also make sure that if you have any references you don't need, to
dereference them.
 
J

Jon Davis

See #5 of my post.

Jon

ASP.Confused said:
In your page_load function toss this at the end of it...

GC.Collect()

It's called a garbage collector (good name.)




querying users
 
J

Jon Davis

ASP.Confused said:
Also make sure that if you have any references you don't need, to
dereference them.

Thank you. But I am not that newbie, and unless I'm keeping things in the
Session or Application, all references get dereferenced when they fall out
of scope.

Jon
 
A

ASP.Confused

Sorry, had to cover all bases :)

Ok. I've only had this issue when I have had a runaway query (I still use
ADO in .NET)...but I wouldn't think that would be the problem.

You could try using SysInternals listdlls, which lists all the DLL's that
are being used by a specific application. It is a very useful tool, and
will tell you what dlls are using the most memory. This may point you in
the right direction.
 
Ad

Advertisements

J

John Saunders

Jon Davis said:
I'm reposting this because I really need some advice.

I have a web app that makes many queries to the database on every page. In
order to save development effort, I've consolidated all database querying to
methods in a single static class, so whenever I need data, I pass a SQL
string to a method and I am passed a datareader or else individual values
(string, integer, etc).

There is a horrible memory leak in this application. Just one page load
results in a loss of about 50 MB. I COULD LIVE WITH THIS if only the memory
would be restored as soon as the web page response is finished, as I just
added another 512 MB of RAM to the server and there is never more than two
or three users hitting the site at the same time (there may be more users at
the same time, but within page load time frame there's never more than two
or three). I'm watching the Task Manager report memory usage skyrocketing
from 250 or so all the way up to 800MB in one user session, and it is never
restored until SQL Server and IIS services are restarted. SQL server takes
up about 1/3 of the excessive memory loss, and IIS takes up about 2/3 of the
excessive memory loss.

In another post you say that you're not a newbie, so I hope you don't find
the following insulting:

Are you losing virtual memory or physical memory? When the memory maxes out,
do you start paging?
 
J

Jon Davis

When the page class deconstructs, yes, I have a manual closing method. See
first post.

Jon
 
J

Jon Davis

Yes, it starts paging when total used ram reaches about 700-800MB. That's
when the app crashes. "Timeout while allocating memory." There is 768MB of
physical RAM installed.

Jon
 
Ad

Advertisements

C

Chris Botha

I don't know how relevant this is, but I had a problem with a Windows
Service connecting to SQL Server that accumulated memory and later on
degraded the performance of the computer.
After about a week of hunting the problem, Closing and Disposing everything
I could lay my eyes on, I came upon some newsgroup with an article that
fixed it. In the Connection String of the Connection, I've added
"Connection Lifetime=1" . This influences the Connection Pooling, but hey,
it fixed my problem (which made me extremely grateful). The memory use
(private bytes) fluctuates between 130 and 150 MB and it has been purring
like a kitten for more than a month now on the client site.
 
B

bruce barker

now you've learned the danger of Datareaders. no component should return one
(as you can never trust the caller to release them). they should be created
and destroyed in the same method with a finally or use statement. change
your code to use datasets (which are much lighter and safer to store in
caches).

make the connection pool small to try to detect connection leaks.

try moving cleanup code to page unload

use devpartner to find the leak:

http://www.compuware.com/products/devpartner/studio.htm


-- bruce (sqlwork.com)
 
J

Jon Davis

Thank you, Chris. I had high hopes for such an easy fix, but this still does
not resolve my problem at all.

Jon
 
J

Jon Davis

On second thought, after a few minutes the memory came back .. this could be
it?

Jon
 
J

Jon Davis

Thank you bruce,
try moving cleanup code to page unload

I don't know if I fixed the problem, but the memory seems to be restored on
my development machine. I did the above ("> ") and Chris Botha's advice ..
will post here once I figure out which one did it, or whether both did it.

Jon
 
Ad

Advertisements

C

Chris Botha

It could be it, in my case it fluctuates, goes up and comes down all the
time (the Windows Service does its thing every minute). Should be
interesting, let us know.
 
J

Jon Davis

Really hard to tell. Task Manager is showing fluctuations. I do think BOTH
are helping a great deal. However, I still see 50MB loss after a 100MB-loss
test session.

Jon
 
Ad

Advertisements

A

ASP.Confused

You could try using SysInternals listdlls, which lists all the DLL's that
are being used by a specific application. It is a very useful tool, and
will tell you what dlls are using the ***most memory***. This may point you
in
the right direction, and it may even tell you what assembly is causing the
problems

(or you could also use Microsoft's CLR Profiler, which is free from
Microsoft.)
 
Ad

Advertisements


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