經過git bisect快速定位大型工程中的問題


本文介紹瞭如何經過git bisect來快速定位大型工程中所存在的問題node

上篇文章回顧:公有云運維福利-開源監控小工具:Open-Falcon插件cloud-monlinux


背景

在開發測試一個重IO操做的應用場景時,咱們發現SSD的隨機混合讀寫的數值,在 linux 4.9.2內核上和在linux 4.8.2上有很大的差別,基於此咱們開始探索各類方法來解決定位的問題。git

                                         

方法探索

初期思路

解決問題初期,咱們嘗試用如下三種方式來定位問題所在算法

  • 搜索相關文獻數組

  • 求助於相關社區bash

  • 逐一測試可行方案運維

可是,通過大約兩週的搜索、源碼修改、編譯和測試,咱們仍未定位到問題所在。因而,咱們開始尋找其餘的解決辦法。工具

二分查找

二分查找(binary search)是一種在有序數組中查找某一特定元素的搜索算法。性能

搜索過程從數組的中間元素開始,若是中間元素正好是要查找的元素,則搜索過程結束;測試

若是某一特定元素大於或者小於中間元素,則在數組大於或小於中間元素的那一半中查找,而且跟開始同樣從中間元素開始比較;

若是在某一步驟數組爲空,則表明找不到。

這種搜索算法每一次比較都使得搜索範圍縮小一半。

git bisect

git bisect是經過二分查找來快速定位引入問題commit一個工具,經過它可以在咱們已知的good和bad兩個tag的狀況下,肯定某個commit。

咱們將linux內核代碼託管於git倉庫,在這其中發現git自帶的bisect命令,能夠幫助定位問題所在。

使用方法

首先執行git bisect start來開始bisect查找,接着執行git bisect bad [bad_commit] ( 若不指定則認爲當前commit爲bad )來告訴系統哪次提交是有問題的。而後再使用git isect good [good_commit]告訴bisect已知的最後一次正常狀態是哪次提交的,以下所示:

git bisect start
git bisect bad
git bisect good v1
Bisecting: `N` revisions left to test after this[XXXXXXXXXXXXXXX] 中間版本的commit信息複製代碼

以後git會自動切換到[bad_commit][good_commit]中間位置的commit版本,以供咱們進行測試,觀察在這個提交下,問題是否仍是存在。

若是還存在,說明問題是在這個commit以前引入的;若是不存在,說明問題是在這個commit以後引入的。

假設測試結果沒有問題,就能夠經過git bisect good來告訴git來繼續尋找,以下所示

git bisect good
Bisecting: `N/2` revisions left to test after this
[XXXXXXXXXXXXXXX] commit信息複製代碼

重複執行測試,若是發現這個commit是有問題的,能夠經過git bisect bad告訴 git。

git bisect bad
Bisecting: `N/2/2` revisions left to test after this
[XXXXXXXXXXXXXXX] commit信息複製代碼

如此循環往復,當執行完最後一個revisions以後,引入問題的commit就找到了

開始實踐

肯定提交版本

由於linux內核是不一樣分支並行開發的,因此咱們所遇到的問題也是跨了兩個版本,所以首先咱們須要找到linux 4.8.2與linux 4.9.2的連續分支。

git —simplify-by-decoration A C D   
git log —graph —decorate —oneline —simplify-by-decoration A B C複製代碼

獲得good 9395452b4aab以及bad 1001354ca341

進行測試

整個測試過程徹底是靠人力的投入完成的,對於每個bisect給出的版本都要進行編譯安裝

make -j24 && make modules && make modules_install && make install複製代碼

而後進行fio磁盤讀寫測試,分析測試結果,以後選擇good或者bad來進行下一次測試。

測試結果

在通過十幾回的編譯重啓後,最終咱們定位到了引入問題的commit,如圖所示

16c54688592ce8eea85d2a26d37b64fa07e3e233 is the first bad commit
commit 16c54688592ce8eea85d2a26d37b64fa07e3e233
Author: Jan Kara <jack@suse.cz>
Date:   Fri Sep 30 01:03:17 2016 -0400    

     ext4: Allow parallel DIO reads    

     We can easily support parallel direct IO reads. We only have to make    
     sure we cannot expose uninitialized data by reading allocated block to    
     which data was not written yet, or which was already truncated. That is    
     easily achieved by holding inode_lock in shared mode - that excludes all    
     writes, truncates, hole punches. We also have to guard against page    
     writeback allocating blocks for delay-allocated pages - that race is    
     handled by the fact that we writeback all the pages in the affected    
     range and the lock protects us from new pages being created there.    
     
     Signed-off-by: Jan Kara <jack@suse.cz>    
     Signed-off-by: Theodore Ts'o <tytso@mit.edu>: 040000 040000 fdd1a8714b64c422bb200d60e9822dfd63508951 0ac1c0ceaf0ddd0eb27bbb8e719179ed68bb79df M fs複製代碼

總結分析

爲了解決內核性能損耗的問題,咱們前先後後大概耗費了一個月的時間進行排查。

而咱們決定經過git bisect直接排查內核代碼之後,只花費了不到一週的時間。

因而可知,大型項目中遇到的問題,與其耗時搜索結論,不如直接上手逐個commit排查


文章首發於共公衆號「小米運維」,點擊查看原文

相關文章
相關標籤/搜索