具有异步UDP操作的.NET IOCP ThreadPool开销

问题描述

| 我已经开发了一种VoIP媒体服务器,该服务器可以与远程SIP端点交换RTP数据包。它需要很好地扩展-尽管我最初担心我的C#实现不会接近它所替代的C ++版本,但我已经使用各种分析器来磨练实现,并且性能非常接近。 我通过创建可重用对象池来限制大多数对象分配,我使用ReceiveFromAsync和SendToAsync发送/接收数据报,并且使用生产者/消费者队列在系统中传递RTP数据包。现在,在配备2个2.4GHz Xeon处理器的计算机上,我可以处理大约1000个并发流,每个流每秒发送/接收50个数据包。但是,迭代配置文件/调整/配置文件让我着迷了-我相信那里的效率更高! 触发处理的事件是在socketasynceventargs调用Completed委托-该委托又通过处理管道发送RTP数据包。 剩下的令人沮丧的是,IOCP线程池中似乎存在大量开销。探查器显示,“我的代码”中只有72%的“包含采样”时间-在此之前的时间似乎是线程池开销(下面的堆栈帧)。 因此,我的问题是: 我在我的理解中缺少什么吗? 可以减少这种开销吗? 是否可以替换异步套接函数使用的线程池,以使用开销较小的自定义轻量级线程池? 100%MediaGateway 95.35%Thread :: intermediateThreadProc(无效*) 88.37%ThreadNative :: SetDomainLocalStore(class Object *) 88.37%BindioCompletionCallbackStub(无符号长,无符号长,结构_OVERLAPPED *) 86.05%BindioCompletionCallbackStubEx(无符号长,无符号长,结构_OVERLAPPED *,int) 86.05%ManagedThreadBase :: ThreadPool(结构ADID,void(*)(void *),void *) 86.05%CrstBase :: Enter(无效) 86.05%AppDomainStack :: PushDomain(结构ADID) 86.05%Thread :: ShouldChangeAbortToUnload(类框架*,类框架*) 86.05%AppDomainStack :: ClearDomainStack(无效) 83.72%ThreadPoolNative :: CorWaitHandleCleanupNative(void *) 83.72%__CT ?? _ R0PAVEEArgumentException @@@ 84 83.72%dispatchCallDebuggerWrapper(unsigned long *,unsigned long,unsigned long *,unsigned __int64,void *,无符号__int64,无符号int,无符号char *,类ContextTransitionFrame *) 83.72%dispatchCallBody(unsigned long *,unsigned long,unsigned long *,unsigned __int64,void *,unsigned __int64,unsigned int,unsigned char *) 83.72%MethodDesc :: EnsureActive(无效) 81.40%_CallDescrWorker @ 20 81.40%System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint32,uint32,值类型System.Threading.NativeOverlapped *) 76.74%System.Net.sockets.socketasynceventargs.CompletionPortCallback(uint32,uint32,valuetype System.Threading.NativeOverlapped *) 76.74%System.Net.sockets.socketasynceventargs.FinishOperationSuccess(值类型System.Net.sockets.socketError,int32,值类型System.Net.sockets.socketFlags) 74.42%System.Threading.ExecutionContext.Run(类System.Threading.ExecutionContext,类System.Threading.ContextCallback,对象) 72.09%System.Net.sockets.socketasynceventargs.ExecutionCallback(对象) 72.09%System.Net.sockets.socketasynceventargs.OnCompleted(类System.Net.sockets.socketasynceventargs)     

解决方法

在Windows上,每秒50,000个数据包相当不错,我想说硬件和操作系统对于扩展来说是更重要的问题。不同的网络接口施加了不同的限制,英特尔服务器NIC主要具有高性能,并且具有跨平台的良好驱动程序,但是与Linux相比,Broadcom在Windows上的记录不佳。 Windows的高级核心网络API仅在驱动程序支持这些功能时才启用,并且Broadcom已证明是一家公司,尽管其他操作系统支持较旧的设备,但仅对较新的硬件启用高级功能。 我将开始研究多个NIC,例如使用四核Intel Server NIC,并使用Windows高级网络API将一个NIC绑定到每个处理核心。从理论上讲,您可以通过一个NIC发送50,000,通过另一个NIC发送50,000。 http://msdn.microsoft.com/zh-CN/library/ff568337(v=VS.85).aspx 但是,似乎您并没有真正的基准来衡量代码的效率。我希望看到与不运行VoIP有效负载,在TCP传输而不是UDP上运行,在其他操作系统上运行的服务器进行比较以比较IP堆栈和API效率的服务器。     ,只是添加一些信息-我最近发现IOCP线程池中存在一个错误,该错误可能会影响您的性能:请参阅http://support.microsoft.com/kb/2538826中“原因”部分的第3点。这可能对您的情况有效。