【问题标题】:Dotnet Core Will Not Use SwapDotnet Core 不会使用 Swap
【发布时间】:2021-04-25 08:04:25
【问题描述】:

我编写了一个简单的dotnet 应用程序来分配内存。它耗尽了机器上的所有物理内存,然后以OutOfMemoryException 崩溃。但是我的系统有一个交换文件,dotnet 从未使用过它。其他应用程序使用交换就好了。我玩过swappiness (60, 100, 1),但这没有效果。

我的理解是,Linux 上的进程可以消耗它想要的所有物理内存,如果没有剩余内存,则该内存将被写入交换文件/分区。只有当交换和物理内存都已满时,应用程序才会因 OOM 而崩溃。这是其他应用程序所做的,但不是dotnet 应用程序。

我尝试过 dotnet core 3.1 和 5.0,使用的操作系统是 Ubuntu 20.04。

编辑:我的测试代码:

namespace TestProject
{
    class Program
    {
        static List<byte[]> l = new List<byte[]>();

        static void Main(string[] args)
        {
            while (true)
            {
                var b = new byte[100 * 1000 * 1024];
                l.Add(b);
            }
        }
    }
}

【问题讨论】:

  • Java 的类似问题 - stackoverflow.com/questions/64888598/… 。不完全是一个骗局(并且它的质量标志),但答案开始涉及操作系统如何使用交换来为应用程序授予更多内存
  • 这是 Linux 上的可配置行为。您的vm.overcommit_memory 设置为什么? .net 应用程序是否在 64 位模式下运行?您是否正在创建任何 2GB 以上的数组?
  • 程序对交换一无所知,它是由内核管理的操作系统。你是如何分配内存的?可以出示相关代码吗?
  • @thatotherguy cat /proc/sys/vm/overcommit_memory 返回结果为 0。这是一个 64 位应用程序,我正在创建 100MB 数组。
  • @Alejandro 测试代码已添加。我知道它会永远分配内存,但我希望它在某些时候使用交换,并且只有在物理内存和交换都用完时才会崩溃。我知道进程只是要求内存并且操作系统会提供它,这就是为什么我不明白为什么这个程序没有交换(物理内存用完时出现 OOM 异常),但是如果我打开足够多的 chrome 选项卡,它将使用交换。

标签: linux memory .net-core swapfile


【解决方案1】:

经过反复试验后,我明白(或多或少)发生了什么。在上面的代码中,数组没有被完全分配,除非它的元素被“触摸”。我的意思是,除非我在将数组存储在静态列表中之前执行Array.Fill&lt;byte&gt;(b, 0) 之类的操作,否则消耗的内存不是我所期望的。虽然我不知道这种行为,但似乎 dotnet 的一些延迟分配对于降低内存使用是有意义的(即在您要使用数组之前实际上不分配)。如果我使用Array.Fill,那么内存会更快地上升,最终会被分页交换。

那么为什么我之前得到了 OOM 呢?我相信答案是我达到了静态列表的 2GB 对象大小。这是我不知道的限制,但在 dotnet 中,没有单个对象可以超过 2GB。使用上面的代码,我相信列表对象(内部数组、指向所有元素的指针等)已经用完了足够的内存,它达到了 2GB 的限制并导致 OOM。

感谢所有阅读本文并提供反馈的人。

【讨论】:

    猜你喜欢
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-10
    相关资源
    最近更新 更多