日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

磁盘IO的总结

發布時間:2023/11/27 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 磁盘IO的总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://simpleframework.net/blog/v/8486.html

1. 完全隨機寫還是跳躍,5倍的性能差距!

全隨機寫無疑是最慢的寫入方式,在logic dump測試中很驚訝的發現,將200M的內存數據隨 機的寫入到100G的磁盤數據里面,竟然要2個小時之多。原因就是雖然只有200M的數據,但實際上卻是200萬次隨機寫,根據測試,在2850機器上, 這樣完全的隨機寫,r/s 大約在150~350之間,在180機器上,r/s難以達到250,這樣計算,難怪需要2~3個小時之久。

如何改進這種單線程隨機寫慢的問題呢。一種方法就是盡量將完全隨機寫變成有序的跳躍隨機寫。實現方式,可以是簡單的在內存中緩存一段時間,然后排序,使得在 寫盤的時候,不是完全隨機的,而是使得磁盤磁頭的移動只向一個方向。根據測試,再一次讓我震驚,簡單的先在內存中排序,竟然直接使得寫盤時間縮短到1645秒,磁盤的r/s也因此提升到1000以上。寫盤的速度,一下子提高了5倍。

一個需要注意的地方,這種跳躍寫對性能的提升,來至與磁頭的單方向移動,它非常容易受其他因素的影響。測試中,上面提到的測試是只寫block文件, 但如果在每個tid的處理中再增加一個寫index的小文件。雖然如果只寫index小文件,所用時間幾乎可以忽略,但如果夾雜在寫block文件中間的 話,對整體的寫性能可能影響巨大,因為他可能使得磁盤的磁頭需要這兩個地方來回跑。根據測試,如果只寫index文件,只需要300s就可以寫完所有 200萬個tid,單如果將寫索引和寫block放在一起,總時間就遠大于分別寫這兩部分的時間的和。針對這種情況,一種解決方案就是就不要將小數據量的數據實時的刷盤,使用應用層的cache來緩存小數據量的index,這樣就可以消除對寫block文件的影響。

從原理上解釋上面的表象,一般來說,硬盤讀取數據的過程是這樣的,首先是將磁頭移動到磁盤上數據所在的區域,然后才能進行讀取工作。磁頭移動的過程又可以 分解為兩個步驟,其一是移動磁頭到指定的磁道,也就是尋道,這是一個在磁盤盤片徑向上移動的步驟,花費的時間被稱為“尋道時間”;其二就是旋轉盤片到相應 扇區,花費的時間被稱為“潛伏時間”(也被稱為延遲)。那么也就是說在硬盤上讀取數據之前,做準備工作上需要花的時間主要就是“尋道時間”和“潛伏時間” 的總和。真正的數據讀取時間,是由讀取數據大小和磁盤密度、磁盤轉速決定的固定值,在應用層沒有辦法改變,但應用層缺可以通過改變對磁盤的訪問模式來減少“尋道時間”和“潛伏時間”, 我們上面提到的在應用層使用cache然后排序的方式,無疑就是縮短了磁盤的尋址時間。由于磁頭是物理設備,也很容易理解,為什么中間插入對其他小文件的讀寫會導致速度變慢很多。

建議:盡量避免完全的隨機寫,在 不能使用多線處理的時候,盡量使用應用層cache,確保寫盤時盡量有順序性。對于小數據量的其他文件,可以一直保存在應用層cache里面,避免對其他大數據量的數據寫入產生影響。

2. 多線程隨機讀、處理速度、響應時間

多線程隨機讀的處理速度可以達到單線程隨機讀的10倍以上,但同上也帶來了響應時間的增大。測試結論如下:(每個線程盡量讀)

結論標明增加線程數,可以有效的提升程序整體的io處理速度。但同時,也使得每個io請求的響應時間上升很多。

從底層的實現上解釋這個現象:應用層的io請求在內核態會加入到io請求隊列里面。內核在處理io請求的時候,并不是簡單的先到先處理,而是根據磁盤的特 性,使用某種電梯算法,在處理完一個io請求后,會優先處理最臨近的io請求。這樣可以有效的減少磁盤的尋道時間,從而提升了系統整體的io處理速度。但對于每一個io請求來看,由于可能需要在隊列里面等待,所以響應時間會有所提升。

