Jad*_*ias 52 .net performance buffer
在MSDN网站上指出:
缓冲区是内存中用于缓存数据的字节块,从而减少了对操作系统的调用次数.缓冲区可提高读写性能.缓冲区可用于读取或写入,但不能同时使用.BufferedStream的Read和Write方法自动维护缓冲区.
我应该在每个可能的场合使用这门课吗?
dew*_*ald 70
据布拉德艾布拉姆斯说,几乎从来没有:链接
不,围绕FileStream包装BufferedStream没有任何好处.我们大约4年前将BufferedStream的缓冲逻辑复制到FileStream中以鼓励更好的默认性能......事实上,我认为.NET Framework中没有任何Streams需要它,但是自定义Stream实现可能需要它.他们默认不做缓冲.
hac*_*ker 20
以下是我正在参加的在线课程的一些文字:
BufferedStream类是一个扩展Stream类的具体类,用于为其他类型的流提供额外的内存缓冲区,包括同步和异步.必须将BufferedStream类配置为在创建类的实例时读取或写入,但不能将BufferedStream配置为同时执行这两个任务.
Microsoft通过包含内置缓冲区来提高.NET Framework中所有流的性能.通过将BufferedStream应用于现有流(例如FileStream或MemoryStream),性能得到显着提高.将BufferedStream应用于现有.NET Framework流会产生双缓冲区.
BufferedStream类的最常见应用是在不包含内置缓冲区的自定义流类中.
迟到的答案,但无论如何都会回答。如果您了解它的工作原理,您就可以理解为什么在某些情况下使用它没有意义,以及为什么在其他情况下不使用它是有意义的。
为了证明这一点,我正在使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在您已经拥有了基本上是现有 strem 的包装器的包装器类,您可以执行以下测试:
写作示例:
// 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
}
Run Code Online (Sandbox Code Playgroud)
示例阅读:
// 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] );
}
}
}
Run Code Online (Sandbox Code Playgroud)
例如,如果要对文件进行写入操作,则可以通过确保每次至少写入 8 个字节而不是 1 个字节来提高性能。在现实生活中,您希望这个数字约为 4 KB
普通文件 I/O 流已使用 StreamReader/StreamWriter 进行缓冲。
由于流上的读/写操作通常使用采用字节数组的读/写方法,因此您自然会自己提供一些缓冲。
如果您使用非常小的数组或使用 WriteByte,则通过在其间使用 BufferedStream 可能会获得更好的性能。