WCF流的Read行为

4
情境:有一个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个回答

3
你有没有测量秒表的实际性能影响?我在我的机器上进行了快速测试(因此你的情况可能不同),使用外部秒表来测量总时间,并在循环内使用了一个秒表来模拟你正在使用的秒表。该循环迭代一百万次,内部秒表的总性能影响仅为49毫秒(分布在所有1百万次迭代中),因此每次迭代只有几个低单数滴答声。
除非你看到更大的影响,否则看起来你不需要担心它。

1

考虑到您在循环内部执行的其他操作非常简单,因此我认为这种方法相当准确。

您可以通过下载更长的流并增加chunkSize来提高循环中有用时间与无用时间的比率。

此外,检查bytesRead == 0并递增totalBytesRead的时间可能非常短,我建议将stopwatch.start/stop的调用移至循环之外,因为这些调用需要较长时间。


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和Start方法所花费的额外时间是可以忽略不计的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接