SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 30
  1. #1
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Profiling a Classic ASP and Access website for memory leaks

    Hi,

    I am fairly new to ASP and VBasic. However, I have somehow managed to create a website for a shop that has gone live after appearing to be fine and robust during testing.

    Sadly, it seems that since launching the site (which has between 100-1000 visitors a day) it has suffered memory problems with the w3wp.exe process chewing up from ~132MB to ALL (512MB) of the available memory and the processor is apparently maxing out at points and causing the server to fall over. That said, the main problem is the fact that pages are very slow to download and I am trying to find out why...

    Since I am new to VB I suspect that I have not been closing up all my objects and releasing memory properly (which I presume is done by explicity setting the variables to Nothing after closing them). I am doing this now. I figured that high mem usage might cause more cpu cycles as the garbage collector goes into overload trying to free up memory.

    How can I measure and profile my classic ASP (VB) code to find where it is taking time and how much memory each line/page uses?

    Next Question: Session Variables....My code features a lot of Session variable usage. I am not sure that the Global.asa->Session_OnEnd() function is being executed because I often log in to find that the active sessions is between 1000-4000 (usually about 4-10 times the number of visitors as reported by google analytics). I am getting the number of active sessions from a counter variable that is incremented in Global.asa->Session_OnStart() and decremented in Global.asa->Session_OnEnd(). My session duration is supposed to be about a day. Heres my global.asa file:

    <script language="vbscript" runat="server">

    Sub Application_OnStart
    Application("visitors")=0
    Application("logged_in_visitors")=0
    End Sub

    Sub Session_OnStart
    ' Basket lives as long as session
    Session.Timeout=1440
    Session("started")=now()
    Application.Lock
    Application("visitors")=Application("visitors")+1
    Application.UnLock
    End Sub

    Sub Session_OnEnd
    Application.Lock
    Application("visitors")=Application("visitors")-1
    Application.UnLock
    End Sub

    sub Application_OnEnd
    end sub

    </script>

    Is it likely that extensive use of session variables are responsible for my memory troubles due to this large timeout? If so, how can I reduce this without reducing the timeout (customers want their login to survive until the next day).

    Last question: Access..grrrrr

    I am using Microsoft Access as the database behind my website. In this db all the user, order and product information is stored in tables with stored queries to access that data. My experience with Access has been rubbish. I am used to working with PHP-MySQL, PostgreSQL and SQL Server. It seems to have a significant lack of functionality for a modern site and now I am beginning to wonder... With every ASP page on the site making several queries to the database and more than 100 visitors daily, is it possible that Access is the bottleneck causing my web pages to be slow?

    I am looking at migrating the DB to SQL Server using the Access 2007 migration tool. It seems to work on the DB side. Any ideas what issues may arise from the move to SQL Server? (Obviously connection string, but is there anything else such as SQL language issues?)

    Thanks in advance.

    Tom

  2. #2
    SitePoint Guru
    Join Date
    Jun 2007
    Posts
    691
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    !00 - 1000 visitors per day is not a problem quantity.

    Sessions do take up a lot of memory - check your session timeout setting - 20 minutes is normal

    Access can handle the load you are getting. SQL server is of course much better to use as it is designed for servers. There are no problems with SQL server except learning it and the cost.

  3. #3
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks webber,

    Yeah my session timeout is set to 1440 mins but I have removed the need for that by storing the cart data in cookies if available and reduced the session timeout to 60mins. Hopefully that should fix any major memory issues.

    I am really not a fan of Access and I have experience with SQL Server. Plus if the DB is <4GB is there any issue with using SQL Server Express?

    Cheers,
    Tom

  4. #4
    SitePoint Addict
    Join Date
    Apr 2009
    Posts
    359
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Migrate to another db. Access itself is capable of handling your users but the access drivers are not well suited for busy websites and connections crash easily when overloaded, and apparently leave behind memory leaks.

    I worked with asp forum code and when the user count reached 5+ regularly on line servers started having mysterious problems.

    Review the connection string you're using, the access OLEDB connection is more robust than an ODBC connection.
    Doug G
    =====
    "If you ain't the lead dog, the view is always the same - Anon

  5. #5
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Cheers Doug,

    Sounds like timely advice. Im just working on the migration to SQL Server at the moment!

    Thanks,
    Tom

  6. #6
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    I have reduced my Session timeouts and checked / fixed any memory leaks in my asp code. But I am still getting really high CPU usage from w3wp.exe.

    How can I debug this?

    How do I get a dump of its state?

    Any help or suggestions much appreciated.

    Tom

  7. #7
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am getting CPU spikes:


  8. #8
    SitePoint Wizard bronze trophy
    Join Date
    Oct 2001
    Location
    Vancouver BC Canada
    Posts
    2,037
    Mentioned
    5 Post(s)
    Tagged
    0 Thread(s)
    Are you destroying DB connections and objects once they're done with?

    Access and ASP are far from perfect when compared to todays PHP or ASP.NET but I'm still supporting some fairly complex ASP/Access legacy sites I built 10 years ago with member levels into the hundreds and I haven't run into problems with memory leaks or Access limitations, mind you I've had to do some interesting things to obtain the results I need

    These are my top three rules
    Always use DSN-less connections for access database connections. DSN for Access will drop the connection if it gets busy or just for any old reason. It sure is easy in development but DSN just never seems to work in reality.

    I kill my connection at the end of the page and my recordset object (and any object) as soon as I'm done with it.... I usually run my query, use GetRows() to stuff the results into a multi-dimensional array and kill the recordset object to free the memory. If you don't set connections, recordsets, and other objects to nothing, you're just inviting memory leaks.

    Don't set your session timeout too high... 15 or 20 minutes is enough, otherwise w3wp.exe will just get bigger and bigger because it is a worker process that manages sessions, caching, objects in memory and anything that consumes memory in IIS.

    I'm not sure about the spikes... Have you looked at what processes are consuming the most cpu cycles?

    Edit: I just re-read the cpu cycle note and it's w3wp.exe which means that you haven't solved your memory leak issue yet. Check your database connections and any objects in use to make sure they are properly disposed of. Also reduce your session timeout even if temporarily for testing. Good luck!
    Andrew Wasson | www.lunadesign.org
    Principal / Internet Development

  9. #9
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Cheers awason!

    You're bang on the money. You truly deserve the title of Wizard!

    I have just finished a really intensive inspection of about 70-odd files closing and nulling >300 recordsets, connections and other objects. That seems to have made a big difference to w3wp's size (it doesn't really change anymore - no more leaks!... for now). Happy days.

    I have also now managed to find the cause of my spikes. You'll love this or pity me for being such a pillock but I had a SQL query in a page that is visited very frequently, multiple times by every user (it shows them the product details). The offending query performed an INNER JOIN on itself (dundunduhhhh) which didn't matter on the dev env because the test DB isnt as big. But once live that query performed a sort and search on 175,000x175,000 rows. Not good! Once I commented out that code I removed all spikes. (Either that or all our customers have given up).

    EDIT: It gets worse. The stored query in Access that bad query was using was in fact a self-join again.. eesh. I need a code reviewer...

    I am still keen to get away from Access and old Classic ASP. My first mission is to migrate to SQL Server. Access may work but it is still too unstable to be left for someone else (non-techy) to handle and I cant spend my life maintaining this website.

    Anyway. Sorry for the rant. Thanks very much!

    Tom

  10. #10
    SitePoint Wizard siteguru's Avatar
    Join Date
    Oct 2002
    Location
    Scotland
    Posts
    3,631
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    If I'd seen this earlier I would have made the same recommendations.

    With ASP, and especially with Access, the mantra to follow is "Open Late, Close Early, and Kill Everything". Follow this approach and issues with concurrent connections and memory usage fall away.
    Ian Anderson
    www.siteguru.co.uk

  11. #11
    SitePoint Wizard bronze trophy
    Join Date
    Oct 2001
    Location
    Vancouver BC Canada
    Posts
    2,037
    Mentioned
    5 Post(s)
    Tagged
    0 Thread(s)
    Thanks Tom,
    Glad that worked out for you.

    Good plan going with SQL Server. It will make life easier in the long run. I've been amazed at how resilient ASP/Access is but in this day and age there are so many vastly superior technologies and you can do things with a couple of lines of ASP.NET that take reams of ASP code.

    Good luck!

    Andrew
    Andrew Wasson | www.lunadesign.org
    Principal / Internet Development

  12. #12
    SitePoint Addict
    Join Date
    Apr 2009
    Posts
    359
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Doug G
    =====
    "If you ain't the lead dog, the view is always the same - Anon

  13. #13
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    I am still having problems it seems.

    My Global.asa file looks like this:

    <script language="vbscript" runat="server">

    Sub Application_OnStart
    Application("session_timeout")=20
    Application("visitors")=0
    Application("logged_in_visitors")=0
    End Sub

    Sub Session_OnStart
    Session.Timeout=Application("session_timeout")
    Session("started")=now()
    Application.Lock
    Application("visitors")=Application("visitors")+1
    Application.UnLock
    End Sub

    Sub Session_OnEnd
    Application.Lock
    Application("visitors")=Application("visitors")-1
    Application.UnLock
    Session.Abandon
    End Sub

    sub Application_OnEnd
    end sub

    </script>

    The setting in IIS 7 for ASP->Session Properties->Time-out = 00:20:00.

    I have a page that displays the number of "Active Sessions" by printing the Application("visitors") variable. This variable appears to grow to between 2000-4000 every day. However, the number of daily visitors being reported by Google Analytics is between 20-100. Therefore, I am suspicious that this may be the cause of our problem, since the Session_OnEnd() function is responsible for decrementing the "visitors" counter, if it isn't being called does that indicate that Sessions are not being timed out and closed properly?

    I do use Session.Abandon in 2 other places on the website. One is when someone logs out, the other is at the end of a web_update.asp script that is called regularly (10-20 times per update, where an update runs every 15mins). This script updates the website database with stock info and downloads the latest orders.

    If the Session.On_End() function is not being called, does that imply these sessions are not being released properly? Does Session.Abandon call Session.On_End()?

    Can anyone suggest how I can debug this problem once and for all? I cant tell how many sessions are truly active at any one time.

    In addition, to this I have looked at my Event log and seen that there has been a reoccurring ASP application error every 12-24 hours.. How can I read and interpret these ASP errors using the Event Log info (lots of codes - where do I look them up?).

    I have Plesk installed and will be looking at the Logs at those times for further clues.

    Any and all help is very much appreciated. Sorry if Im starting to sound like a broken record

    Tom

  14. #14
    SitePoint Wizard siteguru's Avatar
    Join Date
    Oct 2002
    Location
    Scotland
    Posts
    3,631
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Remember that Session-OnEnd fires after 20 minutes (default) of inactivity of a session, and not immediately when a browser is closed. That said, this doesn't appear to be your issue.

    Session.Abandon does kill all items related to a session, but when would you know to use this command, if you're unsure if Session_OnEnd is firing? It wouldn't hurt to put it there though.

    One test you can try ... in Session_OnEnd update an Application variable with some test text. Then check whether that variable contains the expected text after you have expired a session.

    Code:
    Sub Application_OnStart
    Application("TEST")=""
    End Sub
    
    Sub Session_OnEnd
    Application("TEST")="I Fired"
    End Sub
    Then open a new session and check the variable.
    Ian Anderson
    www.siteguru.co.uk

  15. #15
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks siteguru,

    I will try that and get back to you with the results.

    But in the meantime I have found that I am receiving these errors regularly:

    Failed to retrieve the Anonymous User Token for ASP Application /LM/W3SVC/424/ROOT. Global.ASA OnEnd routines will not be executed.

    What would cause this error?

    Thanks,
    Tom

  16. #16
    SitePoint Addict
    Join Date
    Apr 2009
    Posts
    359
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    I don't think you want session.abandon in the session_onend() function in global asa. If I recall correctly, the onend event fires after the session is abandoned, either by timeout or explicit;y calling session.abandon.
    Doug G
    =====
    "If you ain't the lead dog, the view is always the same - Anon

  17. #17
    SitePoint Wizard siteguru's Avatar
    Join Date
    Oct 2002
    Location
    Scotland
    Posts
    3,631
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Is this a load-balanced web server? (i.e. more than one physical server providing the web service).
    Ian Anderson
    www.siteguru.co.uk

  18. #18
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes I think so. It is a "Windows HyperV Cloud" provided by EUKHost..

    I have now changed my Global.asa file to:

    <script language="vbscript" runat="server">

    Sub Application_OnStart
    Application("session_timeout")=20
    Application("visitors")=0
    Application("logged_in_visitors")=0
    End Sub

    Sub Session_OnStart
    Session.Timeout=Application("session_timeout")
    Session("started")=now()
    Application.Lock
    Application("visitors")=Application("visitors")+1
    Application.UnLock
    End Sub

    Sub Session_OnEnd
    Application.Lock
    Application("visitors")=Application("visitors")-1
    Application.UnLock
    End Sub

    sub Application_OnEnd
    end sub

    </script>

    I am also trying to get DebugDiag to get a dump when the server appears to crash with no luck so far though. And the server has definitely stopped responding at least once today.

    Thanks for your help. Very much appreciated. I really am feeling kind of lost here..

  19. #19
    SitePoint Wizard siteguru's Avatar
    Join Date
    Oct 2002
    Location
    Scotland
    Posts
    3,631
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    I've heard of issues before regarding ASP sessions and load balanced servers. Unless the load balancer is configured to make sure user sessions are ALWAYS pointed to the same server then sessions issues can arise.
    Ian Anderson
    www.siteguru.co.uk

  20. #20
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Is this something I can control as the customer?

    I am using a hosting company so I presume they are the ones who need to do the configuring.. Is that correct?

  21. #21
    SitePoint Wizard siteguru's Avatar
    Join Date
    Oct 2002
    Location
    Scotland
    Posts
    3,631
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Yes. Anything to do with server config needs your hosting company's support.
    Ian Anderson
    www.siteguru.co.uk

  22. #22
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Can anyone suggest how I can profile and analyze the ASP and the state of sessions on the server?

    I need to know which sessions are open at any one time. I need to know what code on which page is taking time / using memory / causing errors / causing crashes. The usual story for debugging really.

    The problem is that I have never really debugged a Classic ASP application before and I am not familiar with Windows debugging tools. Is this approach sensible?

    If my server is falling over because of the W3WP.exe application then I need to get DebugDiag or some other debugger like WinDbg to generate a dump of the memory for that process and then analyze it. The analysis will show which symbols (ASP functions/variables) were running and how much memory was being used at the time it crashed.

    The issue is I dont really know how to use these tools. I put rules on DebugDiag and waited but it wont create a dump for IIS or W3WP even though the server has fallen over.

    Can anyone suggest or recommend any good tools for analyzing ASP code and informing you which code is likely to cause problems? I have tried several and not had much luck.

    Cheers,
    Tom

  23. #23
    SitePoint Member
    Join Date
    Aug 2010
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay apparently.. according to my hosts the problem is definitely with the ASP app using too much resources. However, it is the CPU that is being overloaded not memory now.

    The sent me a screenshot showing 97% memory usage by w3wp.exe.

    How should I go about resolving this? I have been through my code and as far as I can tell I am closing all connections and setting objects to 0. Perhaps I have too many connections and queries per each page?

    Is it time to get SQL Server going since that might handle the number of queries and connections better..?

    Sorry for the thinking out loud but I really need to bounce this off of someone as I am struggling here and it sucks.

    Thanks,
    Tom

  24. #24
    SitePoint Guru
    Join Date
    Jun 2007
    Posts
    691
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    you can google for application stress testing tools .

    try Microsoft Web Application Stress (WAS) Tool Kit"

  25. #25
    SitePoint Wizard bronze trophy
    Join Date
    Oct 2001
    Location
    Vancouver BC Canada
    Posts
    2,037
    Mentioned
    5 Post(s)
    Tagged
    0 Thread(s)
    Ok so if it's CPU and not memory, I wouldn't spend my time looking at sessions. I would look for continuous loops in the code.

    Mind you, it would be good to get an idea of how many sessions are being created and at what rate they are being created because as you noted sometime earlier there was a discrepancy in the number of sessions being created and the number of sessions (visits) that were being reported in your web analytics program.

    If something was causing multiple sessions to be created, even if they were empty, it could make the processor % spin up. Otherwise, I would be looking for anything in the way of a loop that might be continuing without an end.
    Andrew Wasson | www.lunadesign.org
    Principal / Internet Development


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •