2011-07-05 79 views
5

在.NET中執行文件IO時,似乎有95%的示例使用4096字節的緩衝區。關於緩衝區長度,4kb有什麼特別之處?或者它僅僅是一個習慣像在for循環中使用我的索引?4kb的緩衝區長度有什麼特別之處?

+1

[Optimum file buffer read size?](http://stackoverflow.com/questions/1552107/optimum-file-buffer-read-size) –

回答

7

這是因爲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(); 
    } 
} 
+0

啊,我明白了。認爲這可能是這樣的。有沒有什麼辦法可以在運行時確定磁盤的簇大小以適應磁盤的大小? – sheikhjabootie

+0

我不知道使用託管代碼獲取羣集大小的方法,但可以使用P/Invoke調用Win32 API函數'GetDiskFreeSpace',該函數將返回獲取羣集大小所需的信息。如果需要,我可以在今天晚些時候提供樣品,當時我在我的開發機器上。 –

+0

@CodingHero,我添加了一個快速樣本來確定羣集大小。說實話,我不會走這麼遠來嘗試優化緩衝區大小,我寧願去用4K或8K之類的東西做一些性能測試,看看我需要什麼樣的性能來完成它。只有當我正在處理受限於內存的設備並且我無法承受4K緩衝區時,我纔會減少4K。 –

0

我的猜測是,這是關係到OS文件塊的大小---的Windows .NET上。

+0

想象一下,兩個南非人從世界的另一端回答同樣的問題。 –

+0

我現在只看到這個評論:) ---是的,我們無處不在! –

1

幾個因素:

  • 更多的,往往不是4K是一個磁盤驅動器上的簇大小
  • 4K在Windows上最常用的頁面大小,所以在4K操作系統可以內存映射文件塊
  • 4K頁面通常可以從驅動器傳輸到操作系統到用戶進程而不被複制
  • Windows使用4K緩衝區將文件緩存到RAM中。

更重要的是在很多人都使用4K作爲因上述的緩衝區長度,因此很多IO和OS代碼爲4K緩衝區優化年!