3

If I had a 1000 asp.net websites each with 30 DLL's in their /bin folders.

Therefore 30,000 DLL's.

Would the websites / web server / machine run faster if I registered one set of the DLL's into the Global Assembly Cache and each site used the DLL's in the GAC?

e.g. would the websites collectively use less memory?

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
Robs
  • 8,219
  • 6
  • 41
  • 57

3 Answers3

7

Even though assemblies are in the GAC they will still be loaded from there into memory separately to provide isolation. In other words, just because assemblies are in the GAC doesn't mean that those copies are shared across AppDomains. I believe that mscorlib (and possibly a few of the BCL assemblies) can be shared across AppDomains but any assemblies you or I write will not be.

This is a good thing however: consider the implications of the Cache type being shared across AppDomains.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
  • 2
    Assemblies can be loaded as domain neutral using LoaderOptimizationAttribute. I'm not exactly sure of the implications of doing this but I don't think it has anything to do with the sharing of state across AppDomains. – Josh Jun 03 '09 at 15:17
  • Right but that attribute is only valid on the entry point of an executable which means that it has no bearing on libraries. – Andrew Hare Jun 03 '09 at 15:42
  • Ahh good point. But surely ASP.NET has configured the CLR host to allow domain neutral loading? Otherwise any organization with a shared .DLL used in multiple projects would have to load a separate copy of that DLL into memory for each appdomain, would they not? Obviously each appdomain needs its own state, but would the code itself be loaded twice? – Josh Jun 03 '09 at 16:06
  • Yes, the code itself is loaded twice. Consider that any static members would be shared across AppDomains if the assemblies themselves were shared. Imagine if you had to be concerned about thread-safety (not to mention security) not only in your AppDomain but also in any AppDomain that may also load the same assembly! – Andrew Hare Jun 03 '09 at 16:27
  • Again, I think we're talking about two different things here. Sharing the assembly across appdomains does not mean the static state would be shared. I verified this in a small test app but I can't post it in comments obviously. – Josh Jun 03 '09 at 22:24
  • 2
    http://msdn.microsoft.com/en-us/library/43wc4hhs.aspx From MSDN - "Access to static data and methods is slower for domain-neutral assemblies because of the need to isolate assemblies. Each application domain that accesses the assembly must have a separate copy of the static data, to prevent references to objects in static fields from crossing domain boundaries. As a result, the runtime contains additional logic to direct a caller to the appropriate copy of the static data or method. This extra logic slows down the call." – Josh Jun 03 '09 at 22:25
  • Very cool!! Very nice find - I will enjoy reading up on this :) – Andrew Hare Jun 04 '09 at 00:38
  • @AndrewHare - are you SURE they aren't loaded into a shared space? The well known memory profiler Tess Ferrandez says differently - https://blogs.msdn.microsoft.com/tess/2006/04/12/asp-net-memory-you-use-the-same-dll-in-multiple-applications-is-it-really-necessary-to-load-it-multiple-times/ – Dave Black Oct 09 '18 at 22:18
2

Actually, the accepted answer from @AndrewHare is incorrect. Placing assemblies in the GAC DOES help reduce memory usage.

This is confirmed by Jeffrey Richter (from Wintellect who helped design the CLR with the .NET team) in his book CLR via C#:

Installing assemblies into the GAC offers several benefits. The GAC enables many applications to share assemblies, reducing physical memory usage on the whole....

It is also confirmed by Tess Ferrandez (Memory and Performance Guru from Microsoft's - https://blogs.msdn.microsoft.com/tess/2006/04/12/asp-net-memory-you-use-the-same-dll-in-multiple-applications-is-it-really-necessary-to-load-it-multiple-times).

Wherever possible strong name and install to the global assembly cache (GAC) any assemblies that are used by more than one ASP.NET application. This will reduce memory consumption.

I've also confirmed this myself by testing (WinDbg, Task Manager, and ProcExplorer) on a x64 WebAPI service as an example. You'd see that the Private Working Set is lower with the GAC'd app. In the case of NGen, you would again see the Private Working Set decreased. However, the Page Faults are also greatly reduced in the NGen'd app compared to the baseline (almost by half in my test). I saw no difference in Page Faults between the GAC'd app and non-GAC'd app.

Note that the best solution in some cases is to combine NGen and the GAC by installing NGen'd assemblies into the GAC. This optimizes memory usage between apps that share assemblies as well as providing a performance boost at application startup!

Dave Black
  • 7,305
  • 2
  • 52
  • 41
1

Actually this would be much faster, particular if they are NGEN'd as well. If you NGEN without putting them in the Global Assembly Cache then you will actually slow things down because the CLR will need to perform verification of the assembly to ensure that it matches the native image. The CLR skips this check for GAC'd assemblies and will simply load and use the native image.

There are also memory benefits to NGEN'd assemblies because they can share code pages.

You might also consider trying to optimize the base addresses of the DLL's because if they're all using the default, then Windows needs to rebase 30,000 times!

Here's a great article on performance benefits of NGEN.

http://msdn.microsoft.com/en-us/magazine/cc163610.aspx

Josh
  • 68,005
  • 14
  • 144
  • 156
  • Hmm... yes, running them through NGEN and possibly changing their base addresses might help - but just putting 1'000 DLLs into the GAC alone doesn't really make a difference, as far as I can tell. – marc_s Jun 03 '09 at 15:46
  • I think the performance improvement for GAC'd assemblies has to do with whether or not the assembly is strong named and strong name verification is turned on. But if nothing else, the CLR will probe for the assembly first in the GAC so there might be a slight improvement there. The big improvements come from NGEN and probably base address though I've never messed with base address. – Josh Jun 03 '09 at 16:08