Tuesday, March 12, 2013

SharePoint Best Practices for Performance Tuning




Rule 1: Dispose site/web object
SPSite/SPWeb –
Bad Practice
SPSite oSPsite = new SPSite(“http://server”);
SPWeb oSPWeb = oSPSite.OpenWeb();
str = oSPWeb.Title;
// bad practise since object are not disposed.
In this case, You never dispose SPSite and SPWeb. Its memory leak.
SPSite/SPWeb –
Good Practice
String str;using(SPSite oSPsite = new SPSite(“http://server”))
{
using(SPWeb oSPWeb = oSPSite.OpenWeb())
{
str = oSPWeb.Title;
}
}
You can automatically dispose of SharePoint objects that
implement the IDisposable interface by using the Microsoft Visual C# using statement

Rule 2: Do not Dispose current site/web object
SPSite/SPWeb –
Bad Practice
using(SPSite oSPsite = SPContext.Current.Site) //bad practice
{
using(SPWeb oSPWeb = SPContext.Current.Web) //bad practice
{
str = oSPWeb.Title;
}
}
Do not dispose current context object
SPSite/SPWeb –
Good Practice
String str;SPSite oSPsite = SPContext.Current.Site;
SPWeb oSPWeb = SPContext.Current.Web;
str = oSPWeb.Title;
You can automatically dispose of SharePoint objects that
implement the IDisposable interface by using the Microsoft Visual C# using statement

Rule 3: Get SPList Object
SPWeb.Lists (“name”) – style="color: #ff0000;">Bad Practice
using (SPSite site = new SPSite(strSite))
{
using (SPWeb web = site.OpenWeb())
{
SPList oList = web.Lists ["MyList"]
}
}
In this case, it loads the metadata*
of the all lists in that specific SPWeb object.
SPWeb.GetList (string strUrl) –
Good Practice
using (SPSite site = new SPSite(strSite))
{
using (SPWeb web = site.OpenWeb())
{
SPList oList = web.GetList(“/list/AllItem.aspx”)
}
}
In this case, it loads the metadata*
of the all lists in that specific SPWeb object.

Rule 4: Get SPListItem Object
SPList.Items[int idx] – style="color: #ff0000;">Bad Practice
using (SPSite site = new SPSite(strSite))
{
using (SPWeb web = site.OpenWeb())
{
SPList oList = web.GetList(“http://Site/list/AllItem.aspx”);
for(int idx =0; idx< oList.ItemCount; idx ++)
{
string strLstItemName = oList.Items[idx].Name;
}
}
}
In this case, for each iteration oList.Item[idx] will
load a SPListItemCollection.
SPListItemCollection[int idx] –
Good Practice
using (SPSite site = new SPSite(strSite))
{
using (SPWeb web = site.OpenWeb())
{
SPList oList = web.GetList(“http://Site/list/AllItem.aspx”);
SPListItemCollection oListItems = oList.Items;
for(int idx =0; idx< oList.ItemCount; idx ++)
{
string strLstItemName = oListItems[idx].Name;
}
}
}
In this case, in the memory this code will load only one
SPListItemCollection

Rule 5: SPListItem in Event Handler
SPListItem –
Bad Practice
public override void ItemAdded(SPItemEventProperties properties)
{
using (SPSite oSite = new SPSite(properties.WebUrl))
{
using (SPWeb oWeb = oSite.OpenWeb())
{
SPList oList = oWeb.Lists[properties.ListId];
SPListItem oListItem = oList.GetItemByUniqueId(properties.ListItemId);
}
}
}
In this case, we are unnecessarily giving extra load to
the memory by adding so many memory consuming APIs
SPListItem –
Good Practice
public override void ItemAdded(SPItemEventProperties properties)
{
SPListItem oItem = properties.ListItem;
}
In this case, we have reduced lots of code and it will
return the current ListItem by using “proerties”

Rule 6: item count
SPList.Item.Count –
Bad Practice
using (SPSite site = new SPSite(strSite))
{
using (SPWeb web = site.OpenWeb())
{
SPList oList = web.GetList(“http://Site/list/AllItem.aspx”);
int iCount = oList.Items.Count;
}
}
In this case, oList.Items.Count, first it will load all
the SPListItems in the memory and then it will find out the total count.
SPList.Item.ItemCount – style="color: #339966;">Good Practice
using (SPSite site = new SPSite(strSite))
{
using (SPWeb web = site.OpenWeb())
{
SPList oList = web.GetList(“http://Site/list/AllItem.aspx”);
int iCount = oList.ItemsCount;
}
}
In this case, ItemCount is a part of metadata of the SPList
object and this will get generated whenver we create a SPList instance

Rule 7: Applying Lock
Cache –
Bad Practice
public void CacheData()
{
SPListItemCollection oListItems;oListItems = (SPListItemCollection)Cache["ListItemCacheName"];
if(oListItems == null)
{
oListItems = DoQueryToReturnItems();
Cache.Add(“ListItemCacheName”, oListItems, ..); // bad practice
}}
Although the use of the cache in this example is functionally
correct, because the ASP.NET cache object is thread safe, it introduces potential
performance problems
Cache with lock
Good Practice
private static object _lock = new object();public void CacheData()
{
SPListItemCollection oListItems;lock(_lock) // Good Practice
{
oListItems = (SPListItemCollection)Cache["ListItemCacheName"];
if(oListItems == null)
{
oListItems = DoQueryToReturnItems();
Cache.Add(“ListItemCacheName”, oListItems, ..);
}
}
}
In this case, you do not need to suspend all threads while
checking to see if the data is already cached.

Rule 8: SPQuery
SPQuery –
Bad Practice
SPQuery query = new SPQuery();
SPListItemCollection spListItems ;StringBuilder sb = new StringBuilder();
sb.Append(“<OrderBy Override=”TRUE”><FieldRef Name=”ID”/></OrderBy>”);
//.. Append more text as necessary ..
query.Query = sb.ToString();spListItems = spList.GetItems(query);
Although the use of SPQuery is good but its increase performance
since its does not use rowlimit, viewfields
SPQuery –
Good Practice
SPQuery query = new SPQuery();
SPListItemCollection spListItems ;// Include only the fields you will use.
query.ViewFields = “<FieldRef Name=”ID”/><FieldRef Name=”ContentTypeId”/>”;
query.RowLimit = 200; // Only select the top 200.StringBuilder sb = new StringBuilder();
sb.Append(“<OrderBy Override=”TRUE”><FieldRef Name=”ID”/></OrderBy>”);
//.. Append more text as necessary ..
query.Query = sb.ToString();spListItems = spList.GetItems(query);
In this case, You use SPQuery which has rowlimit and view
fields. This increase performance

Table 1. Alternatives to SPList.Items  
   
Poor Performing Better Performing
Methods and Properties Alternatives
SPList.Items.Count SPList.ItemCount
SPList.Items[System.Guid] SPList.GetItemByUniqueId(System.Guid)
SPList.Items[System.Int32] SPList.GetItemById(System.Int32)
SPList.Items.GetItemById(System.Int32) SPList.GetItemById(System.Int32)
SPList.Items.ReorderItems (System.Boolean[],System.Int32[],System.Int32) Perform a paged
query by using SPQuery and reorder the items within
each page.
SPFolder.Files.Count SPFolder.ItemCount
SPList.Items.XmlDataSchema Create an SPQuery
object to retrieve only the items you want.
SPList.Items.NumberOfFields Create an SPQuery
object (specifying the ViewFields)
to retrieve only the items you want.

No comments:

Post a Comment