我正在使用同步apis和线程池的tcp服务器上看起来像这样:
TcpListener listener;
void Serve(){
while(true){
var client = listener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(this.HandleConnection, client);
//Or alternatively new Thread(HandleConnection).Start(client)
}
}
Run Code Online (Sandbox Code Playgroud)
假设我的目标是在资源使用率最低的情况下处理尽可能多的并发连接,这似乎很快就会受到可用线程数量的限制.我怀疑通过使用非阻塞任务apis,我将能够用更少的资源处理更多.
我最初的印象是这样的:
async Task Serve(){
while(true){
var client = await listener.AcceptTcpClientAsync();
HandleConnectionAsync(client); //fire and forget?
}
}
Run Code Online (Sandbox Code Playgroud)
但令我印象深刻的是,这可能会导致瓶颈.也许HandleConnectionAsync需要花费非常长的时间才能达到第一次等待,并且将阻止主接受循环继续进行.这只会使用一个线程,还是运行时会在多个线程上神奇地运行它看起来合适的东西?
有没有办法结合这两种方法,以便我的服务器将使用它所需的线程数量来确定正在运行的任务的数量,但是它不会在IO操作上不必要地阻塞线程?
在这样的情况下,是否存在最大化吞吐量的惯用方法?
我创建在C#5.0 TCP服务器和打电话时我使用的await关键字tcpListener.AcceptTcpClientAsync和networkStream.ReadAsync
但是,当我使用Process Explorer检查我的服务器的CPU使用率时,我得到以下结果:
Tcp Sync版本: CPU使用率为10%
Tcp异步版本:30%的CPU使用率一半的使用是内核使用.
此外,我通过在网络流的外观中添加计数器来测量我接收数据的时间,并且异步版本循环120,000次,而同步版本循环2,500,000次.
在收到的消息/秒中,当从3个不同的客户端接收消息时,异步版本比同步版本慢15%.
为什么Async Version比Sync版本使用更多的CPU?
这是因为async/await关键字?
Async Tcp服务器比其同步速度慢吗?这是正常的吗?
编辑:这是异步tcp服务器代码的示例
public class AsyncTcpListener : ITcpListener
{
private readonly ServerEndpoint _serverEndPoint; // Custom class to store IpAddress and Port
public bool IsRunning { get; private set; }
private readonly List<AsyncTcpClientConnection> _tcpClientConnections = new List<AsyncTcpClientConnection>();
private TcpListener _tcpListener;
public AsyncTcpMetricListener()
{
_serverEndPoint = GetServerEndpoint();
}
public async void Start()
{
IsRunning = true;
RunTcpListener();
}
private void MessageArrived(byte[] buffer)
{
// …Run Code Online (Sandbox Code Playgroud)