臉書開源內部用來加速大型應用程式的工具BOLT,由於提供複雜服務的應用程式,相對來說檔案容量就比較大,即便只編譯一種服務的機器語言,大小也可能介於10到100MB間,難以放入CPU指令快取中,硬體需要花費額外的時間處理,而臉書的程式最佳化工具BOLT藉由改進代碼布局,來加速程式載入效率。

由於臉書提供廣泛的服務,即便只編譯一種服務的機器語言,都會因容量太大而難以放進現代CPU指令快取,臉書研究,發現他們的應用程式,從記憶體獲取指令串流載進CPU的時間,需要多花30%的時間。

這個被稱為指令飢餓(Instruction Starvation)的問題,過去通常都以特性指引最佳化(Profile-guided Optimizations,PGO)來解決,最佳化輸出的檔案能讓硬體更輕易的高效使用快取架構,也能提供工程師手動標註進行配置的彈性。由於撰寫程式碼的人,最了解哪一區塊的程式碼最常被執行,由工程師進行手動標記可以獲得很好的效果,但是這種方法卻缺乏可擴展性,而且程式碼的行為也可能隨著時間改變。

在某些情況下,難以判斷程式碼的優先順序,也很難分辨哪些程式碼被執行的次數較多。而應對這問題,一般的解決辦法都是先使用PGO典型負載執行應用程式,藉由收集程式執行過程的資料,再將結果回饋到重新編譯的程式中。而當整個應用程式都使用PGO最佳化,編譯器能讀取所有的程式碼,便能從更全面的角度改進程式輸出布局,並允許編譯器在應用最佳化時做出更好的決策。

但PGO除了上述有擴展的限制外,只要沒有原始碼,PGO就無用武之地,編譯器沒辦法對組合語言或是第三方函式庫進行最佳化,而且也很難在編譯時取得或是應用配置檔案。臉書提到,AutoFDO是一個反饋最佳化來簡化真實世界部署的系統,或許能夠解決臉書遇到的問題,但是由於HHVM在臉書被大量使用,而AutoFDO剛好不適合處理大量使用HHVM中的C++例外機制。

臉書並沒有修改AutoFDO來符合自家需求,而是重新建構了BOLT,他們認為,臉書需要一個靈活的工具,可以與任何先進編譯器運作良好,不只與所有編譯器產生的代碼都能相容,也能混合來自不同編譯器的輸出。另外,這個工具還必須要能夠支援沒有原始碼的組件,像是廠商提供的函式庫,最後,這個最佳化系統需要能夠支援手動編寫的組合語言程式,以最佳化布局。

為了讓BOLT可以為應用程式執行新的代碼布局,BOLT必須重構程式碼的控制流程圖,這個任務類似反編譯,但是只需要找到像是原始碼與目標的分支與迴圈等高階結構,並不需要執行區域變數偵測等其他反編譯的工作。應用程式最後會被表示為一組函式運行一組資料的結構。

BOLT的輸入要求很低,臉書的目標是要支援Linux二元檔,他們從x86-64指令集開始,並增加支援AArch64,未來也還計畫擴展到其他架構上。最初HHVM被BOLT加速後,其效能比編譯器最佳化的結果提高3%,還能藉由連結期函式布局工具HFSort最佳化。經過一系列的改進與調整,目前HHVM在許多情況下能夠加速8%,整體來說,不同的CPU架構造成不同的結果,提升2%到15%的執行效能。

現在臉書將BOLT在GitHub上開源,開發者在解決遇到大量指令快取,或是轉譯後備緩衝區失誤的問題,BOLT可以提供有效的幫助。

熱門新聞

Advertisement