[英]Allocating memory in C# is not actually allocating memory
當我聲明一個新的字節數組時,內存使用量不會增加。
byte[] test = new[1024*100];
只有在我遍歷每個字節之后,它才真正開始占用 ram。
我怎樣才能讓它實際提交內存而不必先使用它?
我將此用作帶有 try catch 塊的測試,以查看它是否無法分配內存,從而告訴我我的應用程序內存不足,不應嘗試分配任何新對象。
編輯:由於我將要分配的對象與垃圾收集器和堆棧一起使用,我不想使用 malloc 進行分配,因為它可能會在那里成功,但在嘗試分配新的托管對象時會失敗。
好吧,如果你真的想映射所有的內存,那么通過數組重復並用零填充它。 反正都是線性時間。 Array.Clear
使用Array.Clear
。 C# 確實不是為這種內存優化而設計的。 您應該關心的唯一資源是未損壞的資源。 在 C# 中考慮剩余內存消耗的正確方法是根本不考慮它。 老實說,在搜索這個問題之前,我不知道 C# 如何在數組聲明期間處理內存分配,這就是重點,我沒有使用高級抽象語言來關心這些東西。 只有當您的應用程序遇到內存瓶頸並且需要優化時,它才有意義。
有一個stackalloc
運營商,您也許可以彎曲到您的使用,但它是一個不安全的操作。 還有GC.GetTotalMemory()
,它可以顯示當前的內存使用情況(托管對象的),以及Microsoft.VisualBasic.Devices.ComputerInfo.TotalPhysicalMemory
,它會給你機器的總 RAM(不要介意 VB在名稱中,它是一個 .NET Framework 方法,只需添加對Microsoft.VisualBasic.Devices
的引用),因此使用它您可以實現您的目標,即是否有足夠的內存供您分配數組。
從 C# 7.2 開始,現在允許使用stackalloc
而無需使用Span<T>
和ReadOnlySpan<T>
類型進入unsafe
上下文。 但是,我無法確定是否需要從堆棧中實際分配stackalloc
指令,或者如果分配的緩沖區未使用,是否可以省略它,因此可能仍然需要實際遍歷緩沖區以誘使編譯器進入認為需要分配。
如果你想讓它分配所有的字節,你可以使用 Array.Clear,它會用 0 填充所有值
Array.Clear(test, 0, test.Length);
這個簡單的控制台應用程序可讓您在創建和填充 clear 時監控內存使用情況
class Program
{
static void Main(string[] args)
{
//Memory usage 7.1 MB
Console.WriteLine("Hit enter to allocate");
Console.ReadKey();
byte[] data = new byte[1024*1024]; //Memory still 7.1 MB
Console.WriteLine("Hit Enter to Fill with zeros!");
Console.ReadKey();
Array.Clear(data, 0, data.Length); //Memory now 8.1 MB
Console.WriteLine("1MB filled, hit enter to exit");
Console.ReadKey();
}
}
制作了一個函數,該函數將嘗試實際分配我指定的內存(如果不可能,則拋出異常而不是撒謊),如果成功,垃圾收集器將立即收集。
bool IsMemoryAvailable(int amount)
{
int size = (int)Math.Sqrt(amount) / 2;
try
{
using (Bitmap bmpTest = new Bitmap(size, size))
{
}
GC.Collect();
return true;
}
catch(Exception x)
{
return false;
}
}
如果您遷移到 .NET 6,您可以利用新引入的 NativeMemory 方法使用 C API 分配本機內存:
using System.Runtime.InteropServices;
unsafe
{
byte* buffer = (byte*)NativeMemory.Alloc(200);
NativeMemory.Free(buffer);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.