经过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排查


文章首发于共公众号“小米运维”,点击查看原文

相关文章
相关标签/搜索