With the SP1 work winding down, I thought that I’d take a moment and discuss three new performance improvements that are going into VSTO for SP1. We have listened to your feedback and understand that startup time is a major issue, and so we have focused on attempts to make the VSTO runtime load faster.
In this article, I will be delving into these features and how you can take advantage of them. The most important feature is Fast Path loading, which is a loading path for the runtime which is as fast and as lean as possible. In addition, we updated the form region and ribbon discovery process so reflection is not required in most cases. Plus, I will also share a few of the numbers we gathered during this effort so that you can get a before and after picture.
VSTO Fast Path
The Fast Path is a new way to load and launch VSTO addins that is much faster than the current launch path. However, it achieves this speed by bypassing a few of the steps that would normally happen during addin launch. The following conditions must be met in order to use the fast path:
- The addin (or document) manifest must be installed under %ProgramFiles% or %ProgramW6432%.
- The addin must be registered as |vstolocal in the registry.
When the fast path is in use, the following steps will be skipped:
- Schema validation on the manifests
- Any automatic update checking
- Security checks – the digital signatures of the manifests will not be validated.
Notice that the requirement that the add-in is deployed into the secure location on the user machine allows us to relax the security verifications done at runtime without compromising the security of the machine. Relaxing these expensive checks is what contributed the most to the improvements in startup time.
In order to take advantage of Fast Path loading, an addin has to be deployed via an MSI. As a consequence, these addins also will not be able to automatically check for updates.
Ribbon Aware Manifests
As mentioned in a previous blog post, VSTO reflects over the addin assembly in order to find Ribbon extensions. On particularly large assemblies, this can be quite time consuming. While there have been manual workarounds for this behavior in the past, we are now including Ribbon extension types directly into the VSTO manifest. If there are no Ribbon extensions, then an empty list is placed in the manifest, which will tell the VSTO runtime that reflection is not necessary.
In order to take advantage of this improvement, the addin must be built (or rebuilt) with Visual Studio 10.0 SP1, and the addin must be loaded with the SP1 version of the VSTO Runtime. The addin must also be targeting .Net 4.0. If you attempt to load an SP1 addin with a RTM runtime, or if you load an RTM addin with the SP1 runtime, all of the ribbon objects will still be discovered and loaded; the runtime will just have to use reflection to find them.
Of course, if your code already overrides CreateRibbonObjects or CreateRibbonExtensibilityObject as mentioned in the above blog entry, then this optimization does not apply to you. The reason why this was implemented is because many people are not aware of this optimization, and we want to ensure that we are as performant as possible by default with as little manual optimization as possible.
To better visualize the new ribbon xml, here are two examples of its intended use:
<vstov4:appAddIn application="Excel" loadBehavior="3" keyName="ExcelAddIn14"> <vstov4:friendlyName>ExcelAddIn14</vstov4:friendlyName> <vstov4:description>ExcelAddIn14</vstov4:description> <vstov4.1:ribbonTypes xmlns:vstov4.1="urn:schemas-microsoft-com:vsto.v4.1"> <vstov4.1:ribbonType name="ExcelAddIn14.Ribbon1, ExcelAddIn14, Version=18.104.22.168, Culture=neutral, PublicKeyToken=null" /> </vstov4.1:ribbonTypes> </vstov4:appAddIn>
That addin had one ribbon type, and the class is called ExcelAddIn14.Ribbon1, and it is part of the ExcelAddIn14.dll assembly.
Here is one with no ribbons:
<vstov4:appAddIn application="Excel" loadBehavior="3" keyName="ExcelAddIn15"> <vstov4:friendlyName>ExcelAddIn15</vstov4:friendlyName> <vstov4:description>ExcelAddIn15</vstov4:description> <vstov4.1:ribbonTypes xmlns:vstov4.1="urn:schemas-microsoft-com:vsto.v4.1" /> </vstov4:appAddIn>
The empty ribbonTypes list serves to tell the SP1 runtime that doing the reflection is unnecessary. This will save a lot of time during VSTO startup.
VSTO Form Region discovery
When loading an Outlook addin that has Form Regions, the VSTO Runtime uses reflection to discover Form Region factories and match them up with Form Regions registered with the addin. This had the potential to inflict a serious performance hit, especially if the addin assembly contained a lot of different types.
To eliminate this performance hit, the name of the factory is now being included in the addin manifest. Now when Outlook requests the factory from the addin, the addin knows immediately which class to instantiate and doesn’t need to reflect over every type in the assembly to find the appropriate class. If you look in the new SP1 manifest, you can see the new information:
<vstov4:formRegion name="Outlook_OFR_MSI.EmptyFormRegion" vstov4.1:class="Outlook_OFR_MSI.EmptyFormRegion+EmptyFormRegionFactory" xmlns:vstov4.1="urn:schemas-microsoft-com:vsto.v4.1">
Like the Ribbon aware manifest above, the SP1 runtime is capable of loading an addin with Form Regions that was built with the RTM version of VS, and the RTM runtime can load an SP1 addin. You just won’t be able to take advantage of this improvement.
Below are some of the numbers that we tracked on startup time during this effort. These numbers were collected on a machine in a ‘cold’ state (everything in memory flushed out to disk, superfetch disabled) in order to give us the most consistent results during our work. In addition, there are no other applications running at the time that Outlook was launched, and all addins except for the one that we were testing was disabled.
There four startup times of interest are as follows:
- Outlook application baseline – an empty mail account, no addins loaded
- Outlook simple addin – a simple .Net 4.0 addin. In SP1, it would take advantage of the fastpath as well as the ribbon improvements (since the VSTO runtime was no longer looking for Ribbons)
- Outlook Ribbon addin – this is similar to the above one, only now we see the time it takes to instantiate a simple Ribbon extension.
- Outlook WPF Form Region – this is the simple addin plus the time to load (but not show) a Form Region with a WPF control on it. This takes advantage of all of the improvements listed in this article.
|Outlook + VSTO RTM||Outlook + VSTO SP1||Improvement|
|Scenario||Time||%||Time||%||% of App baseline|
|Outlook application baseline||3762||100.00%||3762||100.00%||N/A|
|Outlook simple addin||10215||271.53%||7952||211.38%||60%|
|Outlook Ribbon addin||10973||291.68%||8424||223.92%||68%|
|Outlook WPF Form Region||12231||325.12%||8192||217.76%||107%|
As you can see, there are many performance improvements to the VSTO Runtime coming in Visual Studio 2010 SP1. Not only that, but many tweaks that used to require extra work (such as working around Ribbon reflection) are now available out of the box with no interaction on the user’s part. This will help you deliver VSTO addins that are faster to your end-users.