如何在运行时告诉我的进程是CPU绑定还是I / O绑定

时间:2012-11-26 21:21:44

标签: c# networking .net-4.0 io compression

我有一个程序,我通过TCP链接发送数据。我正在使用异步读取并写入磁盘和网络。如果我在中间放置一个DeflateStream(所以我在写入网络链接之前进行压缩,然后在接收数据时将其解压缩并将其写入磁盘)我在压缩端受CPU限制。这会导致我的最大传输速率约为300 KB/s。但是,如果我删除压缩步骤,我现在将I / O绑定到磁盘,并且传输速率为40,000 KB/s

在严格的LAN条件下,我的上限I / O限制总是超过300 KB / s,但是如果我的程序通过互联网运行,我很可能会有一个低于300 KB / s的网络IO限制。

我想检测我是否受I / O限制,我的网络/磁盘链接是限制因素,或者我是否受CPU限制,压缩行为是最让我失望的原因。如何在运行时检测我的程序是否受到我的CPU或I / O的限制,以便我可以切换协议并获得最佳的传输速率?

private static void SendFile(string filename, NetworkStream stream, int sendBufferSize)
{
    using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
    using (var ds = new DeflateStream(stream, CompressionMode.Compress))
    {
        StreamUtilities.CopyAsync(fs, ds, sendBufferSize);
    }
}

public static void CopyAsync(Stream sourceStream, Stream destStream, int bufferSize = 4096)
{
    Byte[] bufferA = new Byte[bufferSize];
    Byte[] bufferB = new Byte[bufferSize];

    IAsyncResult writeResult = null;
    IAsyncResult readResult = null;

    bool readBufferA = false;
    int read;

    readResult = sourceStream.BeginRead(bufferA, 0, bufferA.Length, null, null);
    //Complete last read
    while ((read = sourceStream.EndRead(readResult)) > 0)
    {
        if (readBufferA)
        {
            PerformOperations(sourceStream, destStream, bufferA, bufferB, ref readResult, ref writeResult, read);
        }
        else
        {
            PerformOperations(sourceStream, destStream, bufferB, bufferA, ref readResult, ref writeResult, read);
        }

        //Flip the bit on the next buffer
        readBufferA = !readBufferA;
    }
    if (writeResult != null)
        destStream.EndWrite(writeResult);
}

private static void PerformOperations(Stream sourceStream, Stream destStream, Byte[] readBuffer, Byte[] writeBuffer, ref IAsyncResult readResult, ref IAsyncResult writeResult, int bytesToWrite)
{
    //Start next read
    readResult = sourceStream.BeginRead(readBuffer, 0, readBuffer.Length, null, null);

    //End previous write
    if (writeResult != null)
        destStream.EndWrite(writeResult);
    writeResult = destStream.BeginWrite(writeBuffer, 0, bytesToWrite, null, null);
}

1 个答案:

答案 0 :(得分:6)

一个选项是将两个方面分成生产者/消费者队列:压缩器将块写入队列,然后由刚刚执行IO的线程使用。

那样:

  • 您可以在IO发生时进行压缩,而无需进入异步IO
  • 您可以检测您是否受CPU限制(队列通常为空,或者短暂地有1个阻止)或IO绑定(队列逐渐变大,因为压缩速度比可以发送的速度快)
  • 通过一些工作,你可以多线程压缩;你需要跟踪区块顺序,但这应该是可行的。