dotnet / wcf

This repo contains the client-oriented WCF libraries that enable applications built on .NET Core to communicate with WCF services.
MIT License
1.71k stars 559 forks source link

High unmanaged memory usage in ASPNet core project #4722

Closed pmiddleton closed 3 years ago

pmiddleton commented 3 years ago

I have a 3rd party wsdl that I am currently using in a project. This wsdl is rather large, svcutil produces about 1.5 million lines of code between two services.

When the channel for the generated service is created, in my asp.net core application, the unmanaged memory usage jumps by about 550 mb. I have used dotMemory to confirm it is unmanaged memory and not in the managed heaps.

What is strange is that if I take the same wcf code and use it in a console application I am seeing different results. In that case unmanaged memory does not spike, but managed memory shoots up to about 150mb.

I have attached two watered down test applications to show this behavior. All they do is create both channels and exit. The console app uses 200 mb of which 150 imb is managed. The aspnet core app uses 600mb of which 550mb is unmanaged. The offending wsdl is include in the Service References directory of each project.

I thought it might have something to do with xml serialization so I have tried pre generating a xml serializer assembly, but that does not affect the results. I am seeing this same behavior on both my windows dev machine and my linux docker image in production.

I fully expect there to be a large amount of memory used because of the size of these wsdl files, but I just can't understand why I am seeing such large differences between aspnet core and a console app. What is the aspnet core runtime doing that would cause this large difference in unmanaged memory usage?

code.zip

mconnew commented 3 years ago

The last time I saw something like this, it was because someone was creating new IServiceProvider scopes and then not disposing of the scope when done with it. Your best bet would be to use VS's memory analysis tools to see what's using all the space and how it's rooted.

mconnew commented 3 years ago

I downloaded your repro and checked the heap allocations and they are pretty much identical. The different comes down to asp.net core projects use server GC by default, and regular SDK projects use workstation GC. Add the following to your Web project csproj file and you will see the memory allocation is about the same:

  <PropertyGroup>
    <ServerGarbageCollection>false</ServerGarbageCollection>
  </PropertyGroup>

Here's some documentation about the differences. The main one which affects size is server GC allocates a heap for every CPU core, whereas workstation GC has a single heap allocation. The extra size you are seeing is a result of there being more heaps due to more than 1 CPU core.