響應時間上升,應該主要是由于我們測試的時候采用每個線程都盡量讀的方式。在實際的應用中,我們的程序都沒有達到這種壓力。所以,在io成為瓶頸的程序里面,應該盡量使用多線程并行處理不同的請求。對于線程數的選擇,還需要通過性能測試來衡量。

3. 是否使用direct io

首先看測試結論:

可見在小數據量下非dio方式更快,但隨著數據量增大,dio方式更快,分界線在50G左右。(注,測試基于: 線程數:50,每次讀操作讀出:4K, 機器:del 180, 內存:機器總內存8G,使用其他程序占用3G,剩余5G左右, 其他情況可能有不同的分界線。)

4. 系統緩存

4.1. 系統緩存相關的幾個內核參數:
1. /proc/sys/vm/dirty_background_ratio
該文件表示臟數據到達系統整體內存的百分比,此時觸發pdflush進程把臟數據寫回磁盤。
缺省設置:10

2. /proc/sys/vm/dirty_expire_centisecs
該文件表示如果臟數據在內存中駐留時間超過該值,pdflush進程在下一次將把這些數據寫回磁盤。
缺省設置:3000(1/100秒)

3. /proc/sys/vm/dirty_ratio
該文件表示如果進程產生的臟數據到達系統整體內存的百分比,此時進程自行把臟數據寫回磁盤。
缺省設置:40

4. /proc/sys/vm/dirty_writeback_centisecs
該文件表示pdflush進程周期性間隔多久把臟數據寫回磁盤。
缺省設置:500(1/100秒)

4.2. 系統一般在下面三種情況下回寫dirty頁:

1. 定時方式: 定時回寫是基于這樣的原則:/proc/sys/vm/dirty_writeback_centisecs的值表示多長時間會啟動回寫線程,由這個定時 器啟動的回寫線程只回寫在內存中為dirty時間超過(/proc/sys/vm/didirty_expire_centisecs / 100)秒的頁(這個值默認是3000,也就是30秒),一般情況下dirty_writeback_centisecs的值是500,也就是5秒,所以 默認情況下系統會5秒鐘啟動一次回寫線程,把dirty時間超過30秒的頁回寫,要注意的是,這種方式啟動的回寫線程只回寫超時的dirty頁,不會回寫 沒超時的dirty頁,可以通過修改/proc中的這兩個值,細節查看內核函數wb_kupdate。

2. 內存不足的時候: 這時并不將所有的dirty頁寫到磁盤,而是每次寫大概1024個頁面,直到空閑頁面滿足需求為止

3. 寫操作時發現臟頁超過一定比例: 當臟頁占系統內存的比例超過/proc/sys/vm/dirty_background_ratio 的時候,write系統調用會喚醒pdflush回寫dirty page,直到臟頁比例低于/proc/sys/vm/dirty_background_ratio,但write系統調用不會被阻塞,立即返回.當臟 頁占系統內存的比例超/proc/sys/vm/dirty_ratio的時候, write系統調用會被被阻塞,主動回寫dirty page,直到臟頁比例低于/proc/sys/vm/dirty_ratio

4.3. pb項目中的感觸:
1,如果寫入量巨大,不能期待系統緩存的自動回刷機制,最好采用應用層調用fsync或者sync。如果寫入量大,甚至超過了系統緩存自動刷回的速 度,就有可能導致系統的臟頁率超過/proc/sys/vm/dirty_ratio, 這個時候,系統就會阻塞后續的寫操作,這個阻塞有可能有5分鐘之久,是我們應用無法承受的。因此,一種建議的方式是在應用層,在合適的時機調用 fsync。

2,對于關鍵性能,最好不要依賴于系統cache的作用,如果對性能的要求比較高,最好在應用層自己實現cache,因為系統cache受外界影響太大,說不定什么時候,系統cache就被沖走了。

3,在logic設計中,發現一種需求使用系統cache實現非常合適,對于logic中的高樓貼,在應用層cache實現非常復雜,而其數量又非常 少,這部分請求,可以依賴于系統cache發揮作用,但需要和應用層cache相配合,應用層cache可以cache住絕大部分的非高樓貼的請求,做到 這一點后,整個程序對系統的io就主要在高樓貼這部分了。這種情況下,系統cache可以做到很好的效果。

