asp.net.netiisw3wp

Sharing assemblies between w3wp processes for reduce memory usage


Problem We are publishing a lot of microservices on one machine, i.e.: 30 instances and every one use 150 – 300 mb. A lot of microservices use the same libraries, but load it independent.

Question Can the CLR load assembly once and share it with other domains for reduce memory usage?

Investigation and experiment When I investigated this problem through ProcessExplorer, I've seen there are 2 Application domain for every w3wp process. One of them is used to load assemblies from GAC and another to load assemblies from the application folder.

When I put common assemblies in GAC. It increase Shareable, Shared WS and reduce Private WS for all processes. But Working set without changes.

enter image description here enter image description here


Solution

  • Open VMMap and have a look at memory structure of w3wp process.

    vmmap screen

    The simplest way to reduce memory usage: it's combine multiple sites into one application domain. Startup time for every single site will be reduce.

    If there are a lot of assemblies with strong name you can put them in GAC. It's make their domain neutral assembly for w3wp process. Such assemblies are domain neutral if and only if it is in GAC, and all the assemblies in its transitive binding closure are all in GAC. (see also blogs.msdn)

    Domain neutral assembly pros and cons:

    Some words about strong named assemblies and GAC.

    If your assemblies have strong names, make sure to place them in the global assembly cache (GAC).

    Otherwise, loading the assembly requires touching almost every page to verify its digital signature.

    Verification of strong names when the assembly is not placed in the GAC will also diminish any performance gains from NGen.
    (see also: Pro .NET Performance: Optimize Your C# Applications. Page 289)