Link to home
Start Free TrialLog in
Avatar of sachinjain_aspnet
sachinjain_aspnet

asked on

System Out of Memory Exception

Hi

I am having an application running on production server. There are around 100 domains running on that server though we are not getting muhc traffic right now we are getting 2,500 unique Visitors. Now twice a day I get system out of memory exception ..and by applying so many things ..I am unable to solve it .. The structure of my application is 3 Tier .. and following is the code for classes I am using ...I want to know is anything in classes I am doing wrong which is causing it. Please see the code below. This is just a sample class.

For further information. I am using Idisposable for all my classes and also using supressfinalize in dispose method. For access all classes I am USING keyword .. May be i missed it for some classes ..but I don't think it really affect ?

Also I have checked my all SQL connections are getting closed properly. using sp_who command .. generally I see around 2500 connections among 7 databases which I am using in my application ..as my application is a portal.
using System;
using System.Data;
using System.Collections;
 
/// <summary>
/// Summary description for clsCarPayments
/// </summary>
public class clsCarPayments : IDisposable
{
    #region --Declare Variables --
    int intAgentId = 0;
    Hashtable HTable = new Hashtable();
    clsCarDb objDatabase;
    #endregion
 
 
    #region --Declare Properties --
 
  
    public int AgentId
    {
        get { return intAgentId; }
        set { intAgentId = value; }
    }
 
    #endregion
    public clsCarPayments()
	{
		//
		// TODO: Add constructor logic here
		//
	}
 
    //~clsCarPayments()
    //{
    //    
    //}
    public void Dispose()
    {
        GC.SuppressFinalize(this);
    }
 
    public DataTable getAgentPayments()
    {
        using (objDatabase = new clsCarDb())
        {
            HTable.Clear();
            HTable.Add("AgentId", intAgentId.ToString());
            return objDatabase.procFetchRecord_DS("uspSelectAgentPayments", HTable).Tables[0];
 
        }
    }
}
 
 
------------------------------------------------------ Following is the database class function------
 
 public DataSet procFetchRecord_DS(string procname, Hashtable Htab)
    {
        try
        {
 
            sqlCmd = new SqlCommand();
            sqladp = new SqlDataAdapter();
            sqlds = new DataSet();
 
            sqlCmd.Connection = con;
            sqlCmd.CommandType = CommandType.StoredProcedure;
            sqlCmd.CommandText = procname;
            IDictionaryEnumerator ObjEnumerator = Htab.GetEnumerator();
 
            while (ObjEnumerator.MoveNext())
            {
                sqlCmd.Parameters.Add(new SqlParameter("@" + (ObjEnumerator.Key).ToString(), ObjEnumerator.Value));
            }
            sqladp.SelectCommand = sqlCmd;
            sqladp.Fill(sqlds);
 
        }
        catch (Exception ex)
        {
            sRetVal = ex.Message.ToString();
            //     sqlTran.Rollback();
        }
        finally
        {
            closeDBConnection();
        }
        return sqlds;
 
    }

Open in new window

Avatar of Muhammad Ousama Ghazali
Muhammad Ousama Ghazali
Flag of Saudi Arabia image

Although the version of .NET you are usign is not mentioned, but if it is .NET 1.1. in one or more websites hosted, please consider seeing these two official fixes for your problem:
http://support.microsoft.com/kb/888419
http://support.microsoft.com/kb/825680
the class looks ok to me - what are the machine specs?
also - how do you have IIS setup? how many concurrant users do you have? If you profile the server using perfmon can you see the memory being released properly or does it steadily increase?
You might want to think about how often the application pool recyles - do it more often to release some memory??
Avatar of sachinjain_aspnet
sachinjain_aspnet

ASKER

Sorry not to mention version ..I am using .net 2.0
I am recycling worker process at every 12 hour. This resolve my problem but I don't want to do that ..I want to know actual reason why it is happening. Just recycling worker process doesn't give actual solution of this
what about my other questions:
what are the machine specs?
also - how do you have IIS setup? how many concurrant users do you have? If you profile the server using perfmon can you see the memory being released properly or does it steadily increase?
You have something very odd in your code. You are asking why you use up a lot of memory and then you state this:

For further information. I am using Idisposable for all my classes and also using supressfinalize in dispose method. For access all classes I am USING keyword .. May be i missed it for some classes ..but I don't think it really affect ?
which is effectively saying "I use suppressfinalize to prevent my classes to be garbage collected". If you do that, the objects having that, will never be freed. Unless there is a very specific reason to use IDisposable i.e., using unmanaged sources that need to be finalized) you do not need it. And if you use IDisposable (or a class that uses it), there are only very few reasons to need SuppressFinalize.

I suggest removing all those lines and try again.

PS: testing for the memory usage is not enough. You may run out of memory before you system runs out of memory. That is because the CLR in ASP.NET uses its own pool. You can trace that using Performance Monitor.

-- Abel --
GuitarRich

System Configuration are as follows

CPU INTEL Pentium-IV x86 Family 15 Model 4 Stepping 3 ~3600MHz
Version psa v8.4.0_build20080505.00 os_Windows 2003/2008
OS Microsoft Windows 5.2;build-3790;sp2.0;suite272;product3
RAM - 2GB

Regarding concurrent users - I don't know exactly as I don't know how to watch it. But you can take a guess on average we are getting 3,000 hits per site per day NOT UNIQUE VISITORS

good call abel - I missed that. Try that suggestion
This explains my point more thoroughly: http://stackoverflow.com/questions/151051/when-should-i-use-gc-suppressfinalize

