。Net Core快速分配和零初始化内存(跨平台解决方案)

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

是否有使用.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
}
memory-management .net-core
1个回答
0
投票

在C#7中,.Net引入了用于处理内存的新结构,其中包括Span和Memory

Span被定义为一个引用结构,仅限于在堆栈上分配,即减少了一些潜在的用例,例如将其存储为类中的字段。但是您可以通过使用其他类型的内存来解决这些问题

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