WCF stream.Read行为

时间:2014-07-03 19:40:33

标签: .net wcf stream

场景:有一个WCF流服务,它向客户端提供文件流。在客户端,通过调用stream.Read(buffer,0,chunkSize)来读取WCF文件流,其中chunkSize是10240.

我想知道只有在调用Read时才会通过网络(Internet)传输数据,或者在后台读取数据的内容以及在调用stream.Read时可能已读取数据。我问这个是因为我需要测量下载速度。但是,在我读取一大块数据后,我执行其他操作 - 发送事件,将刚刚读取的数据写入本地文件流。因此,我需要对这些其他操作进行折扣,以便我清楚地了解仅下载文件所需的时间。所以我一直在测量下载10KB数据需要多长时间,最后使用总文件大小和总时间来计算kbsPerSecond。

不幸的是,在循环中使用秒表会导致性能下降,但我想如果我想正确测量带宽,我将不得不忍受它。

long totalBytesRead = 0;
Stopwatch stopwatch = new Stopwatch();

do
{
    int bytesRead;

    stopwatch.Start();
    bytesRead = stream.Read(buffer, 0, chunkSize);
    stopwatch.Stop();

    if (bytesRead == 0)
        break;

    totalBytesRead += bytesRead;

    // 1. write to local file stream
    // 2. raise file download progress events

} while (true);

long elapsedTime = stopwatch.ElapsedMilliseconds;
int kbsPerSecond = Convert.ToInt32(((double)totalBytesRead / 1024) / ((double)elapsedTime / 1000));

这种方法是否准确?

3 个答案:

答案 0 :(得分:3)

您是否测量过秒表的实际性能影响?我刚刚在我的机器上进行了快速测试(所以YMMV),用一个外部秒表来测量总时间,并在一个循环中使用一个秒表来模拟你正在使用的那个。循环迭代了一百万次,内部秒表的总体性能影响仅为49毫秒(分布在所有100万次迭代中),所以你说的是每次迭代的低单位数滴答。

除非你看到更大的影响,否则你不必担心它。

答案 1 :(得分:1)

我说这种方法相当准确,因为你在循环中做的其他事情是非常小的。

您可以通过下载更长的流,并通过增加chunkSize

来提高循环中有用的:非有用时间的比率

另外,检查bytesRead == 0并增加totalBytesRead确实可能花费很少的时间,我建议调用stopwatch.start / stop需要更长的时间 - 你可以将这些调用移到循环之外

答案 2 :(得分:0)

如果您需要一个真正准确的时间来读取流由于某种原因(为什么您需要如此高的准确度尚不清楚),为什么不隔离读取代码完全只通过将内容读入一个非常大的缓冲区来调用它(如果你知道从流中读取的内容大小,你可以使用它):

byte[] buffer = new byte[int.MaxValue]; // Alternatively, enter the size of the content
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int totalBytesRead = stream.Read(buffer, 0, buffer.Length);
stopwatch.Stop();
long elapsedTime = stopwatch.ElapsedMilliseconds;
double kbsPerSecond = ((double)totalBytesRead / 1024) / ((double)elapsedTime / 1000);

但是,如果这是生产代码并且您正在尝试测量实际生活时间,那么您的方法是正确的,与从流中读取所花费的时间相比,使用Stop and Start方法所花费的额外时间可以忽略不计