The importance of Performance (part 1)

It’s been some time since my last blog post. This had mostly to do with some personal changes in my life and not really having interesting topics. But since that last post I’ve seen some “error in thinking” that most SP developers did, that I’ve decided to write a blog series about writing code and more importantly, writing code that does the job quicker or better (improving code quality).

Keep in mind that I never criticize the code of other developers, you never know in what mindset the code has been written. Were they on time pressure, lack of knowledge or is it more fundamental and they always write code the same way. Nothing is wrong with that, but as a consultant it is a good nature to question sometimes your own code and asking yourself, can’t this be done faster or is this the correct way?  

Tools

Tools are meant to help you in your day to day work. So I’m not going to list all the tools that I use on a daily basis. There are enough blog posts about that (Zimmergrem did a nice blog post about this).

But SPCop (free tool) or SPCaf are worth the extra mention. This began as a community tool encapsulating the SPDisposeCheck and now it’s so much more. I even suggest to have it installed on the TFS so that the developer gets a full report when checking in his or her code.

But with the SPDisposeCheck there is still a check that hasn’t been fixed yet.

Maybe this is general knowledge or not. But I do see sometimes that the rootweb of the SPLimitedWebPartManager is not being disposed. So in the code below manager.web.Dispose() needs to be called manually.

If you are asking , what is the SPLimitedWebPartManager than you didn’t do some webpart changes to Pages yet. if that’s a good or a bad thing, I leave that up to you :-).

SPLimitedWebPartManager manager = SPContext.Current.Web.GetLimitedWebPartManager(Page.Request.RawUrl, PersonalizationScope.Shared);
manager.Web.Dispose();

So this is one that keeps showing up as well and causing memory leaks.

Next up are a few changes that were done in the OM model that some of you might not know about.

Examples:

Items.Add() or AddItem()

Adding a new item to a list, you have 2 ways to add an item to a list.

SPList.Items.Add(); or SPList.AddItem()

both do the exact same thing, adding a new item to a list :-), but it is the way that they are doing it, that is different. using the first was the only option in SharePoint 2007, but since SharePoint 2010 the OM code has changes some with a lot of extra functions. The part that isn’t good in the first part, is that it iterates over all the items and than returns the new item object. While the second part of the code launches a query and returns a new item. The last is much quicker if you have a lot of items in your list.

This is because the entire collection is parsed to find the last ID in the list. if you are doing this a lot than you put more stress on the back end system than needed.

Items.Count() or ItemCount()

If you do SPList.Items.Count this is also the same thing, you iterate through the entire collection. Should you use SPList.ItemCount this will give the result in a much cleaner and faster way.

What is even worse is to use

for (int i = 0; i < 100 && i < activeList.Items.Count; i++)
                      {
                          SPListItem listItem = activeList.Items[i];
                          // htmlWriter.Write(listItem[‘Title’]);
                          // do something here like printing title value
                      }

This is horrible in performance, every time the entire collection gets iterated. better is to use activeList.ItemCount(); , this is just a property that gets updated every time an item is added. And provides the data much quicker.

for (int i = 0; i < 100 && i < activeList.ItemCount ; i++)
                      {
                          SPListItem listItem = activeList.Items[i];
                          // htmlWriter.Write(listItem[‘Title’]);
                          // do something here like printing title value
                      }

String Concatenation

when hunting for performance this was one that surprised me the most. If you look for examples on the net about string concatenation than most of them are telling the following.

There are 3 ways to put multiple strings together.

1. string dummy = “test” + “test2” + “test3”;

2. string dummy = string.format(“{0}{1}{2}”,”test”,”test2”,”test3”);

3. string dummy = new StringBuilder().Append(‘test’).Append(‘test2’).Append(‘test3’).ToString();

What do you think is faster?

Apparently (in the fastest sequence) , 1 , 3 and 2 all the way at the back.

As using string.format on a regular basis it kind of surprised me. Of course it depends on how many times you are using it and big the string is. So this is a “it depends” situation.

SPSecurity.RunWithElevatedPriviliges

Ok, it has nothing to do with performance but still it should be a best practice.

This bugged me for a long time, personally I don’t like to use this just to read something from somewhere that is “not accessible” by a normal user. Most SharePoint Developers know this method but few ask themselves if this is actually the correct way or that is there another way to get what they want.

Running this method makes the code between the { and } all powerful. Sure it will get the data from a hidden SharePoint list that has no security set (or where the user(s) has no access to). But it also allows to do things on the file system of the server. Little too much power if you ask me.

So instead of using the code below, that in 90% of the cases is only used to stay in SharePoint and not going to the file system.

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite site = new SPSite(SPContext.Current.Site.ID))
    {
        using (SPWeb web = site.OpenWeb())
        {

What else is in place to get data from a list or library where normal users don’t have access? Nothing you say?

Have you ever looked at the overload of an SPSite object?

using (SPSite dummySite = new SPSite(SPContext.Current.Site.ID, SPContext.Current.Site.SystemAccount.UserToken))
{
    using (SPWeb web = dummySite.OpenWeb())
    {

You can do something like this. Sure it still is too much power but at leastatleast you are restricting that power to SharePoint use only.

Edit 6/10/2014

After looking over the code from above together with Karine Bosch both usage of runwith or using the systemtoken, Karine noticed that the operation with the SystemAccount token takes longer to run than the runwith. If someone knows of a third option on run with more privileges please let me know. 

Think about it and let me know if you have any comments about the things that I’ve written here.

Leave a Reply

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