5. 磁盤預讀

關于預讀,從網上摘錄如下兩段:
預讀算法概要
1. 順序性檢測
為了保證預讀命中率,Linux只對順序讀(sequential read)進行預讀。內核通過驗證如下兩個條件來判定一個read()是否順序讀:

  • 這是文件被打開后的第一次讀,并且讀的是文件首部;
  • 當前的讀請求與前一(記錄的)讀請求在文件內的位置是連續的。

如果不滿足上述順序性條件,就判定為隨機讀。任何一個隨機讀都將終止當前的順序序列,從而終止預讀行為(而不是縮減預讀大小)。注意這里的空間順序性說的 是文件內的偏移量,而不是指物理磁盤扇區的連續性。在這里Linux作了一種簡化,它行之有效的基本前提是文件在磁盤上是基本連續存儲的,沒有嚴重的碎片 化。

2. 流水線預讀
當程序在處理一批數據時,我們希望內核能在后臺把下一批數據事先準備好,以便CPU和硬盤能流水線作業。Linux用兩個預讀窗口來跟蹤當前順序流的預讀 狀態:current窗口和ahead窗口。其中的ahead窗口便是為流水線準備的:當應用程序工作在current窗口時,內核可能正在ahead窗 口進行異步預讀;一旦程序進入當前的ahead窗口,內核就會立即往前推進兩個窗口,并在新的ahead窗口中啟動預讀I/O。

3. 預讀的大小
當確定了要進行順序預讀(sequential readahead)時,就需要決定合適的預讀大小。預讀粒度太小的話,達不到應有的性能提升效果;預讀太多,又有可能載入太多程序不需要的頁面,造成資源浪費。為此,Linux采用了一個快速的窗口擴張過程:
首次預讀: readahead_size = read_size * 2; // or *4
預讀窗口的初始值是讀大小的二到四倍。這意味著在您的程序中使用較大的讀粒度(比如32KB)可以稍稍提升I/O效率。

后續預讀: readahead_size *= 2;
后續的預讀窗口將逐次倍增,直到達到系統設定的最大預讀大小,其缺省值是128KB。這個缺省值已經沿用至少五年了,在當前更快的硬盤和大容量內存面前,顯得太過保守。
# blockdev –setra 2048 /dev/sda
當然預讀大小不是越大越好,在很多情況下,也需要同時考慮I/O延遲問題。

6. 其他細節:

6.1. pread 和pwrite
在多線程io操作中,對io的操作盡量使用pread和pwrite,否則,如果使用seek+write/read的方式的話,就需要在操作時加鎖。這種加鎖會直接造成多線程對同一個文件的操作在應用層就串行了。從而,多線程帶來的好處就被消除了。

使用pread方式,多線程也比單線程要快很多,可見pread系統調用并沒有因為同一個文件描述符而相互阻塞。pread和pwrite系統調用在底層 實現中是如何做到相同的文件描述符而彼此之間不影響的?多線程比單線程的IOPS增高的主要因素在于調度算法。多線程做pread時相互未嚴重競爭是次要 因素。

內核在執行pread的系統調用時并沒有使用inode的信號量,避免了一個線程讀文件時阻塞了其他線程;但是pwrite的系統調用會使用inode的 信號量,多個線程會在inode信號量處產生競爭。pwrite僅將數據寫入cache就返回,時間非常短,所以競爭不會很強烈。

6.2. 文件描述符需要多套嗎?
在使用pread/pwrite的前提下,如果各個讀寫線程使用各自的一套文件描述符,是否還能進一步提升io性能?
每個文件描述符對應內核中一個叫file的對象,而每個文件對應一個叫inode的對象。假設某個進程兩次打開同一個文件,得到了兩個文件描述符,那么在 內核中對應的是兩個file對象,但只有一個inode對象。文件的讀寫操作最終由inode對象完成。所以,如果讀寫線程打開同一個文件的話,即使采用 各自獨占的文件描述符,但最終都會作用到同一個inode對象上。因此不會提升IO性能。


轉載于:https://www.cnblogs.com/bugchecker/archive/2011/08/29/3041625.html

總結

以上是生活随笔為你收集整理的磁盘IO的总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。