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



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

在严格的局域网条件下,我的I/O上限总是超过300 KB/s,但是如果我的程序在互联网上运行,我的网络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限制(队列通常为空,或短暂地有1个块)还是受IO限制(队列随着压缩速度的加快而逐渐变大)
  • 只要做一点工作,就可以对压缩进行多线程处理;你需要跟踪区块顺序,但这应该是可行的

最新更新