Troubleshooting SPSite/SPWeb leaks in WSS v3 and MOSS 2007

In an earlier article I have discussed that all SPSite and SPWeb (and potentially also PublishingWeb) objects need to be properly disposed to avoid memory pressure situations. Roger Lamb has a nice summary of coding patterns which will actually cause such leaking objects and also provides information about how such code would have to be adjusted to avoid such leaks.

In this article I will provide some details about how a sharepoint administrator is able to isolate if the site contains custom code which does not properly dispose these objects and also how to isolate the components that are leaking these objects.

Overview 

As discussed in my earlier article each SPWeb and SPSite object holds a reference to an SPRequest object which holds a reference to a SharePoint COM object that is responsible to communicate with the backend SQL server. The dispose of the SPWeb and SPSite object is necessary to ensure that the SPRequest object will release the COM object and also all the memory allocated by this COM object is released.

In SharePoint v2 the only way to identify such leaking objects was to analyze a memory dump – which usually required that a support case with Microsoft has to be opened to identify the code that is not correctly disposing the SPWeb or SPSite objects.

SharePoint v3 on the other hand contains code which monitors correct disposal of SPRequest objects (and therefore correct disposal of SPWeb and SPSite objects). This code has two different features:

  1. It monitors how many SPRequest objects are open in parallel on all threads.
  2. It checks if SPRequest objects still exist at the end of the thread that created it

I will now discuss how these build in features can be used to identify how expensive (in regards of SPRequest allocations) your site design is and also if the code contains any controls which don not properly dispose SPWeb and SPSite objects.

How many SPRequest objects are allocated by a single request to my site?

Usually you would think that if you don’t add any custom code to your page that only one SPSite and one SPWeb object should be required (the site collection and the site the page lives in) but this is not correct. The reason is that all the master pages contain three navigation controls: The Top navigation, the Breadcrumb control and the Left Navigation control.

Per default these navigation controls are bound to one of the Site Map Providers shipped with SharePoint. To show the elements in the navigation control the control queries the site map provider which will now enumerate the sites in the sharepoint database to retrieve the title and the URL to be displayed on the navigation control. Each of the enumerated sites will be instantiated during the enumeration to retrieve these properties. That means if you have a navigation control configured to enumerate 3 levels of sites and on each level you have 20 sites that you will end up with more than 400 SPRequest objects. So you need to be very careful with how to configure your navigation controls and also how many sites to create on each level!

A valid question now could be: why does the site map provider not dispose each of the objects directly after it retrieved the URL and the Title? That should reduce the number of parallel existing SPRequest objects heavily. Indeed that would be correct. But remember: you have usually multiple navigation controls on a single page! Disposing these objects directly after the properties have been read would mean that for each navigation control on the page the same objects have to be retrieved from the database again and again – which would impact the performance of the site. To avoid this the items retrieved by the navigation controls are cached to ensure that other navigation controls needing the same items can leverage them without causing additional requests to the backend database. The caveat is that the overall memory consumption of the site will go up through this implementation.

As indicated in the overview section SharePoint v3 monitors how many SPRequest objects exist in parallel on the same thread. As soon as SharePoint identifies that with a new allocation the number of SPRequest objects exceeds a configurable threshold SharePoint will create the following entry into the ULS log:

12/12/2007 12:29:54.05 w3wp.exe (0x1380)                       0x126C  Windows SharePoint Services   General                                0                Medium               Potentially excessive number of SPRequest objects (14) currently unreleased on thread 5.  Ensure that this object or its parent (such as an SPWeb or SPSite) is being properly disposed.  Allocation Id for this object: {2DF92EAD-4959-4A21-8BA0-FBD91E8FDD48} Stack trace of current allocation: at Microsoft.SharePoint.SPRequestManager.Add(SPRequest request, Boolean shareable)

The default threshold to get the above warning is 8 – which is actually far to small for real live scenarios as we have seen that with navigation controls on your master pages you will for sure exceed this number. As you can see in the sample above the warning outlines that 14 SPRequest objects live in parallel on the same thread. As we have seen before with navigation controls a larger number of SPRequest objects is absolutly normal and as expected. So you can expect the ULS log to be filled up with many similar warnings.

You should inspect the ULS logs of your site and verify what are the highest numbers in these warnings to get an idea about how expensive your current site design currently is in regards to memory consumption through allocated SPRequest objects. If the number is higher than 150 you might need to consider to change the design of your site or the number of levels to show in your navigation controls to reduce the memory footprint.

Afterwards you can fine tune the threshold to avoid unnecessary warnings. This can be done by adjusting the threshold through the following a registry key (e.g. to 50):

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings

        LocalSPRequestWarnCount = 50

 

