Addins slow again...

Feb 19, 2008 at 10:24 PM
I previously put a post regarding my loading of addins being extremely slow... I thought I solved the problem by placing the LoaderOptimization on the Main method and I did see my addins load much faster... Last week, I noticed they are running slow again... Again, it is the Activate method causing the slowness.... I have looked through the changes that have taken place in the project since the addins were loading fast, but have not come up with anything... I have disabled VShost process too. At some stage last week, we had to add some web references to the project, but they are not used by the addins..... I dont know if that has anything to do with it. When my addins are running in isolated domains, I created an empty addin, with one button on it, I measured the time it took for the addin to activate (by writing to a text file), the results were:

Before activate: 20/02/2008 10:20:16 AM
After activate: 20/02/2008 10:20:23 AM

The addin took 7 seconds to call this line:
this.wpfAddIn = addInToken.Activate<WPFAddIn>(AddInSecurityLevel.FullTrust); //empty addin with one button

Again, LoaderOptimization is multidomainhost....

Any ideas are appreciated.

Rita


Feb 20, 2008 at 9:06 PM
Are you sure you have the LoaderOptimization attribute with MultiDomainHost on the main method that is actually being used by your application? I know that by default the WPF project system does a very good job of hiding the main they generate from you. If what you did was find their generated main method and apply the attribute to it they may have regenerated the file and overwritten that change. If what you did was add your own application class with its own main method then its possible that a setting in the project got flipped somewhere to go back to the generated one.

Something definitly happened to turn off assembly sharing between your domains, the above are my best guess as to how that could have occured, but it's possible something else changed.

--Jesse
Feb 28, 2008 at 6:11 PM
Jesse,

Can you give us an idea of what to expect from add-in activation. Perhaps you've done this and I don't see it.

With the LoaderOptimization and nothing in the GAC with a an IContract, it's taking over half a second to load my addin. That seems long, and I'm wondering if IContract hurts me here. This isn't the 6 seconds horror, but I'm hoping its not just the expected range.

Also, can your remind me the relative perf of passing a ByRef string or using an IContract return value. The returned string will be less than 40 characters.

Also, the LoaderOptimization seems a bad long term solution, at least without fixes to other parts of .NET. If I want to originate an add-in and ask people to use it in their applications, they have to muck with their WPF code and they cannot use (as far as I can tell) the application framework in VB. It woud seem at the very least, a version of LoaderOptimization should be an assembly attribute so it can be used more easily than on the startup method which in many cases is not accessible. If I am pushing out an addin, that's a high bar for application modification.
Feb 29, 2008 at 6:48 PM
Start-up perf
I'm working on another post describing start-up perf but I haven't posted the complete numbers/article yet. If you look at the existing perf sample the discovery time (AddInStore.Update and AddInStore.FindAddIns) clocks in (on my machine) at about 0.08 seconds while AddInToken.Activate(AddInSecurityLevel) clocks in at about 0.16 seconds. You would find that the cost of spinning up an AppDomain and loading a small add-in assembly in it would cost just about the same as the call to Activate and isn't really impacted by System.AddIn.

If you're hitting about half a second my guess is you're using WPF as that matches fairly well with the cost of activating a WPF based add-in in a new domain with LoaderOptimization turned on. The cost you're paying there is the additional cost of initializing WPF in a new AppDomain. This cost is much lower if you are using LoaderOptimization.MultiDomainHost but is still significant: ~0.4 second for WPF and ~0.16 for the AppDomain versus ~6 seconds without LoaderOptimization.

We're working to increase the start-up performance of WPF across the board in future releases (starting with 3.5 SP1) and those gains will be felt here as well.

ByRef
The size of the string doesn't impact the performance of passing the boundary but until now I didn't actually do a test to compare ByRef with standard return value. I just went through and tried this out and the results were interesting to me. Using C#, defining a method on your contract that returns a string using "ref" you stay on the fast path and have the same performance characteristics as if you simply returned the string (~80k calls per second). If you return the string using "out" then you actually fall off the fast path and end up going across about 4x slower (~20k calls per second). If the fast path is not enabled at all, then all three operations cost the same.

I'm going to look into this a bit more and see if we can figure out what is causing the difference in cost here. This may be something we can fix in a future version of the runtime.

Ease of LoaderOptimization
We're in definite agreement here. We're looking at ways to make this much easier down the road. It isn't a done-deal yet, but we're leaning strongly towards enabling LoaderOptimization.MultiDomainHost as the default for new applications.
Mar 5, 2008 at 4:16 AM
Jesse,
I have my Application class as the startup point and my Main method is in it with LoaderOptimizer set to MultiDomainHost. I have looked to find where this may be overwritten by WPF, but cannot find anywhere. I have also deselected VSHost just in case, and also compared the csproj files in Source Safe to see what project settings could have changed; but found nothing. This has happened to me several times now, the Addins load at a reasonably well speed, then after a few code changes they go back to being slow again. I think you are right about losing a setting somewhere. I have been deleting all dlls and rebuilding; yet to no avail.

