引用流.位置大大增加了执行时间



知道为什么引用流的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不满意,请制作自己的流代理,以便更优雅地处理位置更新:)

最新更新