Monday, July 2, 2012

w3wp.exe uses too much memory and resources

What is the W3WP.exe process?

The W3WP.exe is the IIS worker process, that handles requests, maintain sessions, viewstate, and the cache.  Its been around Since IIS 6 on
Windows Server 2003, and is still found as part of IIS 7.5 with Server 2008 R2.  On a properly configured, and programmed website the W3WP.exe can usually stay under 100 Megs.   If you are running a 64bit OS it could be a little larger.  The actual size of the W3WP.exe will be determined by how much traffic your website gets, and how many pages it serves.  The 100 Meg figure is just an estimate from my own experiences.  Application Pools with multiple websites can easily go over this figure, so don't use it some magic number.  But if you are running a website that has relatively low traffic ( under 20K impressions daily ), and your W3WP.exe is taking up 100+ MB of Memory, then you might want to make some changes.
Why do I care if W3WP.exe is large?

Lets say that you have a website running on a
shared hosting account.  As your site grows, it will start to experience bottle necks from the limited resources it has access to on the shared box.  Remember the average shared server is running on average 300 websites.  You site is constantly fighting other sites for CPU time and resources.  Eventually you out grow the shared environment, and are forced to upgrade to either a VPS or a fully dedicated server.  But what you don't know is your site could last much longer on the shared box or that small VPS, if you were to clean up your code. 

Most popular causes of W3WP.exe using too much memory

Page Caching Dynamic Websites

Some Programmers will use Page Caching on their
ASP.NET pages to improve request speeds. Even though this does work.  It will quickly eat up all your memory.  For Page Caching to work you would need to cache each page and every combination based on its querystring variables.  For Members sites this could result in millions of different pages.  A more effective way of using caching is to Cache objects that do not change, and are used throughout the website.  Things like your menu bar.  Or maybe the details for an event.  This will reduce the number of calls to the database server, and speed up your site.  Some may argue that the function of a Database server is to cache popular queries, and that there is no difference between retrieving the data from the database server and caching the objects in your web server's memory.  This is absolutely false for many reasons.  First anytime your website has to retrieve data from the database, it has to open a connection to another process (the MySQL process), even if MySQL is running on the same box as the web server there is a very small performance penalty to establish this connection.  But if you are on a Shared Hosting Account, its very likely that the hosting company has setup a dedicated MySQL server in the datacenter somewhere.  So now your web server has to reach across the datacenter to a separate server.  At this point the latency of their network becomes an issue.  This is something I have personally experienced with multiple shared hosting providers.  This is the reason I highly recommend doing everything you can to reduce the calls to the database.  Object Caching can make a huge difference on page load times, especially when you are able to cache objects that use expensive queries.  If you want to learn more about how to custom manage objects in the ASP.NET cache, I wrote a few helper functions that are easily integrated into your websites.
ViewState Enabled on Labels

The ViewState is how
ASP.NET keeps track of changes that have been made to Web Controls.  ViewState is needed anytime you are going to do a postback, like for a submit form.  But a common mistake is programmers don't disable viewstate on Label controls that are often used as place holders for long concatenated HTML strings.  If you suspect your may be guilty of this all it takes is a look at the HTML source code from your web browser to confirm it.  If your HTML source looks like this


with a really big view state then you need to disable the viewstate on your label controls.  The Viewstate is stored in the W3WP.exe process.  Its easy to see how this process can consumer so much memory when you have a view state this large and on an exponential number of web pages. The solution is to change your ASP:Label Controls from this
<asp:Label ID="mainmenu" runat="server" />
to this
<asp:Label ID="mainmenu" EnableViewState="false" runat="server" />
Lets face it there is no reason you need to preserve the ViewState of a Label Control.  So go through all your pages and add the EnableViewState="false" attribute to all your Label Controls.
Long Session Time Outs
Anytime a visitor ( organic or spider ) visits your website, ASP.NET is going to maintain a session with them.  Sessions are how the server keeps track of your users and their activity on your website.  Without Sessions things like postback would not be possible.  When ASP.NET uses sessions in the traditional way, they store a Session ID in a cookie on the client's browser.  Then every time this client communicates with the server this cookie value ( Session ID ) is passed along with the request.  The Server can then identify the visitor by their Session ID and handle the requests appropriately.  Now the server has to keep track of the visitors activity.  So each time a submit form is submitted, or a web control is used, the information related to this action is stored with the viewstate in the W3WP.exe, and is tied to the Session ID.  This memory is not released until the Session Expires.  The default on ASP.NET is for Session to Expire about 20 minutes.  This means after 20 minutes of no activity from this visitor the Session would be discarded, and the memory associated with this session would be freed.  Now if you have some lengthy submit forms which could take longer than 20 minutes to fill out, then you might need to have a longer than normal session timeout.  On blog.whitesites.com I have sessions set to 45 minutes ( sometimes I take a while to write an article ) But if your submit forms are the quick kind that can be filled out within a few minutes, then 20 minutes is more than enough.  If your website doesn't have any submit forms, then it might make sense to take your session timeouts down to 5 minutes or less.  The shorter your Session Time Outs, the less memory that will be needed to track your visitors as they navigate through your website.  If you want proof.  Set your Session Timeouts to be 6 hours.  Then watch over the next 6 hours as your W3WP.exe grows to a massive size.  I can only imagine what sites like Facebook must deal with considering their visitors ( or should I call them addicts ), do daily surfing marathons.

For a website like Blog.whitesites.com, in which the only public web control is the comment box at the bottom of the page, I could probably get by with a 15 minute session timeout.  But my backend that is run from the same Application needs much longer Session timeouts.  If I wanted to get very efficient with my memory, I would create a separate application for my backend ( control panel ) with the longer timeout, allowing me to shorten the timeout on my public application. 

So in summary.  Lots of submit forms, plus lots of unique visitors, plus a long session time out will equal a very big W3WP.exe.  You might not be able to change your submit forms, or your visitors, but you can shorten your session timeouts.
Memory Leaks

Certain objects should be cleared from memory with the Dispose() Method.  These include things like BitMap Objects.  Even though the
ASP.NET Garbage Collection does a good job of taking out the trash, I have found that on heavily loaded systems if you don't release Bitmaps with the Dispose Method it tends to lock the image file you were working with.  This object will sit in your W3WP.exe taking up space.  Even though memory leaks can be a problem, they are usually very minor.  ViewState is by far the biggest Memory hog.
Unclosed Database Connections

If you use helper functions to manage your Database connections, be sure that you close the connections, when finished.  Else this will waste memory on both the W3WP.exe side and the Database Server side.
Conclusion

Even though advanced programmers might feel some of this is obvious.  I found it disturbing that I was unable to find more articles online involving something so important.  Who knows, maybe if every programmer uses my advice, this could negatively affect the bottom line of
hosting companies, who's customers won't be needing to get that dedicated server just yet.  If this helped you let me know.



SharePoint or Windows Server acts slow!! use this trick

Total Pageviews