挑戰啓動極速(4)---sreadahead分析

本博客原創文章屬本人lurker0ster所有,歡迎轉載。
轉載時需同意以下條件:
1. 必須保持版權信息,以及文章出處http://blog.csdn.net/lurker0ster/
2. 不準演繹,修改,必須完整轉載全部內容。

===================分割線====================   

    前面的blog提到利用sreadahead程序可以加快啓動,那麼究竟是它是利用什麼原理做到的呢?

    其實,sreadahead程序的原理是在啓動時預先讀取啓動中需要的文件加載到內存中,從而減少文件等待時間。這個程序是Arjan van de Ven <[email protected]>寫的。

    sreadahead的核心就是linux的readahead API。要達到目的需要做兩件事:記錄啓動過程中加載過的文件信息;在內核啓動啓動結束之後早啓動之前預讀取這些文件。對於前者,Arjan最早是通過hack ext3文件系統的Inode來實現的,並且新增加了EXT3_IOC_INODE_JIFFIES的ioctl調用。網上能查到的資料都是說這樣實現,實際上是錯誤的。這樣的做法,只能對ext3文件系統起作用,爲了達到通用和優化效率的目的,最新版本的patch改爲對sys_open進行hook【1】。

    通過研讀源代碼可以發現,sreadahead的追蹤功能是通過對debugfs的tracing/current_tracer和tracing/tracing_enabled進行設置打開的。代碼中對應的函數是trace_start。patch過的內核會啓動sys_open的Hook,在內存中記錄下啓動過程中讀取過的文件,以及其偏移地址和內容大小。

     當程序調用trace_stop時,它會打開debugfs中的tracing/trace,從而得到所有的文件列表,然後記錄在ra數組中。由於debugfs存在於內存中,程序最後會把數據保存在PACK文件中(/var/lib/sreadahead/pack)。

     下次啓動過程中sreadahead啓動後會先檢查PACK文件是否存在。如果存在,則從裏面讀取文件信息,並通過readahead系統調用把文件讀入cache中。之後,lilinux如何需要讀取對應的文件,就直接在內存中讀取。這裏的做法,實際上就是把零散的IO讀操作集中在一起(起了四個線程,依次讀取文件列表中的文件),只是減少了等待時間,文件讀取時間沒有節省。

      一個需要提到的內容是文件系統的readahead參數。我們知道linux文件系統優化措施之一就是readahead(預讀取),在正常的文件讀取操作中,linux會預讀取請求內容後面的128KB內容存在內存中,如何應用程序繼續讀取,則直接從內存中讀取。在sreadahead程序中由於通常都是小文件,128KB的預讀取對性能影響比較大,所有在執行讀取操作時程序會設置改參數爲16KB(通過函數readahead_set_len實現)。

     另外Ubuntu的列表上有人提到trace_stop函數會對文件列表進行冒泡排序和剔除重複記錄(

    sort_ra_by_name();
    remove_dupes();
    get_ra_blocks();

)使得程序很佔用CPU。其實冒泡排序沒有什麼必要,就算一定要排序也可以延後到啓動完成之後再排序。

     在實踐中,必須實際測試sreadahead的性能,因爲小內存的系統已經報告使用了該程序反而使得啓動時間變長。

     ubuntu維護了自己的實現(ureadahead)【2】,由Scott James Remnant 維護,原理是一樣的。

參考文獻:   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章