The actual number to configure here depends on your site structure. After setting this registry key you need to restart the sharepoint services and the application pools (or restart the server) to ensure that the settings get effective.

Also be aware that you will only see the above warning if you have configured diagnostic logging for the General category to at least Medium level – which is actually the default. So if you haven’t changed the configuration of diagnostic logging you will see these warnings.

Do I have code on my site which does not correctly dispose SPSite/SPWeb objects?

One method (not completely reliable but a good indicator) is to monitor the ULS log message mentioned in the last section. If the number for some threads gets higher and higher during the livetime of a thread, without going down to the configured threshold again the chance is high that there is some code which does not properly dispose SPWeb and SPSite objects.

Be aware that you cannot just look at the callstack listed in these messages to identify the bad code as this warning will be written during allocation of the objects! This message does NOT indicate that the object is not properly disposed! So you can only use it as an indicator that some code might be wrong but not to identify the module causing the problem!

To identify the bad code we need to use a different approach.

As mentioned in the Overview section SharePoint not only monitors the number of SPRequest objects allocated by each thread but also checks if SPRequest objects still exist at the end of each thread and create the following message into the ULS log.

05/01/2007 12:58:47.31                w3wp.exe (0x105C)                                      0x09A8 Windows SharePoint Services                   General                               8l1n       High       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.  This object will now be disposed.  Allocation Id: {5BFFCA4B-3B91-45BF-98CD-0BB508BE30EE} To determine where this object was allocated, create a registry key at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings. Then create a new DWORD named SPRequestStackTrace with the value 1 under this key.

Be aware that the livetime of a thread can be much longer as a single request. As SharePoint only checks if undisposed SPRequest objects exist when the thread ends and not at the end of each request the number of entries of this type can be much smaller than you might expect. So you might have to search in multiple ULS logs and not just the latest for this warning (you can actually search for the string 8l1n as this is the unique identifier for this message).

In addition: if the object has been disposed by the garbage collector then you will see a slightly different message stating that the garbage collector reclaimed the object:

05/01/2007 14:48:43.32                w3wp.exe (0x105C)                                      0x09A8 Windows SharePoint Services                   General                               8l1n       High       An SPRequest object was reclaimed by the garbage collector instead of being explicitly freed.  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.  Allocation Id: {098092FF-E4D9-4BA3-B2B8-5C6CE9B96554}  To determine where this object was allocated, create a registry key at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings.  Then create a new DWORD named SPRequestStackTrace with the value 1 under this key. 

To identify which code is responsible for the problem after you identified the problem you have two options:

  1. You can search the earlier ULS logs for the allocation ID in the warning (if the allocation was done beyond the threshold you will find it)
  2. You can follow the hints in the warning and set the following registry key as this will ensure that the stack trace of the allocation of the SPRequest object is preserved in memory and added to the 8l1n ULS log entry:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings

        SPRequestStackTrace = 1

The second option is more reliable as it will ensure that you get a callstack for each of the 8l1n messages. Be aware that after setting this registry key you need to restart the sharepoint services and the application pools (or restart the server) to ensure that the settings get effective.

[Update: 2010-10-18: SharePoint 2010: For SP 2010 the method is different. See here for details]

By analyzing the emitted callstack you should then be able to identify the component causing the problem.

