简体   繁体   English

NetworkStream上的ReadAsync似乎正在使用我的所有CPU

[英]ReadAsync on a NetworkStream appears to be using all my CPU

I have the following method, which reads and deserializes packets from a NetworkStream asynchronously. 我有以下方法,该方法异步读取和反序列化NetworkStream数据包。 Everything works, but CPU profiling shows that the very last line, in which I am awaiting an asynchronous read, is where the majority of my CPU usage comes from. 一切正常,但是CPU性能分析表明,我等待异步读取的最后一行是我大部分CPU使用量的来源。

Have I implemented this badly/inefficiently, or is there something inherently wrong with the NetworkStream 's async implementation? 我是否执行得很差/效率不高,或者NetworkStream的异步实现有天生的错误?

public async Task<Packet> ReadAsync(CancellationToken cancellationToken)
{
    while (true)
    {
        // Read through the available bytes until we find the start of a packet
        while (start < length && buffer[start] != Packet.STX)
            start++;

        // Align the packet (and all successive bytes) with the beginning of the buffer
        if (start > 0)
        {
            if (start < length)
                Array.Copy(buffer, start, buffer, 0, length - start);

            length -= start;
            start = 0;
        }

        // Read through the available bytes until we find the end of the packet
        while (end < length && buffer[end] != Packet.ETX)
            end++;

        // If we have a whole packet in the buffer, deserialize and return it
        if (end < length)
        {
            byte[] data = new byte[end + 1];
            Array.Copy(buffer, data, end + 1);
            byte[] decoded = null;
            Packet packet = null;

            try
            {
                decoded = Packet.Decode(data);
            }
            catch (Exception ex)
            {
                throw new IOException("Could not decode packet", ex);
            }

            if (decoded != null)
            {
                try
                {
                    packet = Packet.Deserialize(decoded);
                }
                catch (Exception ex)
                {
                    throw new IOException("Could not deserialize packet", ex);
                }
            }

            Array.Copy(buffer, end + 1, buffer, 0, length - (end + 1));
            length -= end + 1;
            end = 0;

            if (packet != null)
                return packet;
        }

        // If we read all available bytes while looking for the end of a packet
        if (end == length)
        {
            if (length == buffer.Length)
                throw new InsufficientMemoryException();

            length += await Stream.ReadAsync(buffer, length, buffer.Length - length, cancellationToken);
        }
    }
}

CPU分析结果

I have updated the code to sleep between each call to ReadAsync , for roughly the amount of time the last read took: 我已经更新了代码,以使每次调用ReadAsync之间都可以进入睡眠状态,时间大约是最后一次读取所花费的时间:

var stopwatch = new Stopwatch();
var iteration = 0;

while (true)
{
    // ...
    var delay = stopwatch.Elapsed;
    stopwatch.Restart();

    if (iteration % 10 != 0)
        await Task.Delay(delay);

    length += await Stream.ReadAsync(buffer, length, buffer.Length - length, cancellationToken);
    stopwatch.Stop();
    iteration += 1;
}

This has drastically dropped the CPU usage. 这大大降低了CPU使用率。 This is definitely a work-around, as it does not address the issue, but it works. 这绝对不是一种解决方法,因为它不能解决问题,但是可以。 I would love to hear anyone else's answers or opinions on this issue. 我很想听听其他人对此问题的回答或意见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM