Skip to content

Huge memory usage regression in dotnet 7 on linux #79633

Closed

Description

@8

Description

A dotnet 7 application consumes much more memory on linux than a dotnet 6 or dotnet 5 application.

After upgrading our application to dotnet 7 we noticed a huge increase in memory consumption in linux, services that used 100 MB were now using twice that amount.

The base issue can be easily reproduced

  1. create new console application
  2. make sure it does not exit instantly, e.g. by using a while loop like:
while (true)
{
    Console.WriteLine("Hello, World!");
    Thread.Sleep(TimeSpan.FromSeconds(1));
}
  1. Verify that in your .csproj file you are targeting dotnet 7:
<TargetFramework>net7.0</TargetFramework>
  1. Switch to a Release configuration
  2. Start it under linux, e.g. by select WSL in the dropdown to launch it.
  3. Verify the used memory, e.g. by running ps aux in your wsl shell and taking a look at the RSS column:
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      5335  2.5  0.4 273549912 103944 pts/6 Sl+ 17:17   0:00 /usr/bin/dotnet /mnt/c/projects/sources/DotNet7Test/DotNet7Test/bin/Release/net7.0/DotNet7Test.dll
  1. Realize in horror that the console process consumes 100+ MB
  2. Stop the debugging
  3. Target dotnet 6 by updating your csproj file to:
<TargetFramework>net6.0</TargetFramework>
  1. Start it under linux, e.g. by select WSL in the dropdown to launch it.
  2. Verify the used memory, e.g. by running ps aux in your wsl shell and taking a look at the RSS column:
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      5383  1.0  0.0 2961956 25504 pts/6   Sl+  17:21   0:00 /usr/bin/dotnet /mnt/c/projects/sources/DotNet7Test/DotNet7Test/bin/Release/net6.0/DotNet7Test.dll
  1. Wonder why the same process consumes only 25MB using dotnet 6.

Configuration

Dotnet 7 on Linux x64, see above

Regression?

Yes, this is a major performance regression in dotnet 7 compared to dotnet 5 or 6.

Other information

Notes:
The memory consumption on windows on dotnet 7 is reasonable - it's just a little higher, but not by crazy amounts.
The difference between dotnet 5 and dotnet 6 on linux is negliable.

Take care,
Martin

