问题描述
我编写了一个简单的 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);
}
}
}
}
解决方法
好的,经过一些反复试验,我明白(或多或少)发生了什么。在上面的代码中,数组没有完全分配,除非它的元素被“触及”。我的意思是消耗的内存不是我所期望的,除非我在将数组存储在静态列表中之前执行类似 Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const srcFirst As String = "C4"
Const dstFirst As String = "C4"
Dim srg As Range: Set srg = defineColumnRange(Range(srcFirst))
If srg Is Nothing Then
With Sheet2.Range(dstFirst)
.Resize(.Worksheet.Rows.Count - .Row + 1).ClearContents
End With
Exit Sub
End If
Dim rg As Range: Set rg = Intersect(srg,Target)
If rg Is Nothing Then Exit Sub
Dim dCel As Range: Set dCel = Sheet2.Range(dstFirst)
On Error GoTo clearError
Application.EnableEvents = False
copySortedUniqueColumn srg,dCel
SafeExit:
Application.EnableEvents = True
Exit Sub
clearError:
Resume SafeExit
End Sub
的操作。虽然我不知道这种行为,但似乎 dotnet 部分的一些延迟分配是有意义的,以减少内存使用(即在您要使用数组之前不实际分配)。如果我使用 Array.Fill<byte>(b,0)
,那么内存会加快很多,最终确实会被调出以进行交换。
那为什么我之前会收到 OOM?我相信答案是我达到了静态列表的 2GB 对象大小。这是一个我不知道的限制,但在 dotnet 中,没有一个对象可以超过 2GB。使用上面的代码,我相信在列表对象(内部数组、指向所有元素的指针等)中使用了足够的内存,它达到了 2GB 限制并导致 OOM。
感谢所有阅读本文并提供反馈的人。