【发布时间】:2011-07-05 05:49:51
【问题描述】:
在 .NET 中执行文件 IO 时,我看到的 95% 的示例似乎使用 4096 字节缓冲区。 4kb 的缓冲区长度有什么特别之处?还是只是一种约定,例如在 for 循环中使用 i 作为索引?
【问题讨论】:
在 .NET 中执行文件 IO 时,我看到的 95% 的示例似乎使用 4096 字节缓冲区。 4kb 的缓冲区长度有什么特别之处?还是只是一种约定,例如在 for 循环中使用 i 作为索引?
【问题讨论】:
这是因为 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();
}
}
【讨论】:
GetDiskFreeSpace,它会返回您获取集群大小所需的信息.如果需要,我可以在今天晚些时候在我的开发机器上提供一个示例。
几个因素:
最重要的是,由于上述原因,多年来很多人都使用 4K 作为缓冲区长度,因此很多 IO 和 OS 代码都针对 4K 缓冲区进行了优化!
【讨论】:
我的猜测是它与操作系统文件块大小有关 --- Windows on .NET。
【讨论】:
我的猜测……我的答案是正确的,而其他人则不然——历史上的深度不够。 知道这是一个老问题,更重要的是要提一下,在什么时候,什么时候性能不仅仅是编程风格的问题。
二进制大小(4096、8192 或有时为 1024)来自您可以看到 CPU 与外围芯片的连接的时间。 抱歉听起来很老,但这对于回答您的问题至关重要。 程序中的缓冲区必须转移到外围设备,因此它需要地址线(今天需要其他想法),并且此地址线是二进制有界的。 芯片获取所需(和需要)内存的信息来保存它。该内存是由二进制地址确定的(!)...-您找不到 23gb 芯片。 1k、2k、4k 或(最终)8k 是一个很好的价值(在过去)。
如何在移出一个字节的同时移出一个需要 8k 的缓冲区(以某种方式)。这就是我们有缓冲区的原因!
硬盘有这个(集群)大小并不是缓冲区大小的原因——相反的事实——硬盘的组织遵循上述系统。
【讨论】: