Unity assembly taking 30 seconds to load

Aug 12, 2010 at 2:51 AM
Edited Aug 12, 2010 at 8:19 PM
I have written a windows service that uses Unity 2.0. My company has two domains, one for employees in the US and one for the outsourcers. The outsourcers are running on Citrix boxes, Windows 2003 Server boxes to be specific.

So on to my problem, on our US domain, my service runs fine, but on the Citrix boxes it fails to start. I traced this down to the service taking too long to load, I traced the load time to the Microsoft.Practices.Unity assembly. To verify it wasn't something weird I was doing, I wrote a test app to verify this.

    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            Assembly assembly = Assembly.LoadFrom(args[0]);
            stopwatch.Stop();

            Console.WriteLine("Took {0} ms to load assembly: {1}", stopwatch.ElapsedMilliseconds, assembly.GetName().Name);
            Console.WriteLine("Press ENTER to exit...");
            Console.ReadLine();
        }
    }

When I run this on one of our US boxes, it takes 193 ms to load, but when I run this on a Citrix box it takes 30k+ ms to run. I have tried Unity versions 2.0 and 2.0 beta 2. I haven't tried version 1.0, I think I would like to use the features in 2.0, including Static Factory, etc.

Any ideas? I don't want to switch to a different IoC library, I have used Unity in the past for personal projects and am most familiar with it.

-Jonathan

Aug 12, 2010 at 6:09 AM

Does the Citrix machine have outgoing internet access? My first guess is that it's hanging up waiting to verify the digital signature on the binary. A quick way to check is to add this to your app.config file:

    <runtime>
        <bypassTrustedAppStrongNames enabled="false"/>
    </runtime>

Try that and see if it helps. Remember, this needs to go into the app.config of your test exe.

Aug 12, 2010 at 6:00 PM
I have tried the above suggestion but it didn't have any effect. BTW, I notice my post was converted to a wall of text but I don't see a tutorial links for formatting, any links you are aware of to teach me how to format my posts?
Aug 12, 2010 at 7:46 PM

Codeplex has a bug - the post editor doesn't render in Firefox, and you have to type in HTML manually. It'll be fixed in the next Codeplex release (they usually release every 2 weeks).

Weird on the timing. We're certainly not doing anything special on loading. At this point I'd probably pull out a profiler and see where the time is going. If you can get that information to me I may be able to track things down better.

 

Aug 12, 2010 at 8:34 PM
So I downloaded dotTrace and ran it on my test application, here are the results:

100.00 % Thread #1472200 - 37247 ms - 0 calls
  99.44 % Main - 37037 ms - 1 call - AssemblyLoadTest.Program.Main(String [])
    80.99 % LoadFrom - 30167 ms - 1 call - System.Reflection.Assembly.LoadFrom(String)
    18.05 % ReadLine - 6721 ms - 1 call - System.Console.ReadLine()
    0.19 % WriteLine - 69 ms - 1 call - System.Console.WriteLine(String, Object, Object)
    0.15 % GetName - 57 ms - 1 call - System.Reflection.Assembly.GetName()
    0.01 % Stopwatch..cctor - 3 ms - 1 call - System.Diagnostics.Stopwatch..cctor()
    0.00 % get_ElapsedMilliseconds - 0 ms - 1 call - System.Diagnostics.Stopwatch.get_ElapsedMilliseconds()
    0.00 % WriteLine - 0 ms - 1 call - System.Console.WriteLine(String)
    0.00 % Start - 0 ms - 1 call - System.Diagnostics.Stopwatch.Start()
    0.00 % Stopwatch..ctor - 0 ms - 1 call - System.Diagnostics.Stopwatch..ctor()
    0.00 % Stop - 0 ms - 1 call - System.Diagnostics.Stopwatch.Stop()
    0.00 % get_Name - 0 ms - 1 call - System.Reflection.AssemblyName.get_Name()
  0.38 % IsAssemblyUnderAppBase - 142 ms - 1 call - System.Reflection.Assembly.IsAssemblyUnderAppBase()
  0.11 % SetupDomain - 39 ms - 1 call - System.AppDomain.SetupDomain(Boolean, String, String)
  0.06 % SetDefaultDomainManager - 22 ms - 1 call - System.AppDomain.SetDefaultDomainManager(String, String [], String [])
  0.02 % RemotingServices..cctor - 7 ms - 1 call - System.Runtime.Remoting.RemotingServices..cctor()

Not a lot of useful information, it doesn't show it calling into the Unity assembly.

I have done further testing and have found this happens on non-Citrix boxes on this second domain. So to summarize:

Assembly loads fine on all tested boxes on first domain.

Assembly loads take 30+ seconds on all boxes on the second domain.

So my assumption is there is a group policy that is being set on the second domain that is causing issues. I know this second domain is extremely locked down.

I think for the time being, I am going to have to replace Unity with StructureMap(ugh) until I have time to circle back around and troubleshoot this more, I am supposed to be finish this testing by tomorrow.

-Jonathan

Aug 12, 2010 at 8:49 PM
So as a test I decided to download the Unity source code and compile it myself, it now loads in under 7 ms, after I signed the assembly it jumped to 53 ms, but not the 30k ms load of the pre-built binaries, so it appears the problem is with the pre-built binaries. Do you know what could possibly explain this?
Aug 13, 2010 at 2:11 AM

The only difference between the pre-built binaries and the one you built is the key you used to sign it with. Oh, and the pre-built ones are also authenticode signed - did you do that too, or just do a strong name?

Aug 13, 2010 at 2:37 AM

I didn't authenticode sign it, I am not really sure what that is.  I read a brief page on that and it seems to be using a certificate issued by a certificate authority, could it be attempting to verify this certificate?  I am pretty sure most outbound traffic on this domain is locked down, even internal traffic is pretty locked down, so if it is trying to hit the outside world to verify the certificate authority, that may be my issue.

Sep 15, 2010 at 1:03 PM
Edited Sep 15, 2010 at 2:27 PM

Authenticode signature takes time to validate. To disable it, you need to place generatePublisherEvidence enabled=false in aspnet.config (in case of IIS hosted application)/ machine.config file.

I had the similar problem for my web application and adding the generatePublisherEvidence in aspnet.config (under c:\windows\microsoft.net\Framework\v2.0.50727) solved the problem

For more info: 

http://support.microsoft.com/kb/936707