【问题标题】:What's so special about 4kb for a buffer length?4kb 的缓冲区长度有什么特别之处?
【发布时间】:2011-07-05 05:49:51
【问题描述】:

在 .NET 中执行文件 IO 时,我看到的 95% 的示例似乎使用 4096 字节缓冲区。 4kb 的缓冲区长度有什么特别之处?还是只是一种约定,例如在 for 循环中使用 i 作为索引?

【问题讨论】:

标签: .net io buffer


【解决方案1】:

这是因为 4K 是最大 16TB 磁盘的默认集群大小。因此,在选择缓冲区大小时,以集群大小的倍数分配缓冲区是有意义的。

簇是文件的最小分配单位,所以如果一个文件只包含 1 个字节,它将消耗 4K 的物理磁盘空间。一个 5K 的文件将导致一个 8K 的分配。


更新:添加了用于获取驱动器集群大小的代码示例
using System;
using System.Runtime.InteropServices;

class Program
{
  [DllImport("kernel32", SetLastError=true)]
  [return: MarshalAs(UnmanagedType.Bool)]
  static extern bool GetDiskFreeSpace(
    string rootPathName,
    out int sectorsPerCluster,
    out int bytesPerSector,
    out int numberOfFreeClusters,
    out int totalNumberOfClusters);

  static void Main(string[] args)
  {
    int sectorsPerCluster;
    int bytesPerSector;
    int numberOfFreeClusters;
    int totalNumberOfClusters;

    if (GetDiskFreeSpace("C:\\", 
          out sectorsPerCluster, 
          out bytesPerSector, 
          out numberOfFreeClusters, 
          out totalNumberOfClusters))
    {        
      Console.WriteLine("Cluster size = {0} bytes", 
        sectorsPerCluster * bytesPerSector);
    }
    else
    {
      Console.WriteLine("GetDiskFreeSpace Failed: {0:x}", 
        Marshal.GetLastWin32Error());
    }

    Console.ReadKey();
  }
}

【讨论】:

  • 啊,我明白了。心想大概就是这样。有没有办法在运行时确定磁盘的集群大小以适应它?
  • 我不知道使用托管代码获取集群大小的方法,但是您可以使用 P/Invoke 调用 Win32 API 函数GetDiskFreeSpace,它会返回您获取集群大小所需的信息.如果需要,我可以在今天晚些时候在我的开发机器上提供一个示例。
  • @CodingHero,我添加了一个快速示例来确定集群大小。老实说,我不会走这么远来尝试优化缓冲区大小,我宁愿用 4K 或 8K 之类的东西做一些性能测试,看看什么能提供我需要的性能并完成它。只有在我使用内存受限且无法负担 4K 缓冲区的设备上工作时,我才会低于 4K。
【解决方案2】:

几个因素:

  • 通常,4K 是磁盘驱动器上的簇大小
  • 4K 是 Windows 上最常见的页面大小,因此操作系统可以将文件内存映射为 4K 块
  • 通常可以将 4K 页面从驱动器传输到操作系统到用户进程而无需复制
  • Windows 使用 4K 缓冲区在 RAM 中缓存文件。

最重要的是,由于上述原因,多年来很多人都使用 4K 作为缓冲区长度,因此很多 IO 和 OS 代码都针对 4K 缓冲区进行了优化!

【讨论】:

    【解决方案3】:

    我的猜测是它与操作系统文件块大小有关 --- Windows on .NET。

    【讨论】:

    • 想象一下,来自世界两端的两个南非人在 SO 上回答同一个问题。
    • 我现在才看到这条评论 :) --- 是的,我们无处不在!
    【解决方案4】:

    我的猜测……我的答案是正确的,而其他人则不然——历史上的深度不够。 知道这是一个老问题,更重要的是要提一下,在什么时候,什么时候性能不仅仅是编程风格的问题。

    二进制大小(4096、8192 或有时为 1024)来自您可以看到 CPU 与外围芯片的连接的时间。 抱歉听起来很老,但这对于回答您的问题至关重要。 程序中的缓冲区必须转移到外围设备,因此它需要地址线(今天需要其他想法),并且此地址线是二进制有界的。 芯片获取所需(和需要)内存的信息来保存它。该内存是由二进制地址确定的(!)...-您找不到 23gb 芯片。 1k、2k、4k 或(最终)8k 是一个很好的价值(在过去)。

    如何在移出一个字节的同时移出一个需要 8k 的缓冲区(以某种方式)。这就是我们有缓冲区的原因!

    硬盘有这个(集群)大小并不是缓冲区大小的原因——相反的事实——硬盘的组织遵循上述系统。

    【讨论】:

      猜你喜欢
      • 2014-10-10
      • 1970-01-01
      • 1970-01-01
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多