与来自 HttpWebResponse.GetResponseStream() 的流一起使用的最佳缓冲区大小是多少?
在线示例从 256b 到 5Kb 不等。是什么赋予了?我猜缓冲区大小可能是根据情况而定的。如果是这样,在什么情况下使用什么类型的缓冲区大小?
谢谢。
与来自 HttpWebResponse.GetResponseStream() 的流一起使用的最佳缓冲区大小是多少?
在线示例从 256b 到 5Kb 不等。是什么赋予了?我猜缓冲区大小可能是根据情况而定的。如果是这样,在什么情况下使用什么类型的缓冲区大小?
谢谢。
真的,这并不重要。
当然,如果您使用非常小的缓冲区,您可能需要通过层进行一些额外的调用以获取字节(尽管流可能至少会进行一些缓冲——我不知道它的默认值是什么)。当然,如果你使用非常大的缓冲区,你会浪费一些内存并引入一些碎片。由于您显然在这里进行 IO,因此您通过调整缓冲区获得的任何时间都将受 IO 时间的支配。
作为一般规则,我在 2048 (2k) 和 8192 (8k) 之间选择 2 的幂。如果您使用等于或大于 85,000 字节的缓冲区(然后它是一个“大对象”并受不同的 GC 规则约束) ,请确保您知道自己在做什么。
事实上,比缓冲区大小更重要的是你持有它的时间。对于大对象堆之外的对象,GC 非常擅长处理生命周期很短的对象(Gen 0 收集速度很快),或者生命周期很长的对象(Gen 2)。在被释放之前存活到第 1 代或第 2 代的对象相对来说成本更高,而且通常比缓冲区有多大更值得您花时间担心。
最后一点:如果您认为由于使用的缓冲区大小而存在性能问题,请对其进行测试。这不太可能,但谁知道呢,也许你有一个奇怪的操作系统版本、网络硬件和驱动程序版本的融合,在特定大小的缓冲区中有一些奇怪的问题。
我的轶事经验是,它确实取决于你在做什么,但通常在 1024-4096 字节(1-4KB 也就是 2 的幂)范围内的任何东西都会给我相当的性能(4KB 是“最佳”数字我见过)。
基本上,您需要一个足够大的缓冲区,这样您就不会从流中不必要地读取数据,但又不会大到会减少回报。如果您的缓冲区太大(~MBs),那么您将增加您的内存缓存未命中,这实际上可能会开始降低您的性能。当然,这取决于实际的硬件(总线速度、缓存大小等)变化很大,但我似乎有 4MB 缓冲区比 4KB 缓冲区慢的情况(这两种情况都有很长的生命周期,所以 GC 不是一个问题)。
正如 Jonathan 所说,在尝试过早优化之前测试您当前的实现。
实际上,当缓冲区大小太小时我遇到问题。我已经对其进行了测试并验证了缓冲区大小不应设置为较小的值。在我的示例中,我将其设置为 2048,与 firefox 相比,下载变得非常慢(firefox 也没有下载分段,与我的相同)。
在我将它设置为大尺寸 409600 后,下载速度要快得多,我认为额外的调用会产生开销或使下载速度变慢。也许在网络层面,缓冲区超出了你的缓冲区大小,所以 TCP 需要要求重新发送包?(只是一个猜测,因为我不知道 TCP 是如何工作的),但是小缓冲区肯定会减慢我的下载速度。我已经通过使用 firefox 默认下载(没有添加和分段)运行并使用我的类对其进行了测试,两者差别太大了。
现在它更快了,每次循环时,它会读取大约 200000 字节(200Kb),因为这里的连接速度很快,但是在我运行两个线程之后,它会慢很多,可能需要与另一个线程共享。