HttpWebResponse 响应流的最佳缓冲区大小
与来自 HttpWebResponse.GetResponseStream() 的流一起使用的最佳缓冲区大小是多少?
在线示例从 256b 到 5Kb 不等。 是什么赋予了? 我猜缓冲区大小可能是视情况而定。 如果是的话,什么情况下使用什么类型的缓冲区大小?
谢谢。
What's the optimal buffer size to use with a stream from HttpWebResponse.GetResponseStream()?
Online examples vary from 256b to as much as 5Kb. What gives? I guess buffer sizes might be situational. If so what are the situations to use what type of buffer size?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
真的,这并不重要。
当然,如果您使用非常小的缓冲区,您可能必须在各层中进行一些额外的调用才能获取字节(尽管流可能至少做了一些缓冲 - 我不知道它的默认值是什么)。 当然,如果您使用非常大的缓冲区,您将浪费一些内存并引入一些碎片。 由于您显然在这里进行 IO,因此通过调整缓冲区获得的任何时间都将由 IO 时间主导。
作为一般规则,我使用 2048 (2k) 和 8192 (8k) 之间的 2 的幂。 只要确保您知道自己在做什么,如果您使用的缓冲区等于或大于 85,000 字节(那么它就是一个 "大对象"并遵循不同的 GC 规则)。
事实上,比缓冲区大小更重要的是你保存它的时间。 对于大型对象堆之外的对象,GC 非常擅长处理生命周期非常短的对象(第 0 代收集速度很快)或生命周期非常长的对象(第 2 代)。 在被释放之前存活时间足够长以到达 Gen 1 或 Gen 2 的对象相对而言成本更高,并且通常比缓冲区有多大更值得您花时间担心。
最后一点:如果您认为由于使用的缓冲区大小而导致性能问题,请测试。 这不太可能,但谁知道呢,也许你有一个奇怪的操作系统版本、网络硬件和驱动程序版本的融合,这对某些大小的缓冲区有一些奇怪的问题。
Really, it doesn't matter very much.
Sure, if you use really small buffers, you may have to make a few extra calls down through the layers to get the bytes (though the stream is likely doing at least some buffering -- I don't know what it's defaults are). And sure, if you use really big buffers, you'll waste some memory and introduce some fragmentation. Since you're obviously doing IO here, any time you gain by tweaking the buffers is going to be dominated by the IO time.
As a general rule, I go with a power of two between 2048 (2k) and 8192 (8k). Just make sure you know what you're doing if you go with a buffer equal to or larger than 85,000 bytes (it's then a "large object" and subject to different GC rules).
In fact, more important than the buffer size is how long you hold it. For objects outside of the large object heap, the GC is very good at dealing with very short-lived objects (Gen 0 collections are fast), or very long-lived objects (Gen 2). Objects that live long enough to get to Gen 1 or 2 before being freed are comparatively more costly, and usually much more worth your time worrying about than how big the buffer is.
One final note: if you think you have a performance issue because of the size of buffers you are using, test it. It's unlikely, but who knows, maybe you have an odd confluence of OS version, network hardware, and driver release that has some odd issue with certain-sized buffers.
我的轶事经验是,它确实取决于您在做什么,但通常 1024-4096 字节(1-4KB 又名 2 的幂)范围内的任何内容都会给我相当的性能(4KB 是“最佳”数字)我见过)。
基本上,您需要一个足够大的缓冲区,这样您就不会不必要地从流中读取数据,但又不能太大而导致回报减少。 如果您的缓冲区太大(〜MB),那么您将增加内存缓存未命中率,这实际上可能会开始降低您的性能。 当然,根据实际硬件(总线速度、缓存大小等),这有很大差异,但我似乎遇到过 4MB 缓冲区比 4KB 缓冲区慢的情况(两种情况都有很长的生命周期,所以 GC 不是一个问题)。
正如乔纳森指出的那样,在尝试过早优化之前测试当前的实现。
My anecdotal experience has been that it really does depend on what you are doing, but typically anything in the range of 1024-4096 bytes (1-4KB a.k.a. power of two) would give me comparable performance (with 4KB being the "best" number I've seen).
Basically, you want a buffer large enough so you are not needlessly reading data from the stream, but not so large you diminish returns. If your buffer is too big (~MBs), then you will increase your memory cache misses, which might actually start to decrease your performance. Of course, this varies a lot based on actual H/W (bus speed, cache size, etc), but I've seem cases where a 4MB buffer was slower than the 4KB buffer (both cases had long lifetimes, so GC was not an issue).
As Jonathan notes, test your current implementation before trying premature optimizations.
实际上,当缓冲区大小太小时,我遇到了问题。 我已经对其进行了测试并验证了缓冲区大小不应设置为较小的值。 在我的示例中,我将其设置为 2048,与 firefox one 相比,下载变得非常慢(firefox one 也没有下载分段,与我的相同)。
当我将其设置为大尺寸 409600 后,下载速度要快得多,我认为额外的调用会产生开销或导致下载速度变慢。 也许在网络层面,缓冲区超出了您的缓冲区大小,因此 TCP 需要要求再次重新发送数据包? (只是猜测,因为我不知道 TCP 是如何工作的),但是较小的缓冲区大小肯定会减慢我的下载速度。 我已经通过使用 firefox 默认下载(没有添加和分段)运行并使用我的类对其进行了测试,两者相差太大。
现在它快得多,每次循环时,它都会读取大约 200000 字节(200Kb),因为这里的连接速度很快,但是在我运行两个线程之后,它会慢得多,可能需要与另一个线程共享。
Actually I am having issue when the buffer size is too small. I have tested it and VERIFIED it that buffer size should not be set to be small value. In my example I set it to 2048 and the download is becoming VERY SLOW comparing to firefox one (firefox one is without download segmentation too, the same as mine).
And After I set it to a big size 409600, the download is MUCH FASTER, I think that extra call will cost overhead or such that makes the download slow. Perhaps in the network level, the buffer is exceeding your buffer size, so the TCP need to ask to resend the package again? (Just a guess, as I don't know how TCP works), however small buffer size is definitely slowing down my download. I have tested it by running using firefox default download (without add on and segmenetation) and using my class, both are far too different.
Now it is much faster, every time it loops, it will read about 200000 bytes (200Kb) as the connection here is quiet fast, but after I am running two threads, it will much slower, probably need to share with another thread.