Any particular settings you recommend i look out for?

Thanks

Mar 5, 2008 at 5:58 PM
Try going to the project settings for you exe.
Click on the application tab and see what you have listed under "Startup Object"
See if you have "Not set", the class containing your main method, or some WPF project created class.

I think "Not set" is the default value and I can believe that if you have that and WPF decides to regenerate their basic "Application" class then it will fall back on that. Hopefully specifically setting it to the class you've defined will remove any ambiguity here and fix this problem for you.

If that doesn't do it let me know and I'll dig a little further.

--Jesse
Mar 6, 2008 at 12:55 AM
Jesse,
I am afraid I have tried your suggestion and still face the same problem. My startup object is the class containing my Main (with the LoaderOptimizer set). Can WPF not be referring to this setting at all? How can i know?

Rita
Mar 26, 2008 at 10:16 PM
Edited Mar 27, 2008 at 6:54 AM
Jesse,

I'm having some trouble with this as well. Mine is slightly more complicated as I'm trying to create a tray icon WPF application that starts without a main window. I have successfully created a windows forms tray icon application as a GUI on top of my AddIns and want to create a WPF version to show that no changes need to be done to the AddIns.

For the windows forms version you create an ApplicationContext derived class and in your Main() call Application.Run(AppContext) passing your Application Context that then shows Forms in response to context menu items on the tray icon.

In the WPF version, I have removed the App.xaml and App.xaml.cs files and created a App.cs that derives from System.Windows.Application and added a Main(). I added the NotifyIcon handling code and that seems to work but during the token activation call I get the following Exception.

System.ArgumentNullException occurred
Message="Value cannot be null.\r\nParameter name: con"
Source="mscorlib"
ParamName="con"
StackTrace:
at System.Reflection.Emit.DynamicILGenerator.Emit(OpCode opcode, ConstructorInfo con)
at System.AddIn.Hosting.AddInActivator.AssertAndCreateInvoker(Type targetType, Type argType, Type[] methodArgs, ConstructorInfo havCtor)
at System.AddIn.Hosting.AddInActivator.CreateConsInvoker(Type targetType, Type argType)
at System.AddIn.Hosting.AddInActivator.AdaptToHostT(AddInToken pipeline, IContract addInContract)
at System.AddIn.Hosting.AddInActivator.ActivateInAppDomainT(AddInToken pipeline, AppDomain domain, AddInControllerImpl controller, Boolean weOwn)
at System.AddIn.Hosting.AddInActivator.ActivateT(AddInToken token, PermissionSet permissionSet, String appDomainName)
at System.AddIn.Hosting.AddInActivator.ActivateT(AddInToken token, AddInSecurityLevel level, String appDomainName)
at System.AddIn.Hosting.AddInToken.ActivateT(AddInSecurityLevel trustLevel, String appDomainName)
at HostAddInManager.AddInManager.ActiveAddIn(AddInToken addinToken) in C:\Dev.Net\2008\Host\Src\HostAddinManager\AddInManager.cs:line 49
InnerException:

This happens in the AddInManager class that is used by the Windows Forms application successfully.

Any help would be appreciated. I'm fairly new to WPF and stumbling my way through so I'm not sure if my non-standard way of starting up is to blame or ???

Thanks,
Ed

Edit: Kentcb got this error also and fixed it by removing a reference to his contracts DLL but that did not fix it for me.
http://www.codeplex.com/clraddins/Thread/View.aspx?ThreadId=24568

Edit2: I had to also delete the contracts DLL in the output folder as I had not set the Copy Local to False.
Apr 14, 2013 at 2:41 AM
Hi Jesse,

I have created a WPF addin application , which is returned as a FrameworkElement, which is being added as a control in MainForm(HOST) application. The MainForm is being loaded in a external class library under Application.Run(new MainForm), after going through several articles including at http://blogs.msdn.com/b/clraddins/archive/2008/02/22/add-in-performance-what-can-you-expect-as-you-cross-an-isolation-boundary-and-how-to-make-it-better-jesse-kaplan.aspx, which is very informative. I have applied LoaderOptimization.MultiDomainHost on top of the method which has Application.Run(new MainForm) and even installed Contracts in GAC, but my application is facing very critical performance issue by taking nearly 25secs to load my addin. I have to improve the performance before UAT. Can you please let me know, how to improve the performance and is it something i have missed. Remember my Contract is not a value type but of IContract type, which is MarshallByRef,.


Thanks
Prash