Check it out: http://code.msdn.microsoft.com/SPDisposeCheck
I just fired it up and it looks like it will be really helpful. It confirmed a chunk of bad code I was just looking at along with a handful of others.
The XML mode seems to bomb out (as others have posted), but piping to a file seems to work fine.
I’ve been working on supporting and enhancing a client’s custom SharePoint solution for a while now. The solution involves custom application pages and custom web services hosted in SharePoint, both which use the SharePoint object model heavily. As the number of users (1000+) and number of sites (45000+) increased we started seeing some Out of Memory Exceptions cropping up. Simply stated, these errors are not good. They generally require restarting your app pool or performing an iisreset to fix and get your app back up and running.
I thought it might be helpful to others to document how we went about identifying suspect areas of the application and how we fixed them. First it helps to understand a little more about what is really going on. We’re not actually running out of memory on the server. According to the technet article Dealing with Memory Pressure Issues in WSS and MOSS, what is really happening is that unmanaged resources are not being disposed of properly when using the SharePoint object model. Eventually the worker process, not the server, is not able to allocate more memory and the exception occurs.
We have a good infrastructure with beefy servers and a load-balanced farm of front ends. So really we shouldn’t have issues due to hardware. The volume alone shouldn’t cause the problem, either. From the infrastructure angle, we have do have plans to move to 64-bit servers soon which will further reduce possibility of memory pressure. We also set a memory threshold on the app pools to restart which may have helped in the short term. But in reality, the problem is probably due to an application issue that has just become more noticeable under volume.
So for starters you need to be sure code is to following Microsoft’s Best Practices for using the SharePoint Object Model:
I also recommend Roger Lamb’s SharePoint Development Blog as a good resource to help reinforce and supplement the Best Practices articles.
When you have a large code base like the project I’m working on, it’s time consuming and not necessarily easy to review every line of code to make sure it was written with proper disposal in mind. There is supposed to be a tool coming from MS that will help with this which will be great. (UPDATE: Apparently the SharePoint Dispose Checker Tool is ready now. I haven't tried it yet but you can find it here. I haven't tried it yet.) But if you’re actually having an issue with Out of Memory Exceptions, you need to help pinpoint the problem quickly.
Looking at the SharePoint logs in ..\12\Logs, you can will see entries that read “An SPRequest object was not disposed before the end of this thread. To avoid wasting system resources, dispose of this object or its parent (such as an SPSite or SPWeb) as soon as you are done using it…”
To find more info on what code is responsible, you can find or create the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings and then create a new DWORD named SPRequestStackTrace with the value 1 under this key. If this is not set, the error message above will contain this info. Once it is set, you’ll be able to see the stack trace in your custom offending code. Then you can go identify the cause of the problem and fix it, by adding “using” clauses, for example.
One scenario that wasn’t apparent in the Best Practice documentation (at least to me) is that you need to use SPxxx objects (SPList, SPFile) retrieved from an SPSite/SPWeb before disposing the SPSite/SPWeb. Otherwise the SPxxx object may recreate the SPSite/SPWeb or similar SPRequest object that doesn’t get disposed. So in general, writing methods that return SPxxx objects is not the best way to go, because you probably disposed of the site and web in the method. However it is often nice to break up logic in to smaller private methods for readability and reusability. In this case, you just have to make sure the SPWeb and SPSite are passed in to those methods instead of using and disposing them in the methods.
public DoBigTask(SomeInfoObject info)
{
//figure out guids based on info...
using(SPSite s = new SPSite(guid1))
{
using(SPWeb w = new SPWeb(guid2))
{
SPFile f = GetFileBasedOnInfo(w, info);
DoCommonWork1(f);
DoCommonWork2(f);
}
}
}
private SPFile GetFileForInfo(SPWeb w, SomeInfoObject info)
{
// return SPFile from web based on info
}
private void DoCommonWork1(SPFile f)
{
// do work
}
private void DoCommonWork2(SPFile f)
{
// do work
}
I'd avoid passing SPxxx objects outside of class interfaces if possible so that you retain control and make sure the objects are handled correctly. I would have preferred that Microsoft designed a little more for discoverability of this last issue. My preference would be that if I checked SPFile.Exists I would get an error that said "Parent site has been disposed" as opposed to "helping" me by recreating the parent site/request which causes the memory leak.