gpt4 book ai didi

c# - 使用托管内存进行注册 I/O RIOSend 函数调用

转载 作者:太空狗 更新时间:2023-10-29 23:32:41 25 4
gpt4 key购买 nike

我正在开发一个需要高速、低延迟/抖动通信的系统,它是用 C# 编写的。我们看到有一种新机制可以通过称为 Windows Registered IO 的套接字获得更好的性能 http://www.serverframework.com/asynchronousevents/2011/10/windows-8-registered-io-networking-extensions.html

...但目前 C# 不可用...而且根据 C++ 测试,它似乎确实显示出更好的性能。

无论如何,我已经编写了托管 C++/CLI 部分来创建 DLL,这似乎可以很好地与 C# 配合使用,而且数量大大提高。

但我想知道是否可以通过发送...保存缓冲区副本

目前 C++ 包装器看起来像这样:

bool ManagedSendData( array<byte> ^ buf, ULONG bufLen )
{
// must pin array memory until we're done with sending it,
// at which point it'll be copied into the unmanaged memory

pin_ptr<Byte> p = &buf[0]; // pinning one element of an array pins the whole array
unsigned char * cp = p;

return _RIObs->SendData( cp, bufLen );
}

其中 _RIObs 是实现注册 I/O 功能的非托管 C++ 对象。在该函数中,它会将数据复制到启动时使用 RIORegisterBuffer() 注册的缓冲区中,然后调用 RIOSend() 通知操作系统有要发送的数据。

所以,我的问题是,我能否让这个托管 C++ 对象的用户在启动时传入一个托管字节数组,并对其调用 GCHandle::Alloc() 以修复它并防止垃圾回收,在托管应用程序中对其调用 RIORegisterBuffer(),然后在托管 C++ 对象处于事件状态时使用它?我将注册托管缓冲区内存而不是非托管内存,当用户想要发送数据时,他们将填充他们已经引用的缓冲区,并通知我他们想要发送多少字节。这是一个阻塞发送并等待完成事件,所以他们不会再次使用缓冲区,直到操作系统完成数据。

只要托管内存被锁定直到不再需要它,只要非托管应用程序可以互换使用托管内存或非托管内存,它似乎就可以工作。

最佳答案

您可以直接从 C# 调用 RIO,而不是通过 C++/CLI;分配一个大于 85k 的大缓冲区,这会将其移动到 LoH 而不是干扰常规 GC,然后您可以使用类似于您建议的内容:

_underlyingBuffer = new byte[BufferLength];
var pinnedBuffer = GCHandle.Alloc(_underlyingBuffer, GCHandleType.Pinned);
var address = Marshal.UnsafeAddrOfPinnedArrayElement(_underlyingBuffer, 0);
var bufferId = _rio.RegisterBuffer(address, BufferLength);

我已经使用 direct interop to Registered IO 组合了一个示例 http 回显服务器和 some analysis它的表现如何(非常好)。

关于c# - 使用托管内存进行注册 I/O RIOSend 函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14731550/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com