gpt4 book ai didi

c# - async/await 会影响 tcp 服务器性能吗?

转载 作者:可可西里 更新时间:2023-11-01 02:31:47 26 4
gpt4 key购买 nike

我在 C# 5.0 中创建一个 Tcp 服务器,我在调用 tcpListener.AcceptTcpClientAsyncnetworkStream.ReadAsync 时使用 await 关键字

但是,当我使用 Process Explorer 检查服务器的 CPU 使用率时,我得到以下结果:

TCP 同步版本:10% CPU 使用率

Tcp 异步版本:30% CPU 使用率一半的使用量是内核使用量。

此外,我通过在网络流的 while 外观中添加一个计数器来测量接收数据的次数,异步版本循环 120,000 次,同步版本循环 2,500,000 次。

就每秒收到的消息而言,当从 3 个不同的客户端接收消息时,异步版本比同步版本慢 15%。

为什么异步版本比同步版本使用更多的 CPU?

这是因为 async/await 关键字吗?

异步 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)
{
// Deserialize
}

private void RunTcpListener(){
_tcpListener = null;
try
{
_tcpListener = new TcpListener(_serverEndPoint.IpAddress, _serverEndPoint.Port);
_tcpListener.Start();
while (true)
{
var tcpClient = await _tcpListener.AcceptTcpClientAsync().ConfigureAwait(false);
var asyncTcpClientConnection = new AsyncTcpClientConnection(tcpClient, MessageArrived);
_tcpClientConnections.Add(asyncTcpClientConnection);
}
}
finally
{
if (_tcpListener != null)
_tcpListener.Stop();

IsRunning = false;
}
}

public void Stop()
{
IsRunning = false;
_tcpListener.Stop();
_tcpClientConnections.ForEach(c => c.Close());
}
}

我们为每个新客户端创建一个新的 AsyncTcpConnection

public class AsyncTcpClientConnection
{
private readonly Action<byte[]> _messageArrived;
private readonly TcpClient _tcpClient;

public AsyncTcpClientConnection(TcpClient tcpClient, Action<byte[]> messageArrived)
{
_messageArrived = messageArrived;
_tcpClient = tcpClient;
ReceiveDataFromClientAsync(_tcpClient);
}

private async void ReceiveDataFromClientAsync(TcpClient tcpClient)
{
var readBuffer = new byte[2048];
// PacketProtocol class comes from http://blog.stephencleary.com/2009/04/sample-code-length-prefix-message.html
var packetProtocol = new PacketProtocol(2048);
packetProtocol.MessageArrived += _messageArrived;

try
{
using (tcpClient)
using (var networkStream = tcpClient.GetStream())
{
int readSize;
while ((readSize = await networkStream.ReadAsync(readBuffer, 0, readBuffer.Length).ConfigureAwait(false)) != 0)
{
packetProtocol.DataReceived(readBuffer, readSize);
}
}
}
catch (Exception ex)
{
// log
}
}

public void Close()
{
_tcpClient.Close();
}
}

EDIT2:同步服务器

 public class TcpListener : ITcpListener
{
private readonly ObserverEndpoint _serverEndPoint;
private readonly List<TcpClientConnection> _tcpClientConnections = new List<TcpClientConnection>();

private Thread _listeningThread;
private TcpListener _tcpListener;
public bool IsRunning { get; private set; }

public TcpMetricListener()
{
_serverEndPoint = GetServerEndpoint();

}


public void Start()
{
IsRunning = true;
_listeningThread = BackgroundThread.Start(RunTcpListener);
}

public void Stop()
{
IsRunning = false;

_tcpListener.Stop();
_listeningThread.Join();
_tcpClientConnections.ForEach(c => c.Close());
}

private void MessageArrived(byte[] buffer)
{
// Deserialize
}

private void RunTcpListener()
{
_tcpListener = null;
try
{
_tcpListener = new TcpListener(_serverEndPoint.IpAddress, _serverEndPoint.Port);
_tcpListener.Start();
while (true)
{
var tcpClient = _tcpListener.AcceptTcpClient();
_tcpClientConnections.Add(new TcpClientConnection(tcpClient, MessageArrived));
}
}
finally
{
if (_tcpListener != null)
_tcpListener.Stop();

IsRunning = false;
}
}
}

和连接

public class TcpClientConnection
{
private readonly Action<byte[]> _messageArrived;
private readonly TcpClient _tcpClient;
private readonly Task _task;
public TcpClientConnection(TcpClient tcpClient, Action<byte[]> messageArrived)
{
_messageArrived = messageArrived;
_tcpClient = tcpClient;
_task = Task.Factory.StartNew(() => ReceiveDataFromClient(_tcpClient), TaskCreationOptions.LongRunning);

}

private void ReceiveDataFromClient(TcpClient tcpClient)
{
var readBuffer = new byte[2048];
var packetProtocol = new PacketProtocol(2048);
packetProtocol.MessageArrived += _messageArrived;


using (tcpClient)
using (var networkStream = tcpClient.GetStream())
{
int readSize;
while ((readSize = networkStream.Read(readBuffer, 0, readBuffer.Length)) != 0)
{
packetProtocol.DataReceived(readBuffer, readSize);
}
}
}


public void Close()
{
_tcpClient.Close();
_task.Wait();
}
}

最佳答案

我也遇到了 async 的问题,这些是我的发现:https://stackoverflow.com/a/22222578/307976

另外,我有一个使用 async 示例的异步 TCP 服务器/客户端 here可以很好地扩展。

关于c# - async/await 会影响 tcp 服务器性能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22222531/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com