標籤:

為什麼拷大文件會越來越慢,開始是10Mb/S,最後只有3~4Mb/S?


拷貝文件在應用層次上的過程是:

把源文件讀到內存里,把內存里的數據寫到目標文件里。

要理解為什麼越來越慢,就要從這兩步來分析。

先說把源文件讀到內存里這一步,從用戶層面來看,用來做數據中轉的內存是固定大小的,所以不存在快慢的問題。

但在文件系統驅動一層,則不是這樣的。當你用Windows資源管理器打開一個文件夾,或者在Linux里cd到某個路徑的時候,這個文件夾里很多信息可能已經被讀到內存里了,這種技術簡單的說,是「預讀」,當然實際情況比較複雜,不同的文件系統的操作策略是不同的,但基本上一個實時就是,在你準備拷貝這個文件之前,這個文件的部分信息已經在內存里了。這些信息里,最重要的就包括文件的索引塊信息。索引塊是用來標識你的文件在磁碟上如何分布的,如果把磁碟理解成一個帶有很多格子的本子,那麼索引塊就是用來記錄哪些格子屬於哪些文件的。要訪問文件,索引塊是必須要訪問的。

而對於一個大文件來說,其索引也是不小的,當你剛開始拷貝文件的時候,因為有「預讀」存在,所以此時的拷貝有很多磁碟訪問操作已經可以省略,直接從內存里拿就可以了,速度是很快的。但隨著你操作的繼續,「預讀」被用完了,那麼只能直接訪問磁碟,此時讀文件的速度就下降了,這是拷貝大文件越來越慢的一個原因之一。

再說把內存里的數據寫到目標文件里這一步。

一般來說文件系統只有預讀,但沒有「預寫」,但是設備本身和設備驅動都是有「緩存」概念的,隨便到網上查一個硬碟的信息,都會有「XXM緩存」,這緩存有些就是用來做寫操作的,主機上發送過來的數據,先放到緩存里,然後慢慢寫,緩存的速度基本和內存速度相當,所以一開始緩存沒滿的時候,寫的是很快的,但是此時數據未必真的就寫到磁碟上。但是隨後,緩存滿了,速度就下降了。

緩存也是導致寫速度慢慢下降的一個原因之一。

其實,寫文件也是要伴隨著讀操作的,因為如果要寫入數據,先要讀一下磁碟的索引塊,確定哪些區域是空白的,不然的話就會把舊數據寫壞。隨著寫的數據增多,讀的東西就要更多,另外像ext和NTFS這種,都有機制保證掉電時文件系統不會被嚴重損壞,原理就是Copy On Write機制,就是我要寫某個數據的時候,我先複製一份,這樣即使突然斷電,數據的原始內容是可以恢復的。可是這樣的話,麻煩就來了,如果寫的東西很多,Copy的東西就更多,Copy也要消耗內存,最終的結果就是內存越占越多,也加劇了寫操作時的速度下降。

Copy On Write和寫文件時伴隨的讀操作,也是速度慢慢下降的原因之一。

以上三種原因導致了寫文件速度越來越慢。

同時,有些文件系統(比如NTFS),其索引塊的建立是有延遲性的,一般是先寫一些數據,再建立對應的索引,那麼可能剛開始寫數據的時候,不需要建立索引塊(或者索引塊建立在內存里),但後來除了要寫數據,還要寫索引,寫的速度就下降了。甚至有些大文件的索引是最後才建立的,這種情況下會出現文件的最後一小部分(比如最後1M)會寫的特別慢,因為此時在更新文件索引信息。


因為硬碟會發熱,發熱了速度會降低,降溫將會使速度提升,以前用移動硬碟的經驗。


推薦閱讀:

linux下面如何選擇合適的文件系統?
跟著一個喜歡做理論的導師是怎樣的體驗?

TAG:文件系統 |