cd ../blog

SPRequest – Things I Couldn't Find About It

Understanding SPRequest leaks in SharePoint — what causes them, how to spot them in ULS logs, and the difference between good and bad SPSite/SPWeb disposal patterns.

</>

Since I’ve been doing more and more code reviews and tracking down performance issues, I keep seeing the same category of “bad performance” development.

Before reading anything more — go check your ULS logs on production.

Pay close attention to errors like:

  • An SPRequest object was reclaimed by the garbage collector instead of being explicitly freed.
  • An SPRequest object was not disposed before the end of this thread.
  • Potentially excessive number of SPRequest objects (30) currently unreleased on thread 16.
  • Detected use of SPRequest for previously closed SPWeb object.

These are not good. They’re a reliable indicator of performance issues.

What Is SPRequest?

Pavlov wrote a great deep-dive on what SPRequest actually is. Worth reading.

What Causes These Warnings?

Creating too many SPSite objects in a short time will trigger the “excessive number of SPRequest objects” warning. But the more common mistake is subtler.

Which of these two patterns is wrong?

Pattern A (Bad):

SPSite site = new SPSite(url);
SPWeb web = site.OpenWeb();
SPList list = web.Lists["MyList"];
site.Dispose();
web.Dispose();

// ... continue using `list` here
foreach (SPListItem item in list.Items) { ... }

Pattern B (Good):

using (SPSite site = new SPSite(url))
using (SPWeb web = site.OpenWeb())
{
    SPList list = web.Lists["MyList"];
    foreach (SPListItem item in list.Items) { ... }
}

Pattern A generates the SPRequest errors. Why?

Because you’re creating SPSite and SPWeb, getting the SPList reference, then disposing the parents — but continuing to use the SPList object after the parent is disposed. The list still holds a reference to the underlying SPRequest, but the parent context it belongs to is gone.

Pattern B is correct. Keep all usage of objects obtained from SPSite/SPWeb inside the using block.

Enabling Stack Traces in SP2013

In SharePoint 2013, the SPRequest warning includes this line:

To determine where this object was allocated, set Microsoft.SharePoint.Administration.SPWebService.ContentService.CollectSPRequestAllocationCallStacks = true.

To enable this via PowerShell (script from Stefan Gossner’s blog):

$contentService = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$contentService.CollectSPRequestAllocationCallStacks = $true
$contentService.Update()

Once enabled, the ULS warnings will include a full stack trace showing exactly where the bad object was allocated — making it trivial to find the offending code.

The Golden Rule

Never dispose SPSite or SPWeb while you still need objects obtained from them. Never use objects obtained from a disposed SPSite/SPWeb.

OK for a handful of users. When your solution is used by 50,000 users, this will cause serious performance degradation.

Further Reading

Happy reading! 😊