浅谈BufferedStream与FileStream的效率
最近使用FileStream做了一些文件操作,查找到MSDN
Referenced from 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 can be composed around certain types of streams. It provides implementations for reading and writing bytes to an underlying data source or repository. Use BinaryReader and BinaryWriter for reading and writing other data types. BufferedStream is designed to prevent the buffer from slowing down input and output when the buffer is not needed. If you always read and write for sizes greater than the internal buffer size, then BufferedStream might not even allocate the internal buffer. BufferedStream also buffers reads and writes in a shared buffer. It is assumed that you will almost always be doing a series of reads or writes, but rarely alternate between the two of them.'
这上面说BufferedStream内部缓存了一个Buffer,这个buffer提升了读写的效率,我突发奇想试了试这个效率对比。以下是测试代码:
1 static void Main(string[] args)
2 {
3 string filePath = @"c:\test.dat";
4 using (FileStream fStream = new FileStream(filePath, FileMode.OpenOrCreate))
5 {
6 BufferedStream bStream = new BufferedStream(fStream, 10000 );
7
8 byte[] dataArray = new byte[1000];
9 //Init data array
10 new Random().NextBytes(dataArray);
11
12 DateTime beginTime = DateTime.Now;
13 FileStreamWrite(fStream, dataArray, 10240);
14 Console.WriteLine((beginTime - DateTime.Now).TotalMilliseconds.ToString("F1"));
15
16 beginTime = DateTime.Now;
17 BufferedStreamWrite(bStream, dataArray, 10240);
18 Console.WriteLine((beginTime - DateTime.Now).TotalMilliseconds.ToString("F1"));
19 }
20 }
21
22 public static void FileStreamWrite(FileStream fStream, byte[] buffer, int count)
23 {
24 for (int j = 0; j < count; j++)
25 {
26 fStream.Write(buffer, 0, buffer.Length);
27 }
28 }
29
30 public static void BufferedStreamWrite(BufferedStream bStream, byte[] buffer, int count)
31 {
32 for (int j = 0; j < count; j++)
33 {
34 bStream.Write(buffer, 0, buffer.Length);
35 }
36 }
运行代码进行测试,效果不错,以下是输出结果:
-20.0 -10.0 Press any key to continue . . .
看得出来,的确是BufferedStream效率高一些,但真的如此吗,任何情况下都是这样的吗?基础工具Reflector登场,查看BufferedStream的Write方法。在其中找到了这样一段代码:
View Code
public override void Write(byte[] array, int offset, int count)
{
if (array == null)
{
throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
}
if (offset < 0)
{
throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
if (count < 0)
{
throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
if ((array.Length - offset) < count)
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
}
if (this._s == null)
{
__Error.StreamIsClosed();
}
if (this._writePos == 0)
{
if (!this._s.CanWrite)
{
__Error.WriteNotSupported();
}
if (this._readPos < this._readLen)
{
this.FlushRead();
}
else
{
this._readPos = 0;
this._readLen = 0;
}
}
if (this._writePos > 0)
{
int num = this._bufferSize - this._writePos;
if (num > 0)
{
if (num > count)
{
num = count;
}
Buffer.InternalBlockCopy(array, offset, this._buffer, this._writePos, num);
this._writePos += num;
if (count == num)
{
return;
}
offset += num;
count -= num;
}
this._s.Write(this._buffer, 0, this._writePos);
this._writePos = 0;
}
if (count >= this._bufferSize)
{
this._s.Write(array, offset, count);
}
else if (count != 0)
{
if (this._buffer == null)
{
this._buffer = new byte[this._bufferSize];
}
Buffer.InternalBlockCopy(array, offset, this._buffer, 0, count);
this._writePos = count;
}
}
代码中可以看出,当BufferedStream的bufferSize小于每次写的Data的length的时候,会额外调用Stream.Write写入剩余的byte,这样操作的效率就会下降。这个只是推测,我接着做了以下测试。还是上述的测试代码,将BufferSize改为10,而DataArray的大小改为1000,运行测试。结果如下:
-18.0 -18.0 Press any key to continue . . .
明显看出速度下降了不少,由此看出,当每次写入数据的大小如果大于buffer的大小,会导致BufferedStream的效率下降,这是bufferedStream的内部实现导致的。
微软的说明说的好,bufferedStream的设计思想就是避免频繁的读写而使用buffer数组导致的系统开销损耗,使用的时候注意初始化BufferStream的大小。不初始化大小的BufferedStream的效率与FileStream几乎一样。以后使用的时候要注意以下。

浙公网安备 33010602011771号