. net套接字与c++套接字的高性能对比

本文关键字:套接字 高性能 c++ net | 更新日期: 2023-09-27 18:17:25

我的问题是要和我的同事解决关于c++和c#的争论。

我们实现了一个接收大量UDP流的服务器。该服务器是用c++开发的,使用异步套接字和使用完成端口的重叠I/O。我们使用5个完成端口和5个线程。这台服务器可以轻松地在千兆网络上处理500mbps的吞吐量,而不会有任何数据包丢失/错误(我们的测试没有超过500mbps)。

我们尝试在c#中重新实现相同类型的服务器,但我们无法达到相同的传入吞吐量。我们使用异步接收,使用ReceiveAsync方法和SocketAsyncEventArgs池,以避免为每个接收调用创建新对象的开销。每个SAEventArgs都有一个缓冲区设置,所以我们不需要为每个接收分配内存。池非常非常大,所以我们可以排队接收超过100个请求。此服务器无法处理超过240 Mbps的传入吞吐量。超过这个限制,我们会在UDP流中丢失一些数据包。

我的问题是:我应该期望使用c++套接字和c#套接字获得相同的性能吗?我的观点是,如果在。net中正确管理内存,它应该具有相同的性能。

边问题:谁知道一个好的文章/参考解释如何。net套接字使用I/O完成端口在引擎盖下?

. net套接字与c++套接字的高性能对比

谁知道一个好的文章/参考解释如何。net套接字使用I/O完成端口在引擎盖下?

我怀疑唯一的参考将是实现(即。反射器或其他汇编反编译器)。这样,你会发现所有异步IO都经过一个IO完成端口,回调在IO线程池中处理(与普通线程池分开)。

使用5个补全端口

我希望使用单个完成端口将所有IO处理到单个线程池中,每个线程池一个线程处理完成(假设您正在异步处理任何其他IO,包括磁盘)。

如果你有某种形式的优先级,那么多个完成端口是有意义的。

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

是或否,取决于你对"using…"的定义有多窄。套接字"部分。从异步操作开始到完成被发布到完成端口的操作方面,我希望没有显著的差异(所有的处理都在Win32 API或Windows内核中)。

但是。net运行时提供的安全性会增加一些开销。如。将检查缓冲区长度,验证委托等。如果应用程序的限制是CPU,那么这可能会产生差异,在极端情况下,微小的差异很容易累积起来。

. net版本也会偶尔暂停GC()。. NET 4.5做了异步收集,所以将来会变得更好)。有一些技术可以尽量减少垃圾的堆积。重用对象而不是创建对象,在使用结构的同时避免装箱)。

最后,如果c++版本可以工作并且满足您的性能需求,为什么要移植呢?

你不能直接将代码从c++移植到c#并期望相同的性能。当涉及到内存管理(GC)和确保代码安全(边界检查等)时,. net比c++做得更多。

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

Begin/End和Async方法都在后台使用IO完成端口。后者不需要为每个操作分配对象,从而提高了性能。

我的猜测是,您没有看到相同的性能,因为。net和c++实际上在做不同的事情。您的c++代码可能不那么安全,或者检查边界。此外,您是否只是在不进行任何处理的情况下测量接收数据包的能力?或者您的吞吐量是否包括数据包处理时间?如果是这样,那么您为处理数据包而编写的代码可能没有那么有效。

我建议使用分析器来检查花费最多时间的地方,并尝试优化它。实际的套接字代码应该非常高效。