是否有使用.Net Core分配大内存块并将其初始化为零的快速方法?
正在寻找一种适用于Windows和Linux平台的解决方案。
似乎Windows上最快的方法是通过PInvoke调用kernel32 HeapAlloc函数,这将在不到2毫秒的时间内分配并清零1GB的内存块。
但是,我还没有找到一种仅使用.Net Core就能在Linux上获得类似结果的方法。
我尝试了Marshal.AllocHGlobal
方法,该方法不会将内存清零,然后使用Marshal.Copy将内存中的零字节数组复制到内存中,但是这会导致性能较差,即与2相比,为800毫秒毫秒以上。
对于我的应用程序,分配和清零需要在不到10毫秒的时间内完成。
。Net Core是否提供跨平台API,该API是否具有与Windows HeapAlloc或C函数calloc
类似的性能?
下面的测试代码:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace MemoryApp
{
class Program
{
static void Main(string[] args)
{
const int sizeBytes = 1_000_000_000;
Console.WriteLine($"Allocating memory of size: {sizeBytes} bytes.");
const int totalAttempts = 20;
for (int i = 0; i < totalAttempts; i++)
{
var stopwatch = Stopwatch.StartNew();
var allocatedMemory = new AllocatedMemory(sizeBytes);
stopwatch.Stop();
Console.WriteLine($"Allocated memory in {stopwatch.ElapsedTicks} ticks ({stopwatch.ElapsedMilliseconds} milliseconds).");
allocatedMemory.Dispose();
}
Console.ReadLine();
}
}
public unsafe class AllocatedMemory : IDisposable
{
public byte* MemoryAddress { get; }
#if USE_WINDOWS_HEAP
private IntPtr _heapPtr;
#else
private IntPtr _memoryPtr;
#endif
public AllocatedMemory(int sizeInBytes)
{
#if USE_WINDOWS_HEAP
var heapFlags = HeapFlags.HEAP_GENERATE_EXCEPTIONS | HeapFlags.HEAP_ZERO_MEMORY;
_heapPtr = Heap.HeapCreate(heapFlags, 0, 0);
MemoryAddress = (byte*)Heap.HeapAlloc(_heapPtr, heapFlags, (uint)sizeInBytes);
#else
// Memory allocated but not zeroed
_memoryPtr = Marshal.AllocHGlobal((IntPtr)sizeInBytes);
// Zero the memory
Marshal.Copy(new byte[sizeInBytes], 0, _memoryPtr, sizeInBytes);
MemoryAddress = (byte*)_memoryPtr;
#endif
}
~AllocatedMemory()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (MemoryAddress != null)
{
#if USE_WINDOWS_HEAP
Heap.HeapDestroy(_heapPtr);
#else
Marshal.FreeHGlobal(_memoryPtr);
#endif
}
}
}
}
#if USE_WINDOWS_HEAP
public class Heap
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr HeapCreate(HeapFlags flOptions, uint dwInitialsize, uint dwMaximumSize);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr HeapAlloc(IntPtr hHeap, HeapFlags dwFlags, uint dwSize);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool HeapDestroy(IntPtr hHeap);
}
[Flags]
public enum HeapFlags
{
HEAP_NO_SERIALIZE = 0x1,
HEAP_GENERATE_EXCEPTIONS = 0x4,
HEAP_ZERO_MEMORY = 0x8
}
#endif
}
在C#7中,.Net引入了用于处理内存的新结构,其中包括Span和Memory
Span被定义为一个引用结构,仅限于在堆栈上分配,即减少了一些潜在的用例,例如将其存储为类中的字段。但是您可以通过使用其他类型的内存来解决这些问题