知道为什么引用流的Position属性会戏剧性地增加IO时间吗?
的执行时间
sw.Restart();
fs = new FileStream("tmp", FileMode.Open);
var br = new BinaryReader(fs);
for (int i = 0; i < n; i++)
{
fs.Position+=0; //Should be a NOOP
a[i] = br.ReadDouble();
}
Debug.Write("n");
Debug.Write(sw.ElapsedMilliseconds.ToString());
Debug.Write("n");
fs.Close();
sw.Stop();
Debug.Write(a[0].ToString() + "n");
Debug.Write(a[n - 1].ToString() + "n");
比没有"fs.Position+=0;"的等效循环慢约100倍。通常,使用Seek(或操纵Position属性)的目的是在不需要文件中的所有数据时加快速度。但是,例如,如果你只需要文件中的每一秒值,那么读取整个文件并丢弃你不需要的数据可能比通过移动Stream跳过文件中的每秒值快得多。位置
您正在做两件事:
- 获取职位
- 设置
完全有可能每个都与底层Win32 API执行直接交互,而通常情况下,由于缓冲,您可以读取相当多的数据,而不必与本机代码进行互操作。
我对它更糟的程度有点惊讶,但我并不惊讶它更糟。我认为你应该做单独的测试,找出哪一个更有效——读还是写。因此,编写类似的代码,要么只读,要么只写。请注意,这应该会影响您稍后编写的代码,但它可能会进一步满足您的好奇心。
你也可以试试
fs.Seek(0, SeekOrigin.Current);
这更有可能被忽略为真正的反对。但即便如此,使用fs.Seek(1, SeekOrigin.Current)
跳过单个字节可能会再次变得昂贵。
来自反射器:
public override long Position {
[SecuritySafeCritical]
get {
if (this._handle.IsClosed) {
__Error.FileNotOpen();
}
if (!this.CanSeek) {
__Error.SeekNotSupported();
}
if (this._exposedHandle) {
this.VerifyOSHandlePosition();
}
return this._pos + (long)(this._readPos - this._readLen + this._writePos);
}
set {
if (value < 0L) {
throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
if (this._writePos > 0) {
this.FlushWrite(false);
}
this._readPos = 0;
this._readLen = 0;
this.Seek(value, SeekOrigin.Begin);
}
}
(不言自明)-基本上,每个集合都会导致刷新,并且没有检查您是否为该位置设置了相同的值;如果您对FileStream不满意,请制作自己的流代理,以便更优雅地处理位置更新:)