任何想法为什么引用流的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.Position来跳过文件中的每一秒值
答案 0 :(得分:4)
你正在做两件事:
完全有可能每个执行与底层Win32 API的直接交互,而通常您可以读取相当数量的数据而无需与本机代码互操作,因为缓冲
我对它的恶化程度感到有些惊讶,但我并不感到惊讶 更糟糕。我认为值得你做一些单独的测试,找出哪个更有效 - 读或写。因此,编写类似的代码,只是读取或只是写入。请注意,这应该会影响您稍后编写的代码,但它可能会进一步满足您的好奇心。
您也可以尝试
fs.Seek(0, SeekOrigin.Current);
......作为一个真正的无操作者,它更容易被忽视。但即便如此,使用fs.Seek(1, SeekOrigin.Current)
跳过单个字节可能会再次成本高昂。
答案 1 :(得分:1)
来自反射器:
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不满意,请创建自己的流代理,以更优雅地处理位置更新:)