Activity

  1. buyaa-n commented on Dec 14, 2022

    @buyaa-n
    Contributor

    CC @dotnet/linux-team

  2. transferred this issue fromdotnet/coreon Dec 14, 2022
  3. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Dec 14, 2022
  4. mangod9 commented on Dec 14, 2022

    @mangod9
    Member

    Hi @8,
    yeah this is something we are aware of for unconstrained memory environments. We are working on resolving it in a upcoming servicing release, a workaround is to set DOTNET_GCHeapHardLimit to something reasonable (based on expected app usage or physical memory). Its an absolute increase of 64mb hence its exaggerated for hello world style apps.

    It also shouldnt be an issue for memory constrainted containers

  5. removed
    untriagedNew issue has not been triaged by the area owner
    on Dec 14, 2022
  6. added this to the 8.0.0 milestone on Dec 14, 2022
  7. enclave-alistair commented on Dec 14, 2022

    @enclave-alistair

    Just to add a note that we deploy a single-file self-contained linux application to end-users machines, so cannot realistically set DOTNET_GCHeapHardLimit, and an unrequired increase of 64mb will no doubt raise significant complaints.

  8. mangod9 commented on Dec 14, 2022

    @mangod9
    Member

    Ok, will update this issue once the fix is merged. Thanks

  9. EricStG commented on Dec 16, 2022

    @EricStG

    We have a similar issue.

    We upgraded 2 services to .NET 7 / ASPNET Code 7, both at least doubled memory usage (one went from a max of 15% memory usage to 80%)
    Both are running in container with a 512mb limit (in Cloud Run if that matters)

  10. mangod9 commented on Dec 16, 2022

    @mangod9
    Member

    this issue shouldn't be affecting constrained memory containers (in fact, our TechEmpower measurements show a reduction in working set). Would you be able to share more details and/or a dump to investigate the increase further?

  11. EricStG commented on Dec 16, 2022

    @EricStG

    @mangod9 Absolutely, let me know what you need

  12. 6 remaining items

  13. ilia-cy commented on Feb 5, 2023

    @ilia-cy

    Hello @mangod9, are there any updates regarding the fix?

  14. mangod9 commented on Feb 6, 2023

    @mangod9
    Member

    Hi @ilia-cy, this should be fixed as part of #80173, so should be included in 7.0.3 which should be released next week. Thx.

  15. idan-cyber commented on Feb 14, 2023

    @idan-cyber

    @mangod9 - Any updates on version 7.0.3? Thanks!

  16. richlander commented on Feb 14, 2023

    @richlander
    Member

    It should ship one month from today, 3/14.

    Would you test with a pre-release build to validate?

    I never realized that Pi day is one month after Valentines.

  17. 8 commented on Feb 15, 2023

    @8
    Author

    Hi Rich,

    super!
    yes, I would - if you have a download link that would be great!

    Take care,
    Martin

  18. idan-cyber commented on Mar 12, 2023

    @idan-cyber
  19. declard commented on Mar 14, 2023

    @declard

    The issue doesn't seem to be fixed in either 7.0.3 or 7.0.4

    sh-4.2$ uname -a
    Linux ip-********.aws 4.14.305-227.531.amzn2.x86_64 #1 SMP Tue Feb 14 09:55:28 UTC 2023x86_64 x86_64 x86_64 GNU/Linux
    sh-4.2$ dotnet --list-runtimes
    Microsoft.NETCore.App 6.0.1 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 6.0.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 6.0.4 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 6.0.8 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 6.0.9 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 6.0.10 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 6.0.11 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 6.0.13 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 6.0.14 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 6.0.15 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 7.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 7.0.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 7.0.3 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    Microsoft.NETCore.App 7.0.4 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    

    The following is a screenshot of htop with the dotnet6 version of our app running on a machine:
    image

    Compare it to the screenshot of htop with the dotnet7 version of the same app running on the same machine and the same data set:
    image

    The executable is a generic host console app, it runs

    GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
    GC.Collect();

    in both versions after finishing loading the data.

    Heap analysis didn't show any object size/count difference.

    Such threefold increase in memory is unacceptable when an app consumes a hundred gigs in prod environments.

  20. mangod9 commented on Mar 15, 2023

    @mangod9
    Member

    Hi @declard, your issue seems to be different than the original posted here. That was regarding a vanilla app consuming more memory. I suggest you create a new issue and provide some traces to compare 6 with 7. Would also be good to check if setting DOTNET_GCName=libclrgc.so has any effect on your scenario. Thx!

  21. declard commented on Mar 15, 2023

    @declard

    @mangod9 thank you for the advice, it actually worked! The memory dropped back to dotnet6 size, so I guess the issue is in the new GC indeed.

    I'll dig further to file a new issue when time allows

  22. 8 commented on Mar 15, 2023

    @8
    Author

    After the update I get:

    dotnet --version
    7.0.202

    After rebuilding and running the executable I can see the memory usage dropped from 100MB to 30MB:

    root@N900D90FB:~# ps aux
    USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root       157  0.3  0.1 273476000 30460 pts/1 Sl+  12:41   0:00 /usr/bin/dotnet /mnt/c/projects/sources/DotNet7Test/DotNet7Test/bin/Release/net7.0/DotNet7Test.dll

    Thank you for the fix!

    We can now complete the upgrade of our services to dotnet 7, thank you!

    Take care,
    Martin

  23. mangod9 commented on Mar 15, 2023

    @mangod9
    Member

    Thanks for validating @8 . @declard, yeah please open a separate issue so we could investigate your specific scenario.

  24. mihaimyh commented on Apr 6, 2023

    @mihaimyh

    Hi @declard, your issue seems to be different than the original posted here. That was regarding a vanilla app consuming more memory. I suggest you create a new issue and provide some traces to compare 6 with 7. Would also be good to check if setting DOTNET_GCName=libclrgc.so has any effect on your scenario. Thx!

    Wow, this actually worked also for my app. The memory dropped back to .NET 6 levels after settings this variable. What does actually do?

  25. mangod9 commented on Apr 7, 2023

    @mangod9
    Member

    @mihaimyh , the config moves the GC mechanism back to .NET 6. I would suggest creating a separate issue since your issue would most likely be different that the original one here. If you need notice working set differences with this setting would be good to collect some traces so we could investigate further. Thx!

  26. ghost locked as resolved and limited conversation to collaborators on May 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions