何时使用 .NET BufferedStream 类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/492283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use .NET BufferedStream class?
提问by Jader Dias
The MSDN sitestates:
在MSDN网站的状态:
A buffer is a block of bytes in memory used to cache data, thereby reducing the number of calls to the operating system. Buffers improve read and write performance. A buffer can be used for either reading or writing, but never both simultaneously. The Read and Write methods of BufferedStream automatically maintain the buffer.
缓冲区是内存中用于缓存数据的字节块,从而减少对操作系统的调用次数。缓冲区提高了读写性能。缓冲区可用于读取或写入,但不能同时用于两者。BufferedStream 的 Read 和 Write 方法自动维护缓冲区。
Should I use this class in every possible occasion?
我应该在所有可能的场合使用这个类吗?
采纳答案by hacker
The following is some text from an online course I am taking:
以下是我正在参加的在线课程中的一些文字:
The BufferedStream class is a concrete class that extends the Stream class and is used to provide an additional memory buffer to another type of stream, both synchronously and asynchronously. The BufferedStream class must be configured to either read or write when an instance of the class is created, but the BufferedStream cannot be configured to perform both the tasks at the same time.
Microsoft improved the performance of all streams in the .NET Framework by including a built-in buffer. The performance noticeably improved by applying a BufferedStream to existing streams, such as a FileStream or MemoryStream. Applying a BufferedStream to an existing .NET Framework stream results in a double buffer.
The most common application of the BufferedStream class is in custom stream classes that do not include a built-in buffer.
BufferedStream 类是一个具体类,它扩展了 Stream 类,用于同步和异步地为另一种类型的流提供额外的内存缓冲区。在创建类的实例时,必须将 BufferedStream 类配置为读取或写入,但不能将 BufferedStream 配置为同时执行这两个任务。
Microsoft 通过包含内置缓冲区提高了 .NET Framework 中所有流的性能。通过将 BufferedStream 应用于现有流(例如 FileStream 或 MemoryStream),性能显着提高。将 BufferedStream 应用于现有的 .NET Framework 流会导致双缓冲区。
BufferedStream 类最常见的应用是在不包含内置缓冲区的自定义流类中。
回答by dewald
According to Brad Abrams, almost never: link
根据布拉德艾布拉姆斯的说法,几乎从不:链接
No, there is zero benefit from wrapping a BufferedStream around a FileStream. We copied BufferedStream's buffering logic into FileStream about 4 years ago to encourage better default performance... In fact, I don't think there are any Streams in the .NET Framework that require it, but it might be needed by custom Stream implementations if they do not do buffering by default.
不,将 BufferedStream 包装在 FileStream 周围的好处为零。大约 4 年前,我们将 BufferedStream 的缓冲逻辑复制到 FileStream 中,以鼓励更好的默认性能……事实上,我认为 .NET Framework 中没有任何 Streams 需要它,但如果自定义 Stream 实现可能需要它默认情况下,它们不进行缓冲。
回答by idn
Best case I know of is when BinaryFormatter serialize/deserialize directly from NetworkStream. Use of BufferedStream inbetween increase performance tenfold.
我所知道的最好的情况是 BinaryFormatter 直接从 NetworkStream 序列化/反序列化。在两者之间使用 BufferedStream 可将性能提高十倍。
回答by GvS
The normal file I/O streams are already buffered by using a StreamReader/StreamWriter.
普通的文件 I/O 流已经使用 StreamReader/StreamWriter 进行了缓冲。
Since read/write operations on streams, normally use the Read/Write methods that take a byte array, you will naturally provide some buffering yourself.
由于对流的读/写操作,通常使用带字节数组的读/写方法,您自然会自己提供一些缓冲。
If you use very small arrays, or use WriteByte, you might get better performance by using a BufferedStream in between.
如果您使用非常小的数组,或使用 WriteByte,您可能会通过在两者之间使用 BufferedStream 获得更好的性能。
回答by Anton Gogolev
What must beused in every possible occasion is common sense. There's no use in utilizing this class when reading-writing to-from a MemoryStream, but it might be quite useful when doing network or disk IO (if Streams for these subsystems do not do buffering on their own).
什么是必须要在一切可能的场合使用的是常识。在从 MemoryStream 读写时利用这个类是没有用的,但是在进行网络或磁盘 IO 时它可能非常有用(如果这些子系统的 Streams 不自己做缓冲)。
回答by Tono Nam
Late answer but going to answer it anyways. If you understand how it works you can understand why it makes no sense to use in some cases and why it makes sense to not use in other cases.
迟到的答案,但无论如何都会回答。如果您了解它的工作原理,您就可以理解为什么在某些情况下使用没有意义,而在其他情况下不使用是有意义的。
To proof this I am using StreamWrapperclass. Only use this class to see how many times you hit a breakpoint! Place breakpoints all over this class. Our goal is to see how many times we call the Write, Read, and other methods.
为了证明这一点,我正在使用StreamWrapper类。只使用这个类来查看你打断点的次数!在整个类中放置断点。我们的目标是查看我们调用 Write、Read 和其他方法的次数。
// This class is only used for demo purposes. Place a breakpoint on all parts
class StreamWrapper : Stream
{
Stream stream;
public StreamWrapper(Stream s)
{
stream = s;
}
public override bool CanRead => stream.CanRead;
public override bool CanSeek => stream.CanSeek;
public override bool CanWrite => stream.CanWrite;
public override long Length => stream.Length;
public override long Position { get => stream.Position; set => stream.Position = value; }
public override void Flush()
{
stream.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return stream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return stream.Seek(offset,origin);
}
public override void SetLength(long value)
{
stream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
stream.Write(buffer, offset, count);
}
}
Now that you have that wrapper class that is basically a wrapper to an existing strem you may do the following tests:
既然您拥有基本上是现有流的包装器的包装器类,您可以执行以下测试:
Example Writting:
示例写作:
// in real life you want this to be larger.
int bufferSize = 8;
// Use BufferedStream to buffer writes to a MemoryStream.
using (var memory_test = new StreamWrapper(new MemoryStream()))
using (BufferedStream stream = new BufferedStream(memory_test, bufferSize))
{
// all this will only send one write to memory_test!
stream.Write(new byte[] { 1, 2 });
stream.Write(new byte[] { 1, 2 });
stream.Write(new byte[] { 1, 2 });
stream.Write(new byte[] { 1, 2 });
// BREAKPOINT ONLY HITS ONE TIME
// All this will also send only one write to memory_test
for (int i = 0; i < 8; i++)
stream.WriteByte(5);
// BREAKPOINT ONLY HITS ONE TIME AGAIN INSTAD OF 8
// this will send one write to memory_test. Writes of more than 8 bytes can happen!
stream.Write(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 });
// ALL THIS WILL SEND ONE WRITE AGAIN
}
Example reading:
示例阅读:
// example reading
{
// create stream with some data in it that we will be reading
var ms = new MemoryStream();
{
// Write 256 bytes
for (int i = 0; i <= byte.MaxValue; i++)
{
ms.WriteByte((byte)i);
}
ms.Position = 0;
}
// Use BufferedStream to buffer writes to a MemoryStream.
using (var memory_test = new StreamWrapper(ms))
{
using (BufferedStream stream = new BufferedStream(memory_test, 8))
{
// note I do not care about the output of each read for demo breakpoint. On real life you will store that output
// for now we only care how many times we hit the breakpoint because on real life that could be a slow/expensive
// operation such as opening a file for writing and you want to do those as few as possible.
// hit breakpoint only one time with all this reads
stream.ReadByte();
stream.ReadByte();
stream.ReadByte();
stream.ReadByte();
stream.ReadByte();
stream.ReadByte();
stream.ReadByte();
stream.ReadByte();
// hit breakpoint only one time with all this reads
stream.Read(new byte[2] );
stream.Read(new byte[2] );
stream.Read(new byte[2] );
stream.Read(new byte[2] );
// hit breakpoint only one time even though it is larger than our buffer size 8
// our goal is to hit the breakpoint as fewest time as possible because in real life
// this could be slow/expensive operations
stream.Read(new byte[1024] );
}
}
}
If this where to be write operations to a file for example performance could increase by ensuring you always write at least 8 bytes instead of 1 at a time. In real life you want this number to be about 4 KB
如果这是对文件的写入操作,例如性能可以通过确保始终写入至少 8 个字节而不是一次写入 1 个字节来提高。在现实生活中,您希望这个数字大约为 4 KB

