Free the SPWeb!

Every SharePoint developer knows that you need to free resources that you have used... like SPWeb (and others too!). Most often freeing up the resources are easily managed with the nice using -statement like this:

 1234567
 using (SPSite site = new SPSite("http://localhost/")){  using (SPWeb web = site.OpenWeb("/"))  {    // TODO: Do something funny  }}

But you can do that stuff manually with try-finally + <object> .Displose(); . This is common .NET knowledge. But what happens if you don't do that? How much are we wasting resources if we just fail/forget to free objects? Well I tested this stuff a little bit and it was pretty suprising for me too... but before I'm going to give the results I'll show the examples I used:

 12345678910
 using (SPSite site = new SPSite("http://localhost/")){  for (int i = 0; i < COUNT; i++)  {    using (SPWeb web = site.OpenWeb("/"))    {      // TODO: Do something funny    }  }}

This one is the "normal" way to use SPWeb and SPSite. I'll call this  code 1.

 

 123456789
 using (SPSite site = new SPSite("http://localhost/")){  for (int i = 0; i < COUNT; i++)  {    SPWeb web = site.OpenWeb("/");    // TODO: Do something funny    // Missing: web.Dispose();  }}

This one is _really_ bad example. We're not disposing SPWeb at all! I call this code 2 (cool and creative naming right!)

 

If you run those examples in loop we can get following results (Time is measured in seconds and memory usage is in kilos):

  Code 1 (good) Code 2 (bad)
Count Time Mem Usage Peak Mem Usage VM Size Time Mem Usage Peak Mem Usage VM Size
10 1,42 37 512 37 512 36 792 1,53 42 220 42 220 44 132
100 1,67 37 456 37 456 36 808 4,41 71 932 87 656 91 028
500 2,90 37 532 37 532 36 880 * * * *
1 000 5,00 37 612 37 612 36 888 * * * *
10 000 33,38 35 400 37 524 35 724 * * * *

Note: Memory consumption is just taken from Task Manager just after test code has finished. I haven't removed the test applications "base memory usage" (=usage before calling test code) but it was 8580K.

Note: The * indicates: Unhandled Exception: OutOfMemoryException.

So from numbers after the test run we can clearly see that code 2 is just slow and terrible memory slob! It can barely run few hundred loops before my server is "running low on memory".  And if you look at the memory usage from task manager you'll see something that can't be seen from the table:

Upper image is code 2 and lower one is code 1. So after startup code 1 stays steady even if you're running loop > 1000. And in upper image you can see increasing memory usage. If the loop count is 100 or less (=No OutOfMemoryException is happening on my system) then memory decreases since all of that memory isn't used anymore and this cannot be seenfrom the table above. So the spike usage of code 2 is huge for even in < 100 loops. And if you're doing  the same stuff over 1000 times it would suck up all memory you have in your system...

But if I have managed to scare you a little bit... that's good! But still don't start making too many disposes....  don't free up stuff that you haven't allocated yourself... like SPContext.Current.Web. It's allocated by SharePoint and if you dispose it you'll get exception. Here is example web part that will dispose if there is url parameter demanding it:

 1234567
 protected override void Render(HtmlTextWriter writer){  if (this.Page.Request["Dispose"] != null)  {    SPContext.Current.Web.Dispose();  }}

And if I add that web part to page and use it normally it works fine. But when I add "Dispose=true" to the url, it will give you:

Microsoft.SharePoint.SPException: Trying to use an SPWeb object that has been closed or disposed and is no longer valid.

So don't just free all disposable objects... think first but act second since if you don't act your application will definitely get those "Unhandled Exception: OutOfMemoryException" errors.

When you next time get OufOfMemoryException then check out your code before blaming the system... you might have some bugs in there.

Anyways... Happy hacking!

J