要调用需要 IntPtr 的方法,使用 /unsafe 还是 Marshal.AllocHGlobal 更好?

发布于 2024-08-10 08:56:45 字数 1485 浏览 12 评论 0原文

我有一个类,它将在应用程序的整个持续时间内保留一些实例。这些对象都需要每秒多次调用一个 dll 方法,该方法从现有 float[] 缓冲区附加数据,并将完整数据集传递给接受 IntPtr(浮点数组)的 DLL 方法。作为非托管代码更好:



    class PersistentThing : IDisposable {
        readonly IntPtr _floats = Marshal.AllocHGlobal(sizeof(float) * ArraySize);

        public void DoFrequentAction() {
            // Append data from a buffer to the memory space.
            var floatOffsetPtr = new IntPtr(_floats.ToInt32() + _floatsIndex * sizeof(float));
            Marshal.Copy(_buffer, _bufferIndex, floatOffsetPtr, _bufferCount);

            // Call a DLL method with with memory pointer
            CallDllMethod(_floats);
        }

        // Need to dispose the unmanaged memory
        public void Dispose() {
            Marshal.FreeHGlobal(_floats);
        }
    }

还是使用不安全标签并修复更好?


    class PersistentThing2 {
        readonly float[] _floats = new float[ArraySize];

        public unsafe void DoFrequentAction() {
            // Append data from a buffer to the memory space.
            Array.Copy(_buffer, _bufferIndex, _floats, _floatsIndex, _bufferCount);

            // Call a DLL method with with memory pointer
            fixed (float* floatsPtr = _floats) {
                CallDllMethod((IntPtr)floatsPtr);
            }
        }
    }

不必在编译器中使用“不安全”标签有什么好处吗? Marshal级实际上更“安全”吗?这些方法中哪一种通常具有更好的性能?

我倾向于前者,因为这样GC在清理内存空间时就不必担心_floats(它可能很大)。这是一个合理的担忧吗?建议是否取决于 ArraySize 的大小?

I have a class that will have a few instances persistent throughout the duration of the application. These objects will each need to call a dll method that appends data from an existing float[] buffer, and passes the full dataset to a DLL method that accepts an IntPtr (float array), several times per second. Is it better to do it as unmanaged code:



    class PersistentThing : IDisposable {
        readonly IntPtr _floats = Marshal.AllocHGlobal(sizeof(float) * ArraySize);

        public void DoFrequentAction() {
            // Append data from a buffer to the memory space.
            var floatOffsetPtr = new IntPtr(_floats.ToInt32() + _floatsIndex * sizeof(float));
            Marshal.Copy(_buffer, _bufferIndex, floatOffsetPtr, _bufferCount);

            // Call a DLL method with with memory pointer
            CallDllMethod(_floats);
        }

        // Need to dispose the unmanaged memory
        public void Dispose() {
            Marshal.FreeHGlobal(_floats);
        }
    }

or would it be better to use an unsafe tag and fixed?


    class PersistentThing2 {
        readonly float[] _floats = new float[ArraySize];

        public unsafe void DoFrequentAction() {
            // Append data from a buffer to the memory space.
            Array.Copy(_buffer, _bufferIndex, _floats, _floatsIndex, _bufferCount);

            // Call a DLL method with with memory pointer
            fixed (float* floatsPtr = _floats) {
                CallDllMethod((IntPtr)floatsPtr);
            }
        }
    }

Is there any advantage of not having to use the "unsafe" tag in the compiler? Is the Marshal class actually any "safer"? Which of these methods generally have the better performance?

I lean toward the former, just because that way the GC doesn't have to worry about _floats (which could be quite large) when cleaning up the memory space. Is that a reasonable concern? Does the recommendation depend on the size of ArraySize?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青朷 2024-08-17 08:56:45

在这两种情况下,您都在调用本机、不安全的代码。

我更喜欢第二种选择——它更干净、更容易理解、也更明显。它也不会强制您使用 IDisposable 来收集您的数组。

In both cases, you're calling native, unsafe code.

I prefer the second option - it's cleaner, easier to follow, and more obvious. It also doesn't force IDisposable on you for your array to be collected.

翻身的咸鱼 2024-08-17 08:56:45

我最终了解到这两种解决方案都很好。性能大致相同,GC 不会对第二个解决方案产生影响,因为对象要么被分配到大对象堆并且从不移动,要么在垃圾收集器上快速提升到第二代并且很少移动。

I ultimately learned that both solutions are fine. Performance is about the same and the GC won't have an impact on the 2nd solution, since the object would either be allocated to the Large Object Heap and never moved, or quickly be promoted to 2nd generation on the garbage collector and moved very rarely.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文