Socket.ReceiveAsync可以转到C10K吗?

时间:2018-05-23 08:01:42

标签: c# sockets c10k

使用Socket.ReceiveAsync甚至Socket.SendAsync的TCP套接字是否会遇到C10K问题?

1 个答案:

答案 0 :(得分:1)

我不认为这完全是另一个问题的重复,正如建议的那样: Async-Await vs ThreadPool vs MultiThreading on High-Performance Sockets (C10k Solutions?) 这个问题更多地是关于各种线程模型的讨论,这些模型并不总是适用于Socket。**** Async(全部使用SocketAsyncEventArgs)。

这个问题的答案在很大程度上取决于您的运行时和操作系统。我最近在为Unity开发解决方案时走了这条路,所以即使问题有点老,我也将分享我所知道的东西。

我们首先讨论Windows和MS .NET(实现这些方法时从3.5开始的任何内容)。在此运行时和平台上组合这些套接字方法时,您肯定可以破坏c10k。带有SocketAsyncEventArgs参数的**** Async方法可以直接在运行时中进行本机调用,而本机调用将映射到Windows中的IO完成端口。这是运行时的特殊路径,它的作用不只是防止分配IAsyncResult对象。我认为在Linux上使用.NET Standard的速度也非常快,但是我不能直接这么说。

接下来,我们来讨论Linux上的Mono。具体来说,我目前正在使用: Mono C#编译器版本4.6.2.0 这也将破坏c10k,但其工作方式有所不同。据我所知,***** Async方法在运行时的路径与所有其他异步方法相同,但**** Async调用的路径最短,避免了IAsyncResult分配。运行时通过IOSelector.Add将您的请求作为IOSelectorJob提交。因此,似乎**** Async方法实际上都不会在Mono中返回false,尽管我不会指望该行为始终为true。我认为在Windows上使用Mono的速度同样快,但是我不能这么说。

最后,让我们谈谈Unity。我正在使用具有Mono 5.11.0运行时的2018.3.2f1,设置为.NET 4.x兼容。我不确定是否可以在Unity中破解c10k。我不知道为什么,但是我知道在Mono和.NET中轻易破坏c10k的相同实现甚至都不会实现。我认为这是因为它们的线程池以不同的方式设置了……也许是为了适应他们的工作系统,但这只是一个黑暗的猜测。发生非常奇怪的事情,例如同步接受优于异步。永远不会得到回调的AcceptAsync请求,等等。

一些在Unity之外破解c10k的技巧: -在IO完成回调中尽可能少地做。不要像在MSDN示例中那样在其中调用其他异步方法 -如果可以管理,则由于您的设计,请勿对SendAsync和ReceiveAsync进行相互阻止。您不能使用相同的arg进行2个未完成的调用,但可以同时使用多个和单独的arg(因此还有缓冲区)进行发送/接收。但是请注意,排序可能会变得很复杂,例如在同一套接字上有多个未完成的Recv的情况下,并发队列会从回调中分派返回的args -如果必须在线程之间共享资源,则System.Collections.Concurrent是您的朋友。不要自己动手,因为这些容器并不是为什么您不会破坏c10k的原因,因此您永远无法匹配这些婴儿所经历的测试量

祝你好运,玩得开心:)如果您发现Unity成功的秘诀,请不要忘记告诉我。我一定会更新的。