從磁盤/閃存單元到本地Java變量,單個字節的讀取有很長的路要走。這是一個單字節行進的路徑:
- 磁性板/快閃單元
- 內部硬盤緩衝器
- SATA/IDE總線
- SATA/IDE緩衝器
- PCI/PCI-X公交車
- 計算機的數據總線
- 通過DMA計算機的RAM
- OS Page-cache
- libc的讀緩存,也稱爲用戶空間
fopen()
讀取緩衝
- 本地Java變量
出於性能方面的原因,大多數由OS完成的文件緩衝保持在頁面緩存,存儲最近讀並在RAM上寫入文件內容。
這意味着,從您的Java代碼中每一個讀寫操作是從和你的本地緩存來完成:
FileInputStream fis = new FileInputStream("/home/vz0/F.txt");
// This byte comes from the user space buffer.
int oneByte = fis.read();
一個頁面通常是內存4KB單塊。每個頁面都有一些特殊的標誌和屬性,其中之一就是「髒頁面」,這意味着頁面有一些修改後的數據不會寫入物理介質。
過了一段時間,當操作系統決定將髒數據清理回磁盤時,它會將數據以相反的方向發送。
每當兩種不同過程以相同的文件中寫入數據,所產生的行爲是:
- 不可能,如果文件被鎖定。第二個進程將無法打開文件。
- 未定義,如果在文件的同一區域寫入。
- 預計,如果在文件的不同區域進行操作。
「區域」取決於您的應用程序使用的內部緩衝區大小。例如,在一個兩兆文件,兩個不同的過程可以寫爲:
- 一個上的數據的第一1kB的(0; 1024)。
- 上的數據的最後一個1kB的另一個(2096128; 2097152)只有當本地緩衝器的大小是兩兆字節
緩衝器將發生重疊和數據損壞。在Java上,您可以使用Channel IO來讀取文件,並精確控制內部發生了什麼。
許多事務性數據庫通過發出sync
operation強制一些寫入從本地RAM緩衝區返回到磁盤。所有與單個文件相關的數據都會被刷新到磁盤或閃存單元,從而有效地確保電源故障時不會丟失數據。
最後,memory mapped file是一個內存區域,它使用戶進程可以直接從頁面緩存中讀寫,並繞過用戶空間緩衝。
頁面緩存系統對多任務protected mode操作系統的性能至關重要,而且每個現代操作系統(Windows NT向上,Linux,MacOS,* BSD)都支持所有這些功能。
來源
2011-02-02 03:00:26
vz0