Just recently I’ve had the joy of creating a web part that reads a list. It was decided the list data needed to be presented in a better way with the ability to page the data and drill down.
I created the part and it looked pretty good, I thought, then came the time to test it. It worked fine for me but that was before I populated it with 100 items with 5 items it was fine, of course. Bugger.
Well I spent a fair few hours ripping my code apart, its strange when you optimise code as you look at it with different eyes and what seemed good sensible ideas, became glaring monstrosities. In a few dev cycles I brought the times down from 16 seconds to render the part to 10, to 4.
But four seconds!!! Thats rubbish.
I had object cached almost everything in sight, I’d removed loads of control creates and just raw HTML’d the lot I got to the point I was checking every string concatenation was done efficiently. I even tried to get DevPartner community edition to see where the bottlenecks where (this just did not work, great for windows apps, but could not get this working for sharepoint (if you have leave a clue)).
Luckily for me others in our team had come across slow list API before, and spent days figuring it out so I looked in their code and spotted one line of code they did that I didn’t, but that couldn’t be it surely.
I had been doing the equivalent to this.
SPList selectedList;
selectedList= currentSite.Lists[“Locations”];string Title=selectedList.Items[“Title”].ToString();
Obivously I had more than just title to display and used the same technique all the way down. However by doing this
SPList selectedList;
SPListItemCollection myItems;
selectedList= currentSite.Lists[“Locations”];
myItems=selectedList.Items;string Title=myItems[“Title”].ToString();
This gave HUGE performance increases. Apparently and I’ve yet to find the article myself, but the lads told me they read that unless you object cache the items collection it hits the DB but assigned to a local variable and it caches the data. This would appear to be the case based on the speed increase I have seen here.
So next time your list access is slow try the above.
tags: sharepoint, programming+sharepoint, .net, sharepoint+list+api, slow+sharepoint
chap, re-read it. I know my English is pretty bad, and you’re going the same way.
There was no article; I figured out that assigning the items collection to a local variable gave huge performance benefits.
Mark and I performed a great deal of analysis, and concluded that – without a local item collection – the network becomes a bottleneck. Performing your changes in memory is, naturally, much quicker.
Yes I agree my english is bad, it takes me several attempts to get something right, so I dont bother on the blog, just get the point across, which I think I have.
What I found interesting about this is that local items collection should just be an object reference and to make a local copy should not give you such larger performance gains. It would seem that in setting a local copy the object realises this and serialises the data perhaps.
I might dig out reflector for this.
Article in the SharePoint Products and Technologies SDK detailing how to optermise for performance can be found here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/spptsdk/html/tsovOMGdlnsOptimCodePerf_SV01074494.asp
The key paragraph in this article is: In the following example, separate objects for the Tasks list must be instantiated each time the indexer is used in setting properties or calling the method for updating. This is not a recommended practice.
This suggests that there is no internal cacheing on the Items property, so I figure it’ll look something like the following:
public SPListItemsCollection Items {
get {
return /* Code to get entire list from DB here */;
}
}
A simple rewite of the property to be as follows would make the API faster, but also would increase memory usage.
private SPListItemsCollection _listItemsCollection;
public SPListItemsCollection Items {
get {
if (this._listItemsCollection == null) {
this.listItemsCollcetion = /* Insert code to get from DB here */;
}
return this._listItemsCollection;
}
}
You’ll notice that SPListItemCollection or SPList do not implement IDispose and therefore rely on the GC to clean up objects, so a call to only get one item in the list would result in the entire list sitting in memory until GC collects. This would be a performance killer, so the choice is left up to the developer to decide to get one item from the collection, or the entire collection.
By the way, SPSite and SPWeb do implement the Dispose pattern, so to avoid eating up memory on a Web Part that is hit quite a bit, ensure that Dispose is always called.