Linux下.NET 6 Blazor App内存占用高

问题描述 投票:0回答:1

在 Linux 下运行时,我发现 dotnet 应用程序的内存使用率极高。内存也永远不会被释放。 当用户使用我的网络应用程序时,他们确实需要大量内存(1-2 GB 来运行报告),但当他们关闭选项卡时,资源就会被释放,我希望 dotnet 在某种程度上也能做到这一点。

我的 dotnet 应用程序的内存使用率接近 90-95%。

问题

  1. 我无法确定我的服务器是否处于内存使用高峰,或者 dotnet 是否占用内存,因为其他进程几乎没有内存压力。
  2. dotnet 内存转储很大,我认为它们不应该如此。 (分析时,下载量约为 5-6 GB,而使用过的对象约为 30-300 MB)

内存诊断

root@a9f25bad2d02:~/site/wwwroot# dotnet-counters monitor

[System.Runtime]
    % Time in GC since last GC (%)                                         0    
    Allocation Rate (B / 10 sec)                                     209,648    
    CPU Usage (%)                                                          0    
    Exception Count (Count / 10 sec)                                       0    
    GC Committed Bytes (MB)                                              105    
    GC Fragmentation (%)                                                  43.752
    GC Heap Size (MB)                                                     68    
    Gen 0 GC Count (Count / 10 sec)                                        0    
    Gen 0 Size (B)                                                19,577,728    
    Gen 1 GC Count (Count / 10 sec)                                        0    
    Gen 1 Size (B)                                                 1,608,856    
    Gen 2 GC Count (Count / 10 sec)                                        0    
    Gen 2 Size (B)                                                49,073,776    
    IL Bytes Jitted (B)                                            4,471,180    
    LOH Size (B)                                                  26,161,384    
    Monitor Lock Contention Count (Count / 10 sec)                         0    
    Number of Active Timers                                               15    
    Number of Assemblies Loaded                                        5,110    
    Number of Methods Jitted                                          64,067    
    POH (Pinned Object Heap) Size (B)                                706,440    
    ThreadPool Completed Work Item Count (Count / 10 sec)                 17    
    ThreadPool Queue Length                                                0    
    ThreadPool Thread Count                                                4    
    Time spent in JIT (ms / 10 sec)                                        0 
    Working Set (MB)                                                   5,773 
    
    
root@a9f25bad2d02:~/site/wwwroot# free -m
              total        used        free      shared  buff/cache   available
Mem:           7817        6858         121          19         837         740
Swap:          4095        2156        1939

root@a9f25bad2d02:~/site/wwwroot# top
Tasks:  11 total,   2 running,   8 sleeping,   1 stopped,   0 zombie
%Cpu(s):  1.5 us,  0.7 sy, 50.4 ni, 45.3 id,  2.2 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7817.4 total,     89.3 free,   7262.5 used,    465.6 buff/cache
MiB Swap:   4096.0 total,   1676.2 free,   2419.8 used.    341.3 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                                                      
                                                                                                                           
   74 root      30  10 9812340   5.4g  19812 t   0.0  70.7  21:22.97 dotnet                                                                                                                                       
 1908 root      30  10   13948    708    540 S   0.0   0.0   0:00.18 sshd                                                                                                                                         
 1910 root      30  10    5752   2040   1808 S   0.0   0.0   0:00.03 bash                                                                                                                                         
 2526 root      30  10    9780   3448   2972 R   0.0   0.0   0:00.00 top

正如您从

dotnet-counters monitor
中看到的,工作集约为 5.7 GB,而所有代以及大型和固定对象堆使用的字节总数仅约为 120 Mb。

这得到了对大小为 5 GB 的内存转储的分析的证实。

我已经做了什么

  1. 我已经在服务器和工作站 GC 之间切换 - 没有真正的区别。
  2. 我已经执行了 dotnet dump dotnet-dumpcollect --type Full 并在我的应用程序中搜索任何内存压力。
  3. 我已将 dotnet 计数器添加到我的应用程序中,以报告 Gen 0、1、2、LOH 和堆大小 - 所有值都会上升,但在用户离开站点后会再次下降。
  4. 我已将应用程序切换到 Windows,发现内存使用情况更加“正常”,并且一段时间后内存被释放。
  5. 我已使用
    dotnet-counters collect
    运行应用程序并模拟典型用户负载。我已在下面按时间绘制了
    GC Committed Bytes
    的结果。

背景

  • 应用程序作为 Blazor 服务器运行
  • 该应用程序根据 Linux 应用程序服务计划(准确地说是 P1v3)托管在 Azure 中
.net linux memory blazor
1个回答
0
投票

我的问题的根本原因与我的应用程序或事件 dotnet 无关 - 它与

glib malloc
有关。 malloc 中会动态调整内存分配块的大小,当应用程序使用大量内存时,会发生碎片并且内存会被勉强释放。可以在这里找到更好的文章:https://github.com/dotnet/runtime/issues/13301#issuecomment-535641506

这不仅影响我,dotnet 之外的其他程序也会受到影响。例如,

似乎有 2 个解决方法,要么修复

glibc.malloc.trim_threshold
的大小以阻止其动态,要么通过
glibc.malloc.arena_max
减少竞技场数量,因为默认数量为
8 * NumOfCores
。更多信息可以在这里找到:https://www.gnu.org/software/libc/manual/html_node/Memory-Allocation-Tunables.html

最终我选择设置环境变量

MALLOC_TRIM_THRESHOLD_=131072
这解决了我的问题。

在 Azure 中,您可以方便地使用配置来执行此操作, image

我可以确认是通过 bash 设置的,

kudu_ssh_user@ff3d088f400d:/$ env | grep MALLOC
APPSETTING_MALLOC_TRIM_THRESHOLD_=131072
MALLOC_TRIM_THRESHOLD_=131072

现在我可以在我的 Web 应用程序中看到内存被释放😅, image

© www.soinside.com 2019 - 2024. All rights reserved.