.NET套接字与C + +套接字高性能

我的问题是与C ++与C#的同事解决一个争论。

我们已经实现了一个接收大量UDPstream的服务器。 这个服务器是用C ++开发的,使用asynchronous套接字和重叠的I / O使用完成端口。 我们使用5个线程的5个完成端口。 这台服务器可以在千兆networking上轻松处理500 Mbps的吞吐量,而不会丢失任何数据包/错误(我们没有将testing推到500 Mbps以上)。

我们试图在C#中重新实现相同types的服务器,并且我们还没有达到相同的吞吐量。 我们使用ReceiveAsync方法和SocketAsyncEventArgs池来使用asynchronous接收,以避免为每个接收调用创build新对象的开销。 每个SAEventArgs都有一个缓冲区,所以我们不需要为每个接收分配内存。 池非常非常大,所以我们可以排队超过100个接收请求。 此服务器无法处理超过240 Mbps的传入吞吐量。 超过这个限制,我们在UDPstream中丢失了一些数据包。

我的问题是:我应该期望使用C + +套接字和C#套接字相同的性能? 我的意见是,如果内存在.NET中正确pipe理,它应该是相同的性能。

侧面的问题:有人会知道一个很好的文章/参考解释如何.NET套接字使用I / O完成端口下的引擎?

有人会知道一个很好的文章/参考解释如何.NET套接字使用I / O完成端口下的引擎?

我怀疑唯一的参考将是实现(即reflection器或其他汇编反汇编)。 这样你就会发现所有的asynchronousIO都通过一个IO完成端口,并且在IO线程池(与普通线程池分离)中处理callback。

使用5个完成端口

我期望使用单个完成端口将所有IO处理成一个线程池,每个池有一个线程服务完成(假设您正在执行任何其他IO,包括asynchronous的磁盘)。

如果您有某种forms的优先级正在进行,多个完成端口将是有意义的。

我的问题是:我应该期望使用C + +套接字和C#套接字相同的性能?

是或否,取决于您定义“使用…套接字”部分的狭窄程度。 就从asynchronous操作开始直到完成发布到完成端口的操作而言,我认为没有显着差异(所有处理都在Win32 API或Windows内核中)。

但是.NET运行时提供的安全性会增加一些开销。 例如。 缓冲区长度将被检查,代表validation等。如果应用程序的限制是CPU,那么这可能会有所作为,在极端情况下,一个小的差异可以很容易地加起来。

另外,.NET版本偶尔会暂停GC(.NET 4.5会进行asynchronous收集,所以在将来会更好)。 有一些技术可以最大限度地减less垃圾堆积(例如重用对象而不是创build它们,在避免装箱的同时利用结构)。

最后,如果C ++版本能够正常工作并满足您的性能需求,为什么要使用端口?

你不能直接从C ++代码到C#,并期待相同的性能。 在涉及到内存pipe理(GC)时,.NET确实比C ++做得更多,并确保你的代码是安全的(边界检查等)。

我将为所有IO操作(例如65535 x 500 = 32767500字节)分配一个大缓冲区,然后为每个SocketAsyncEventArgs (和发送操作)分配一个块。 内存比CPU便宜。 使用缓冲区pipe理器/工厂为所有连接和IO操作提供块(Flyweight模式)。 微软在他们的Async例子中这样做。

开始/结束和asynchronous方法在后台使用IO完成端口。 后者不需要为每个操作分配对象来提升性能。

我的猜测是你没有看到相同的性能,因为.NET和C ++实际上在做不同的事情。 你的C ++代码可能并不安全,或者检查边界。 另外,你是否简单地测量了没有任何处理的接收数据包的能力? 还是你的吞吐量包括数据包处理时间? 如果是这样,那么你可能已经编写来处理数据包的代码可能没有那么高效。

我build议使用一个分析器来检查大部分时间在哪里,并试图优化。 实际的套接字代码应该是相当高效的。