将同步方法内联到异步方法的性能大幅下降

时间:2012-12-11 16:54:49

标签: c# .net async-await

我有一个简单的性能测试,间接调用WriteAsync很多次。只要实现WriteAsync,它就会合理地执行,如下所示。但是,当我将WriteByte内联到WriteAsync时,性能会下降约7倍。

(要明确:我所做的唯一更改是将WriteByte调用的语句替换为WriteByte的正文。)

有人可以解释为什么会这样吗?我已经看过使用Reflector生成的代码的差异,但没有任何东西让我感到如此完全不同,因为它可以解释巨大的性能。

public sealed override async Task WriteAsync(
    byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
    var writeBuffer = this.WriteBuffer;
    var pastEnd = offset + count;

    while ((offset < pastEnd) && ((writeBuffer.Count < writeBuffer.Capacity) ||
        await writeBuffer.FlushAsync(cancellationToken)))
    {
        offset = WriteByte(buffer, offset, writeBuffer);
    }

    this.TotalCount += count;
}
private int WriteByte(byte[] buffer, int offset, WriteBuffer writeBuffer)
{
    var currentByte = buffer[offset];

    if (this.previousWasEscapeByte)
    {
        this.previousWasEscapeByte = false;
        this.crc = Crc.AddCrcCcitt(this.crc, currentByte);
        currentByte = (byte)(currentByte ^ Frame.EscapeXor);
        ++offset;
    }
    else
    {
        if (currentByte < Frame.InvalidStart)
        {
            this.crc = Crc.AddCrcCcitt(this.crc, currentByte);
            ++offset;
        }
        else
        {
            currentByte = Frame.EscapeByte;
            this.previousWasEscapeByte = true;
        }
    }

    writeBuffer[writeBuffer.Count++] = currentByte;
    return offset;
}

1 个答案:

答案 0 :(得分:2)

编译器将

async方法重写为巨型状态机,与使用yield return的方法非常相似。您所有的本地人都成为状态机类中的字段。编译器目前根本不会尝试对此进行优化,因此任何优化都取决于编码器。

现在正在读取和写入记忆的每个本地人都会愉快地坐在寄存器中。重构async方法的同步代码 out 并进入同步方法是一种非常有效的性能优化 - 你只是反过来了!