Tuesday, January 15, 2013

Performance Matters - SP2010!

I was researching about the performance in SP2010 and got this rich content of some really good to do's and not to do's which I would like to share.

Why Dispose?

Several of the SharePoint Foundation objects, primarily the SPSite class and SPWeb class objects, are created as managed objects. However, these objects use unmanaged code and memory to perform the majority of their work. The managed part of the object is much smaller than the unmanaged part. Because the smaller managed part does not put memory pressure on the garbage collector, the garbage collector does not release the object from memory in a timely manner. The object's use of a large amount of unmanaged memory can cause some of the unusual behaviors described earlier. Calling applications that work with IDisposable objects in SharePoint Foundation must dispose the objects when the applications finish using them. You should not rely on the garbage collector to release them from memory automatically.
 
Do not instantiate an SPWeb, SPSite, SPList, or SPListItem object within an event receiver.

Event receivers that instantiate these objects instead of using the instances passed via the event properties can cause the following issues:
  • Significant additional roundtrips to the database (one write operation can result in up to five additional roundtrips in each event receiver).
  • Calls to the Update method on these instances can cause subsequent Update calls in other registered event receivers to fail.
If you do not retrieve SPWeb, SPSite, SPList, or SPListItem objects from SPItemEventProperties and instead instantiate those objects within an event receiver, when you call Update on the new instances, you must clear it with the Invalidate method in the appropriate child class of SPEventPropertiesBase (for example, SPItemEventProperties.InvalidateListItem or SPItemEventProperties.InvalidateWeb).

Avoid creating and destroying objects unnecessarily in code, as this may require that extra queries be made against the database and may even involve code that is incorrect.

To return a single item from a collection, always use a Get* method when one is provided through a parent object, instead of iterating through the entire collection and using an indexer. For example, the SPWeb class provides GetFile, GetFolder, and GetListItem methods that you can use to return single items.


An SPWeb or SPSite object can occupy a lot of memory.

Avoid constructing objects of these types simply to get a reference to a parent object. Instead, to get a reference to a web application, use the static SPWebApplication.Lookup(Uri) method, and pass it a Uri object that is created with the URI of the web application. You can then get a reference to the farm by using the Farm property of the web application object. (You can get a reference to a remote farm by using the static Open(String) method.) The ContentDatabases property of the web application object contains a collection of the content databases in the web application. You can get a reference to a particular content database through this property if you know its index in the collection

 
Microsoft SharePoint Foundation 2010 and Microsoft SharePoint Server 2010 apply a default query threshold of 5,000 items. Any custom code that relies on query result sets that can exceed this maximum will not perform as expected. Queries on lists consisting of more than 5,000 items that include fields that are not indexed in their query conditions will also fail, because those queries must scan all rows in a list.
 

Do not use SPList.Items

SPList.Items selects all items from all subfolders, including all fields in the list. Use the following alternatives for each use case.
  • Adding an item
    Instead of calling SPList.Items.Add, use SPList.AddItem.
  • Retrieving all items in a list
    Instead of using SPList.Items, use SPList.GetItems(SPQuery query) . Apply filters, if appropriate, and specify only the fields you need to make the query more efficient. If the list contains more than 2,000 items, paginate the list in increments of no more than 2,000 items. The following code example shows how to paginate a large list.
  • Getting items by identifier
    Instead of using SPList.Items.GetItemById, use SPList.GetItemById(int id, string field1, params string[] fields). Specify the item identifier and the field that you want.
  • Do not enumerate entire SPList.Items collections or SPFolder.Files collections.
    The left column in Table 1 lists the methods and properties that if used will enumerate the entire SPList.Items collection, and cause poor performance and throttling for large lists. Instead, use the better-performing alternatives listed in the right column

  • Alternatives to enumerate SPList.Items

     
    Poor Performing Methods and Properties Better Performing Alternatives
    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.
    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.
    SPList.Items.ListItemCollectionPosition ContentIterator.ProcessListItems(SPList, ContentIterator.ItemProcessor, ContentIterator.ItemProcessorErrorCallout) (Microsoft SharePoint Server 2010 only)
    SPList.Items.ListItemCollectionPosition ContentIterator.ProcessListItems(SPList, ContentIterator.ItemProcessor, ContentIterator.ItemProcessorErrorCallout) (SharePoint Server 2010 only)
     
     
    Using the SPList.ItemCount property is the recommended way to retrieve the number of items in a list. As a side effect of tuning this property for performance, however, the property can occasionally return unexpected results. For example, if you require the exact number of items, you should use the poorer performing GetItems(SPQuery query), as shown in the preceding code example.
     
    Whenever possible, acquire a reference to a list by using the list's GUID or URL as a key.

    Alternatives to SPFolders.Files

    Poor Performing Methods and PropertiesBetter Performing Alternatives
    SPFolder.Files.Count SPFolder.ItemCount
    SPFolder.Files.GetEnumerator() ContentIterator.ProcessFilesInFolder(SPFolder, System.Boolean, ContentIterator.FileProcessor, ContentIterator.FileProcessorErrorCallout) (SharePoint Server 2010 only)
    SPFolder.Files[System.String] ContentIterator.GetFileInFolder(SPFolder, System.String)Alternatively, SPFolder.ParentWeb.GetFile(SPUrlUtility.CombineUrl(SPFolder.Url, System.String) (SharePoint Server 2010 only)
    SPFolder.Files[System.Int32] Do not use. Switch to ContentIterator.ProcessFilesInFolder and count items during iteration. (SharePoint Server 2010 only)
      
      
      
      
      

    No comments:

    Post a Comment