VSTO Performance: Ribbon Reflection (Stephen Peters)

  • Comments 4

It is very easy to customize the Ribbon in your VSTO extension.  All you need to do is to add a Ribbon (Visual Designer) to your solution, and it will appear when your solution is run without needing to do any more work.  Behind the scenes, the VSTO runtime reflects through your entire addin assembly looking for Ribbon extensions to instantiate.  This reflection can cause a significant performance hit, especially on larger solutions.

During an addin’s startup, the VSTO Runtime needs to discover and instantiate any user-created Ribbon extensions.  The runtime does this by calling CreateRibbonExtensibilityObject, which is implemented by VSTO in the addin base class.  It will then call CreateRibbonObjects, another method on the addin base class.  This implementation of CreateRibbonObjects will reflect over every type in the addin assembly looking for classes that implement Microsoft.Office.Tools.Ribbon.IRibbonExtension (4.0) or Microsoft.Office.Tools.Ribbon.OfficeRibbon (3.5), instantiating each one, and then returns these in an array.

The performance hit comes from the reflection that happens in CreateRibbonObjects.  For simple VSTO addins, this isn’t very significant.  But if you link in a large library, then the reflector will pull in any types referenced in your assembly, and any types that those types reference, and so forth.  This can result in having to spend a lot of time reading these types from disk, and it is completely unavoidable. 

In order to avoid this, we can override either of these two methods so that the default implementation of CreateRibbonObjects is not called.  If the addin has no ribbons, then it’s best to override CreateRibbonExtensibilityObject in order to execute as little code as possible.

protected override Office.IRibbonExtensibility 
    CreateRibbonExtensibilityObject()
{
    return null;
}

If your addin includes a Ribbon, then it’s better to override CreateRibbonObjects.  Note that if you are creating an addin for .Net 3.5, you’ll need to return OfficeRibbon[] instead of IRibbonExtension[].

using Microsoft.Office.Tools.Ribbon;
protected override IRibbonExtension[] CreateRibbonObjects()
{
    return new IRibbonExtension[] { new Ribbon1(), new Ribbon2() };
}

In our perf lab, we ran some benchmarks using the method described in this blog entry to generate the numbers.  Of interest were two tests involving an Outlook addin that had a Form Region with a single WPF control, before and after removing the Ribbon reflection.  The results were that removing reflection saved over a second off of the cold startup time.  So if you have larger VSTO solutions you may want to try to this technique to speed up performance.

Leave a Comment
  • Please add 2 and 4 and type the answer here:
  • Post
  • Can you clarify this?  Ribbon1 is not of type IRibbonExtension, it's an IRibbonExtensibility, so the code you show for CreateRibbonObjects doesn't actually complie.

  • The code snippet got cut off when I posted it, so I've cleaned it up.

    It looks like you added a "Ribbon (XML)" instead of a "Ribbon (Visual Designer)".  In this case, copying the CreateRibonExtensibilityObject snippet from the comments in Ribbon1.cs is enough to stop the reflection from happening.

  • What are the implications of overriding, as you suggest? (IOW, how will it affect the result the user gets?)

    If there is no effect - if all remains the same for the user (except for the loading time) why not change how VSTO is doing this, rather than the developer needing to make this change?

  • As long as the developer includes all of thier ribbons in the array that CreateRibbonObjects returns, the user shouldn't notice anything different.

    We are currently investigating having VSTO do this.  This was turned up during a performance investigation, and I thought it would be best to pass the manual workaround along.

Page 1 of 1 (4 items)

VSTO Performance: Ribbon Reflection (Stephen Peters)