C# 如何在运行时判断我的进程是CPU绑定的还是I/O绑定的

C# 如何在运行时判断我的进程是CPU绑定的还是I/O绑定的,c#,networking,.net-4.0,io,compression,C#,Networking,.net 4.0,Io,Compression,我有一个通过TCP链路发送数据的程序。我对磁盘和网络都使用异步读写。如果我把一个放在中间(所以我压缩之前,我写的网络链接,我解压缩,当我收到的数据,并把它写到磁盘)我的CPU绑定在压缩侧。这导致我的最大传输速率约为300 KB/s。但是,如果我删除压缩步骤,我现在将I/O绑定到磁盘,并获得40000 KB/s的传输速率 在严格的局域网条件下,我的I/O上限将始终超过300 KB/s,但是如果我的程序在internet上运行,我的网络IO上限很可能低于300 KB/s 我想检测一下我是否受I/O限

我有一个通过TCP链路发送数据的程序。我对磁盘和网络都使用异步读写。如果我把一个放在中间(所以我压缩之前,我写的网络链接,我解压缩,当我收到的数据,并把它写到磁盘)我的CPU绑定在压缩侧。这导致我的最大传输速率约为
300 KB/s
。但是,如果我删除压缩步骤,我现在将I/O绑定到磁盘,并获得
40000 KB/s
的传输速率

在严格的局域网条件下,我的I/O上限将始终超过300 KB/s,但是如果我的程序在internet上运行,我的网络IO上限很可能低于300 KB/s

我想检测一下我是否受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);
}

一种选择是将这两个方面分离到生产者/消费者队列中:压缩器将块写入队列中,然后该队列由仅执行IO的线程使用

这样:

  • 您可以在IO发生时进行压缩,而无需进入异步IO
  • 您可以检测自己是CPU受限(队列通常为空,或者短暂地有一个块)还是IO受限(随着压缩速度的加快,队列逐渐变大,无法发送)
  • 只需一点工作,就可以实现多线程压缩;您需要跟踪批量订单,但这应该是可行的

但压缩过程当然会让你慢下来。。。试着把它放到另一个线程上。@YoryeNathan我正在使用异步I/O,读和写已经在不同的线程上了(好吧,这不是真正的线程,它是内核中的Aysnc IO系统,但它有相同的影响)是的,但是压缩和写IO在同一个线程上吗?每个压缩都应该有自己的线程(嗯,有点),每当压缩线程发出“哇,我完成了!”的声音时,就会发生异步写入操作。我相信它与读取IO在同一个线程上,我认为这是我的解决方案,但我不想太快地接受一个答案,从而阻碍其他答案。在过去,你只是观察磁带机,看看它们是否停止移动。啊,我。