67 Comments


  1. Extremely useful as usual !! Thanks !!

    Reply

  2. Just wanted to make the community aware of a new blog just written by Stefan Gobner (EE Engineer at Microsoft

    Reply

  3. I do not have that particular key in my entire registry. HKEY_LOCAL_MACHINESOFTWAREMicrosoftShared ToolsWeb Server Extensions is there, but HeapSettings is not. Can I safely create that structure?

    Reply

  4. Some of those best practices require you to know that an INTERNAL method call is made which creates a web that you are in charge of disposing of, e.g., SPList.BreakRoleInheritance(). How can you possibly know to call list.ParentWeb.Dispose(); after you call BreakRoleInheritance? Why doesn’t SPList just implement IDisposable? If it has objects that need to be disposed? Isn’t that the proper pattern for IDisposable?

    Reply

  5. Hi Alex,

    yes you need to cretae this key and the DWORD value below it.

    They do not exist after installing the product.

    Cheers,

    Stefan

    Reply

  6. Hi Tim,

    there is always room for improvement.

    Cheers,

    Stefan

    Reply

  7. Properly Disposing of SharePoint API Objects

    Reply

  8. Stefan Gossner has published a great article on the subject: In an earlier article I have discussed that

    Reply

  9. Hi Stefan

    Excellent article. I was going crazy over the intensive logging for no reason! I have a question though regarding the sitemapprovider. I use the standard CurrentNavSiteMapProvider from the publishing infrastructure. How can I limit this to say 2 levels? I can set the StaticDisplayLevels in my Menu control, but as I read your article, this will not reduce the creation of SPWeb objects? I have to make the CurrentNavSiteMapProvider reduce this creation by telling it to go only two levels deep. Or am I missing something?

    Regards

    Reply

  10. Hi Kristian,

    I was talking about the StaticDisplayLevels and DynamicDisplayLevels settings of the navigation controls.

    Cheers,

    Stefan

    Reply

  11. But does this mean that by using StaticDisplayLevels and DynamicDisplayLevels I also limits the creation of SPWebs?

    Reply

  12. Hi Kristian,

    the answer is yes. The site map provider does not create any objects on its own. Only if being asked for nodes from the navigation control it will create these objects. And the navigation control decides to which level this will be retrieved and that means the navigation control decides how many objects are created.

    Cheers,

    Stefan

    Reply

  13. Cool. Thanks for the good (and fast!) answers. As I said, it (the answers and the blog) has really clarified things!

    Reply

  14. Stefan has a good article on troubleshooting leaks in your WSS and MOSS applications. One of the very

    Reply

  15. Very great article.

    But how can i create a complete sitemap if I have a publishing site?

    Reply

  16. Hi Markus,

    you can (e.g.) create a console application which enumerates the whole site structure and creates the XML file which can then be used by the standard ASPNET XML sitemap provider.

    Cheers,

    Stefan

    Reply

  17. And what about security trimming about the single sitemapnodes when creating a sitemap in an XML file and use it as sitemap provider? I think this cannot be done easily… 🙁

    Reply

  18. Hi Michael,

    you are correct. This approach is good for anonymous sites or site where no security trimming is required.

    For sites where security trimming is required you either have to ensure that the tree structure is not very complex or you should look for a 64-bit machine where more memory can be made available per worker process.

    Cheers,

    Stefan

    Reply

  19. Another holding post that I need to get back to. Excellent read! Stefan Goßner : Troubleshooting SPSite/SPWeb

    Reply

  20. So  what is the GUID in the Allocation ID? Is that a feature GUID?

    Reply

  21. Hi JDP,

    no this is not the feature ID. It is a GUID generated at the momement when the object is allocated in memory. So you cannot use it to track it down to anything on the file system.

    Cheers,

    Stefan

    Reply

  22. Thank you, Stefan. A client’s server has these errors on rare occasion, and it’s quite difficult to pinpoint their origin. It would be quite helpful if some technical information could be included in the error to facilitate analysis.

    Reply

  23. Hi JDP,

    which error do you mean? The SPRequest leak?

    Actually using the steps above you have the complete callstack of the allocation! That is all technical information you need to pinpoint the piece of code that causes the problem.

    Cheers,

    Stefan

    Reply

  24. To clarify — it’s surprising that event tells you how to get the stack, rather than providing it explicitly.

    Adding the reg key does work great, and helps, but IMHO the logging behavior provided by the reg key should be the "out of the box" setting.

    And since I haven’t said it yet — thanks for writing this! You’re one of the most knowledgeable resources around.

    Reply

  25. Stefan,

    Thanks for this great insight. The problem has been nagging me since ages…

    I do have a problem. I’ve developed a webpart that pulls information from the parent web. When the webpart is initialised, I use SPContext.Current to get the web, and from that I get the parent SPWeb. During CreateChildControls, I build a UI with the information. During post back handling, the web references are used too. Probably just after rendering I could dispose the sharepoint objects.

    I understand that I cannot Dispose() the current web as it is owned by the webpart manager or page, and I need to Dispose() the parent web because I referenced it.

    Now here is my problem. If I have second webpart that also references the parent web, I don’t know when to free it.

    If I overwrite the Render() method to dispose the parent web after rendering, I get "SPException: Trying to use an SPWeb object that has been closed or disposed and is no longer valid." Apparently the second webpart still references and needs the same object (seems to be quite logical as they both get it from the SPContext), and still needs it after rendering.

    If I dispose the parent web in the UnLoad(), it works most of the times, but sometimes I get a message in the log that the object is freed on a different thread then when it was created. It is not on my development machine (single CPU), but I’ve seen it on a testing environment. But also, UnLoad() seems to be happening only after a while, so that violates the best practice of holding on to SharePoint objects only for a short time.

    So what should I do? Would limiting the life span of a ParentWeb be a solution? That would mean that I will have to get/dispose it for 2 to 4 times per page view per webpart. What impact will that have on performance?

    So, what _IS_ the best practice handling derefenced SPWebs or SPSites (e.g. through ParentWeb, Site, RootWeb and the like)?

    I would like to make a suggestion that the SharePoint development team changes the rules, so that all SPWebs, SPSites etc. that are opened through deferencing (e.g. SPWeb.ParentWeb, SPWeb.Site, SPSite.RootWeb SPSite.AllWebs() etc.) are property of the "owning" object, and will be disposed of by that owning object. For my example, the parent web should be disposed of when the context web (the one I get through SPContext.Current) is disposed of by the webpart page manager.

    Or, even better: make sure the GC can do it’s work properly. The current system looks like an even bigger mess than badly implemented COM objects. Or please tell me that I am wrong!

    Thanks again for the insight, and I hope you can clear things up further for me!

    Cheers,

    Alex

    Reply

  26. Hi Alex,

    all SPSite/SPWeb objects retrieved through SPContext are not required to be disposed. This also includes SPSite/SPWeb objects created as reference from other SPSite/SPweb objects retrieved through SPContext.

    The SPContext object tracks all SPSite/SPWeb objects created from its objects and disposes them as soon as the SPContext object is disposed at the end of the request.

    Cheers,

    Stefan

    Reply

  27. Stefan,

    I’ve made the change in the Registry (added the HeapSettings key and the SPRequestStackTrace DWORD) but the stack trace doesn’t appear in my logs. I’ve checked and double-checked the Registry setting. Am I looking in the wrong place? Is there some kind of reset I need to do?

    I’ve posted about this problem on Stack Overflow: http://stackoverflow.com/questions/218613/proper-disposal-of-sharepoint-objects

    Reply

  28. Hi Robert,

    sounds as if you did not restart the process.

    The registry change requires a restart of the services to be catched.

    Cheers,

    Stefan

    Reply

  29. Hi Stefan,

    I have a SharePoint Publishing site that I created in SharePoint Designer.  I’m not using any custom code to my knowledge but my default.aspx page will not load on certain systems resulting in a memory error.  Could my publishing site be suffering from memory leak issues?  I guess my question is if I didn’t use any custom code to create this Publishing Site are the SPweb, SPsite and PublishingWeb objects being properly disposed?

    Thanks,

    Jason

    Reply

  30. Hi Jason,

    if you did not code anything and did not include any 3rd party component then everything should be properly disposed.

    I would suggest to open a support call with Microsoft to get this problem analyzed in more detail.

    Cheers,

    Stefan

    Reply

  31. Hi Stefan,

    The question I ask myself is why not just expose SiteMapNode properties only (eg Title, Url), until the code actually asks for SPWeb specific data (through PortalWebSiteMapNode.GetProperty)

    I appreciate it needs to be security trimmed, but it seems wasteful to create a whole SPWeb object (with 2Mb unmanaged object) just to get lightweight info for navigation.

    Is there a roadmap for improving this?

    Thanks

    Martin

    Reply

  32. Hi Martin,

    in order to fill the SiteMapNode properties you have to read them from the underlaying object. So the SPWeb object has to be created to read the URL and Title from it and fill it into the site map node object.

    That’s what happens.

    Cheers,

    Stefan

    Reply

  33. Hi Stefan,

    Thanks for the swift reply. (I hope this isn’t a double post)

    Would it be wrong to call this a design flaw?

    We have objects like SPQuery to get efficient access to other types of SharePoint data without the overhead of the object model, what about something similar for navigation?

    Thanks

    Martin

    Reply

  34. Hi Martin,

    I’m not sure if you could easily implement the required functionality – e.g. enumeration of child sites with optional security trimming as provided by the site map providers – without instantiating the actual objects.

    Cheers,

    Stefan

    Reply

  35. I have discussed problems with missing dispose for SPWeb and SPSite objects earlier on my blog (e.g.

    Reply

  36. There are several articles around discussing the dispose of SPWeb and SPSite objects, e.g.: SharePoint

    Reply

  37. Linki, które posłużyły mi przy tworzeniu prezentacji, z których czerpałem wiedzę, nakładałem ją na to

    Reply

  38. SPSite and SPWeb implement the IDisposable interface

    Reply

  39. Hi stefan,

    Thanks for your effort to explain this to us. Specifically, I notice the "Potentially excessive number of SPRequest objects" (max 21 in one thread) only during the first use of a solution after an IISRESET.

    After this the use does not generate log entries about excessive sprequest. Is this normal?

    Peter.

    Reply

  40. Hi Peter,

    that depends on your solution and what code is executed in the requests. E.g. caching could explain this.

    Cheers,

    Stefan

    Reply

  41. Stefan, thanks for the answer.

    1. Is it safe to conclude that as long I don’t get 8l1n (..object was not disposed before the end of this thread) I can ignore the excessive SPRequest objects entries in the logs?

    2. Are 21 SPObjects really excessive for an 64bit environment?

    Reply

  42. Stefan,

    About caching. I use

    SPUtility.RunWithElevatedPrivilegies() and the application Pool identity is not local admin.

    I read  -> "… this will simply revert the current user identity to the identity of the current application pool, and if this identity is not a farm administrator ->then<- your SPSite _will_ be cached in the SPRequestContext" [Understanding SharePoint SPRequest- Hristo Pavlov’s Blog].

    What if in an environment the identity pool is local admin. Should I then see the "Potentially excessive number of SPRequest objects" in every consequent use?

    Peter

    Reply

  43. Hi Peter,

    1) that depends on how high the number is in the "excessive" message. If it in the range you expect for your application you can ignore them.

    2) 21 objects is actually a very small number.

    Cheers,

    Stefan

    Reply

  44. Hi Peter,

    RunWithElevatedPrivileges will create a new SPSite object – independent from the account.

    The caching that happens in some situations is only for the current http request.

    From SPRequest perspective there is no difference if the SPSite object is cached or not.

    Cheers,

    Stefan

    Reply

  45. Stefan,

    Even after setting SPRequestStackTrace to 1 and running iisreset, we are still *not* getting stack traces for the 8l1n messages.

    Do you know why this might be ?

    Thanks,

    Kim

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftShared ToolsWeb Server ExtensionsHeapSetting]

    "SPRequestStackTrace"="1"

    Reply

  46. Hi Kim,

    the registry key above is wrong. You used "HeapSetting" where it should be "HeapSettings". Notice the missing "s" at the end.

    Cheers,

    Stefan

    Reply

  47. Stefan,

    Sorry, I copied the information from a different site when I wa composing the blog comment.  But we actually did use the HeapSettings

    Below is what we’ve set.  

    Have you actually seen it generate a stack trace for the 8l1n messages ?  What’s interesting is that we do get stack traces for the SPRequest warning messages.  I assume that this one setting controls the stack trace for both sets.  So why is a stack trace appearing for one set and not the other ?

    Also, I wonder if there’s anything else we need to configure to get the stack traces displayed for the 8l1n messages.  This is a bit frustrating as it seems to me that these are the actually useful stack traces…

    Kim

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftShared ToolsWeb Server ExtensionsHeapSettings]

    "SPRequestStackTrace"=dword:00000001

    Reply

  48. Hi Kim,

    yes I use it quite often when working on customer cases. Around 2-3 times a month.

    Its always working.

    Cheers,

    Stefan

    Reply

  49. Stefan,

    Thanks for your help !  I restarted sharepoint services and the www publishing service, and I’m seeing the allocation stack traces for the 8l1n messages. :).

    Best,

    Kim.

    Reply

  50. Stefan,

    I’m not sure if I’m reading this correctly, but it looks like I am getting stack traces for the ‘object was not disposed before the end of this thread.’  Interestingly, I *am* getting stack traces for the ‘object was reclaimed by the garbage collector instead of being explicitly freed.’   I thought both stack traces were controlled by the same registry value ?

    Am I misreading this ?  Do you have any insight into why this might be ?

    Thanks,

    Kim.

    ****************************************************************

    04/13/2009 10:19:25.02  : w3wp.exe (0x0CA8)                       0x129CWindows SharePoint Services   General                       8l1nMonitorable

    ****************************************************************

    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.  This object will now be disposed.  Allocation Id: {7B27433F-4E67-491A-BA7F-B274D9048165}  To determine where this object was allocated, create a registry key at HKEY_LOCAL_MACHINESOFTWAREMicrosoftShared ToolsWeb Server ExtensionsHeapSettings.  Then create a new DWORD named SPRequestStackTrace with the value 1 under this key.

    ****************************************************************

    04/13/2009 10:19:25.02  : w3wp.exe (0x0CA8)                       0x129CWindows SharePoint Services   General                       8l1nMonitorable

    ****************************************************************

    An SPRequest object was reclaimed by the garbage collector instead of being explicitly freed.  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.  Allocation Id: {A143F475-52DD-45BC-B897-AF4C9BEFFBC1}  This SPRequest was allocated at

       at Microsoft.SharePoint.Library.SPRequest..ctor()

       at Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous)

       at Microsoft.SharePoint.SPWeb.InitializeSPRequest()

       at Microsoft.SharePoint.SPWeb.EnsureSPRequest()

       at Microsoft.SharePoint.SPWeb.get_Request()

       at Microsoft.SharePoint.SPFieldCollection.EnsureFieldsSafeArray(Boolean bGetFullXML)

       at Microsoft.SharePoint.SPFieldCollection.Undirty(Boolean bGetFullXML)

       at Microsoft.SharePoint.SPFieldCollection.Undirty()

       at Microsoft.SharePoint.SPBaseCollection.System.Collections.IEnumerable.GetEnumerator()

       at GreyPkgWFApproval.Utils.getMissingFields(SPList spList, String[] listColumns)

    Reply

  51. Hi Kim,

    that is interesting. Haven’t seen this.

    Anyway: the stack clearly shows the 3rd party control that is causing the leak.

    Cheers,

    Stefan

    Reply

  52. This is pretty weird, but it might help other people who may have run into the same issue (stack trace not appearing for the ‘object was not disposed before the end of this thread’).

    I tried configuring the related IIS application pool so that it would recycle the worker process after 1 request.  This actually caused the stack trace to start appearing for the above type messages.  Then, to double-check, I de-selected the ‘Recycle worker process(number of requests)’ option and noted that the stack trace no longer appeared.  Instead it presented the misleading message about setting the SPRequestStackTrace DWORD value to 1 — misleading because it had already been set.

    Finally, I set the ‘Recyle worker process (number of requests)’ to 10 and the stack trace appeared again for the above ‘end of thread’ type messages.

    By the way, for all of the above experiments, I had the ‘Recycle worker processes(in minutes)’ also selected and set to 15 minutes.

    So I think this may be a bizarre Microsoft bug, where the ‘end of thread’ stack traces only appears if the number of requests item is selected.

    Between the two log messages below, the only change I made was to select and set the ‘Recycle worker process (number of requests’)

    to 10.

    Kim.

    ****************************************************************

    04/13/2009 14:40:31.96  : w3wp.exe (0x1428)                       0x1470Windows SharePoint Services   General                       8l1nMonitorable

    ****************************************************************

    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.  This object will now be disposed.  Allocation Id: {A00EAB6F-6BF1-4A5D-A502-AD330B3C3373}  To determine where this object was allocated, create a registry key at HKEY_LOCAL_MACHINESOFTWAREMicrosoftShared ToolsWeb Server ExtensionsHeapSettings.  Then create a new DWORD named SPRequestStackTrace with the value 1 under this key.

    ****************************************************************

    04/13/2009 14:47:43.22  : w3wp.exe (0x1400)                       0x14F0Windows SharePoint Services   General                       8l1nHigh    

    ****************************************************************

    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.  This object will now be disposed.  Allocation Id: {0C8F72A4-C270-442F-B7A6-11BE72E7849A}  This SPRequest was allocated at

       at Microsoft.SharePoint.Library.SPRequest..ctor()

       at Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous)

       at Microsoft.SharePoint.SPSite.GetSPRequest()

       at Microsoft.SharePoint.SPSite.get_Request()

       at Microsoft.SharePoint.SPSite.GetReusableAclForScope(Guid scopeId)

       at Microsoft.SharePoint.Publishing.AclCache.GetAclForScope(Guid scopeId)

       at Microsoft.SharePoint.Publishing.CachedArea..ctor(PublishingWeb area, String id, String parentId, String title, String url, String description, CachedObjectFactory factory)

       at Microsoft.SharePoint.Publishing.CachedArea.CreateCachedArea(PublishingWeb area, CachedObjectFactory factory, String parentId)

       at Microsoft.SharePoint.Publishing.CachedObjectFactory.CreateObject(PublishingWeb area, String parentUrl)

       at Microsoft.SharePoint.Publishing.CachedObjectFactory.CreateObject(PublishingWeb area)

    Reply

  53. Stefan,

    Just an update — this might be useful to other people as well:

    Basically, it looks like the IIS application pool property ‘Recycle worker process (number of requests)’ is the critical property to set, and the only one that generates a stack trace for the ‘object was not disposed before the end of this thread’ message.  It’s best to leave the other recycle options deselected, as if they trigger, they actually won’t generate a stack trace.  I’ve verified this for the ‘Recycle worker processes (in minutes)’ option.

    I have not verified whether the Memory recycling options also generate a stack trace for the ‘object was not disposed before the end of this thread’ message(s).

    Best,

    Kim.

    Reply

  54. Stefan,

    Just an update — this might be useful to other people as well:

    Basically, it looks like the IIS application pool property ‘Recycle worker process (number of requests)’ is the critical property to set, and the only one that generates a stack trace for the ‘object was not disposed before the end of this thread’ message.  It’s best to leave the other recycle options deselected, as if they trigger, they actually won’t generate a stack trace.  I’ve verified this for the ‘Recycle worker processes (in minutes)’ option.

    I have not verified whether the Memory recycling options also generate a stack trace for the ‘object was not disposed before the end of this thread’ message(s).

    Best,

    Kim.

    Reply

  55. Issue: SharePoint Sites may log “Excessive SPRequest Objects,” under normal use. When I first saw this

    Reply

  56. Hey Stefan,

    We implemented your recommended changed on our QA SharePoint WFE server and then the WFE started throwing the following error for some unknown reason:

    Server Error in ‘/’ Application.

    ——————————————————————————–

    Specified cast is not valid.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.InvalidCastException: Specified cast is not valid.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.  

    Stack Trace:

    [InvalidCastException: Specified cast is not valid.]

      Microsoft.SharePoint.SPRequestManager.get_SPRequestsPerThreadWarning() +588

      Microsoft.SharePoint.SPRequestManager.Add(SPRequest request, Boolean shareable) +695

      Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous) +2626

      Microsoft.SharePoint.SPRequestManager.GetContextRequest(SPRequestAuthenticationMode authenticationMode) +192

      Microsoft.SharePoint.Administration.SPFarm.get_RequestNoAuth() +25

      Microsoft.SharePoint.ApplicationRuntime.SPHttpHandler.get_Hash() +162

      Microsoft.SharePoint.ApplicationRuntime.SPHttpHandler.get_AppDomainIdHeader() +152

      Microsoft.SharePoint.ApplicationRuntime.SPHttpHandler.OverrideExecuteUrlPath() +507

      System.Web.DefaultHttpHandler.BeginProcessRequest(HttpContext context, AsyncCallback callback, Object state) +83

      System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8677954

      System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

    ——————————————————————————–

    Version Information: Microsoft .NET Framework Version:2.0.50727.3603; ASP.NET Version:2.0.50727.3082

    The only way to get the WFE back online was to removed the registry entries and restart the services.

    Researching the particular error yielded nothing except one Google cached paged that had the same problem on 9/29/09.

    Do you have any ideas what might have caused the server to behave like that? (I’m not expecting you to miraculously know or be able to resolve the problem, but I’m hoping you might have seen a server do that before when applying these entries)

    Thanks

    C

    Reply

  57. Hi Cornelius,

    I have never seen this.

    But the error indicates that you entered the registry value with the incorrect type. Did you use DWORD or string?

    It should be a DWORD.

    Cheers,

    Stefan

    Reply

  58. I have a strange error here.I have a content source. Whenever crawl runs,SQL connections goes too high. and only thing i got in the ULS logs is below

    Potentially excessive number of SPRequest objects (12) currently unreleased on thread 9.  Ensure that this object or its parent (such as an SPWeb or SPSite) is being properly disposed.  Allocation Id for this object: {329BFC8D-6CB9-4C18-8048-72166ABE4E08} Stack trace of current allocation:    at Microsoft.SharePoint.SPRequestManager.Add(SPRequest request, Boolean shareable)     at Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous)     at Microsoft.SharePoint.SPWeb.InitializeSPRequest()     at Microsoft.SharePoint.SPWeb.EnsureSPRequest()     at Microsoft.SharePoint.SPWeb.get_Request()     at Microsoft.SharePoint.SPWeb.SetMondoPr…

    …ocHint(Int32 hint)     at Microsoft.SharePoint.SPSite.OpenWeb(Guid gWebId, Int32 mondoHint)     at Microsoft.SharePoint.SoapServer.CWebChange.CheckDB()     at Microsoft.SharePoint.SoapServer.CWebChange..ctor(CChange parentChange, String strID, Boolean fDeleteEvent)     at Microsoft.SharePoint.SoapServer.CSiteChange.GetWeb(String strID, Boolean fDeleteEvent)     at Microsoft.SharePoint.SoapServer.SiteDataImpl.ProcessChanges(CChange change, SPChangeCollection spChangeCollection, SPChangeToken& spLastChangeToken, Int64& lTimeLeft)     at Microsoft.SharePoint.SoapServer.SiteDataImpl.GetChanges(CChange change, SPChangeToken& spChangeToken_Start, SPChangeToken spChangeToken_End, Int64 lTimeout)     at Microsoft.SharePoint.SoapServer.SiteDataImpl.GetChanges(ObjectType objectType, String contentDa…

    1…tabaseId, String& startChangeId, String& endChangeId, Int32 Timeout, Boolean& moreChanges)     at Microsoft.SharePoint.SoapServer.SiteData.GetChanges(ObjectType objectType, String contentDatabaseId, String& LastChangeId, String& CurrentChangeId, Int32 Timeout, Boolean& moreChanges)     at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)     at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)     at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)     at System.Web.Services… Windows SharePoint Services   General                       0 Medium   ….Protocols.LogicalMethodInfo.Invoke(Object target, Object[] values)     at System.Web.Services.Protocols.WebServiceHandler.Invoke()     at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()     at System.Web.Services.Protocols.SyncSessionlessHandler.ProcessRequest(HttpContext context)     at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()     at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)     at System.Web.HttpApplication.ApplicationStepManager.ResumeSteps(Exception error)     at System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)     at System.Web.HttpRuntime.ProcessRequestInternal(HttpWo…

    …rkerRequest wr)     at System.Web.HttpRuntime.ProcessRequestNoDemand(HttpWorkerRequest wr)

    Looks like the same error. But it happnes with crawl ? Any pointers. we have custom webparts. But RendertoIndexer property is already set to false. So webparts are not loaded during crawl. So what might be the reason of such high number of SP Requests ?

    Reply

  59. Hi Subhasis,

    this is expected and by design. During crawl the same happens as if you would browse to the website. Except that crawl puts a pretty high load on the site. Every single instantiated SPWeb objects maintains its own SQL connection. As the crawler uses multiple threads to crawl the site it is like a load test against your site. All the navigation controls on the pages will get instantiated and will instantiate SPWeb objects.

    So the only way to reduce the number of SQL connections would be to reduce the number of threads the crawler is using.

    Cheers,

    Stefan

    Reply

  60. How does this apply to SharePoint 2010 and PowerShell with objects like SPSite, SPWeb, etc. Are there any best practices as to use this objecct and  loop through them in PowerShell?

    Reply

  61. Hi Jane,

    it does not matter if this is in C#, VB.NET or powershell.

    You always have to dispose these objects.

    Cheers,

    Stefan

    Reply

  62. Hi All,

    I have a local intranet site that has approximately 2000 users. We have a custom web part deployed at the homepage of our site and people have complained that the web part disappears sometimes, it can be brought back by refreshing the page. The web part has caching enabled and we tested it at our Dev and QA servers and can not reproduce the same error.

    I checked the ULS logs of our production enviornment and see the following errors with high priority:

    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.  This object will now be disposed.  Allocation Id:  {31C1D221-691D-4D95-839E-CFE855F7B114} To determine where this object was allocated, create a registry key at HKEY_LOCAL_MACHINESOFTWAREMicrosoftShared ToolsWeb Server ExtensionsHeapSettings. Then create a new DWORD named SPRequestStackTrace with the value 1 under this key.

    I tried creating a key as per their suggestion thinking I would be pinpointed to the appropriate DLL/Method. That was not very helpful.

    I tried using Microsft SharePoint Memory Dispose Checker and thought it would resolve my problem and found 2 methods (not the same web part with caching) in my solution not disposing memory as per the best practices. I fixed them both and the results slighly improvised. I googled your blog and increased the threshold value of SPRequests. That again did thin down the errors, however I still have some errors coming up. My first guess to my web part caching problem would be to remove all these errors as that may burden the server.

    I am sure there are no other codes that are not disposing memory as per the best practise. What am I missing? Why am I not able to reproduce the same web part error on my Dev and QA boxes? Why am I still getting the errors in my ULS Logs??

    Thoughts??

    Reply

  63. Hi Ali,

    after creating the key you need to do an IISRESET or restart the application pool to ensure that the setting takes effect.

    Cheers,

    Stefan

    Reply

  64. Thanks for your reply Stefan. The settings did take place as per your suggestion but I am not able to remove the memory leaks error, not sure what is causing it as all my codes are properly disposing SPSite and SPWeb objetcs. Is there anything you think I should see ti improve the memory leakage errors. Also I increased the threshold to 150 in the registry key as per your recommendation to play with the threshold, but still no resolute.

    Thanks.

    Reply

  65. Hi Ali,

    not every memory leak is related to SPWeb or SPSite. A detailed analysis of the memory pattern might be required to track this down. Also ensure to be on the latest SharePoint patch level to ensure that you are not running into an already fixed problem in the product.

    Cheers,

    Stefan

    Reply

  66. As I got the question about this recently: in SP2016,2019 and Subscription Edition the ULS tag is no longer “8l1n” – it is now “nask”.

    Reply

Leave a Reply to Alex Dresko Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.