More to the point: you should call SuppressFinalize only AFTER everything is freed. In your case, there's no reason to use IDisposable (you do not use unmanaged resources) so you should not need to use SuppressFinalize either.

Remove all cases where you implement IDisposable, apart from those situations where you really need to do cleanup (close open file handles for instance). In the cases where you really need to do cleanup, remove SuppressFinalize.

You say you use using-statements. That's good. You should use them on classes that expose the IDisposable interface (streams come to mind). It is not always necessary, but it is better to be safe then sorry. Only rarely you will need it for your own objects.

-- Abel --
So Abel

According to you ..I should remove I disposable from all classes .. even database class as well ?
(tx, GuitarRich)

On another angle: while you are fixing your code, you don't want the current site to run out of memory all the time. Check the following (if you haven't already done so) and increase (see screenshot, max virt mem),

Depending on the occurrence frequency, you can configure IIS to restart your web application on fixed times. This is only a temporary workaround until your code is fixed. But it will prevent your visitors to move away. If you have a StateServer, there sessions will remain, otherwise, your users need to logon after restart. It is not a machine restart (see screenshot, recycle worker processes in minutes).

This screen looks different on IIS6/7, but the idea is the same.

ScreenShot293.png
another option might be to use a web garden - give the application pool a number of worker processes to share out the memory load - you would definitely then need the session setting out of process tho - it might be less work just to change your classes as abel has suggested.
> even database class as well ?

what do you mean with a database class? If you mean the entities that represent your data, then yes. If you mean the classes that use your database any which way then yes (but keep the using-statement for your sqlconnection etc). If you mean classes that act as a database by exposing or inheriting from existing database classes then yes.

Only if you created your own ODBC driver wrapper or something becaue you access some exotic database, you may access unmanaged code or resources with your class and keep pointers to them. Think about C++ interfaces or that sort of thing. If the CLR cannot do it automatically, you need to help. But very rarely I see this in practice.

Now there may be cases where you keep a reference to an object that exposes IDisposable itself, and you keep them in your member variables. In those cases, you may also implement the IDisposable interface, but only strictly to cleanup (not yourself, but the references). Here's how such frame should look like: http://www.codeguru.com/csharp/.net/net_general/debugginganderrorhandling/article.php/c14173
By now it is time to tell a little about what IDisposable actually does. It doesn't do much on its own. If it is used properly in try/finalize blocks or within a using-block, then it will prevent memory leaks (at least, that's the idea).

Even if you don't use using-blocks and you don't use try/finalize, the memory will be freed in most cases. Only when exceptions occur, memory may not be freed correctly.

Applications that are sloppy with try/finalize and using-blocks see a slow memory increase sometimes, but if no errors occur, nothing wrong will happen, really.
thanks abel .. now I will remove idisposable and suppresfinalize from all classes .. though i have 100 of classes ...it take some time ..and its reaction need be watched which will take 2-3 weeks ..if everything okay ..otherwise i will come back again
Ok, good luck with the cleanup process. Be careful about those situations where you do need them, please read the two links carefully, I chose them for there clarity and brevity.

Note that it never hurts to use a using-block, and it often doesn't hurt to use a IDisposable implementation, but the extra work is void  (see my last link on how a good implementation should look in those cases where it matters) but SuppressFinalize is probably your real problem here (and do notice, too, that there may be other forces at play that push your memory. I.e., a session that has a long timeout period, or large objects attached to the session, cache or globals etc).

While you are working on it, you can (or not) choose to use the tips I gave you about IIS to prevent your site to show Memory errors to your end-users.
Abel

I am already using web garden and worker process recycle so that error doesn't come. But I also need to clean up my code.

Regarding the session on every request there are 6-7 session variables made. I have session time out to 20 minutes in web.config file. Login sections are seperate for which we create session/cookies. I don't think they will hurt do they ?

SupressFinalize i will remove from all my classes but will use in database class to make sure that connection of current object get closed every time after calling dispose method
ASKER CERTIFIED SOLUTION
Avatar of abel
abel
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi Abel

Can you give me your email ? I think its best I email you some of my sample files of project and you can tell me flaw in coding ?
I wouldn't mind doing so, but if I would, I am violating EE guidelines. My email address is in my profile, normally it should only be used when professional services are requested (which I wouldn't mind you requesting, of course, but in which way it is probably easier to setup a VPN bridge of some sort ;-)
well Abel, I just want to send code to see you If it resolve my problem i won't mind paying but my error shud be resolve at last and i hope thats not much ...coz i am a normal developer :) i will be sending you email from my gmail account .. i hope you will get those files
Yes, I've seen the files, thanks. The main thing I looked at was your database class, I didn't look at the other classes. Inside the database class you have a properly implemented IDisposable interface, but (possibly amongst other things) it does not call Dispose for the "con" member (the connection object), which will mean in practice that the connection pool and some other stuff may stick around.

I also saw something odd in the  constructor: when the connection is closed, it opens it, when it is open, it will close it. It will never be open upon creating, so this code is moot, but it doesn't harm either. Didn't check futher, though.

PS: note that calling .Dispose() will always also call .Close() for any classes in the CLR, if a Close() is applicable.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I think more points should be on offer here! definitely going above & beyond the call of duty here abel!
That's nice, but it's all in the service, so far ;-)
In the line of "what to read to understand IDisposable" and implementing it oneself better, this is yet another excellent read. Check out the code of the first answer (8 votes at the time of this writing): http://stackoverflow.com/questions/792660/is-gc-suppressfinalize-guaranteed

I uses just a slightly different wording that might make the whole process more clear to you.

-- Abel --
thanks a lot