通过git bisect快速定位大型工程中的问题

版权声明:文章可以转载,转载请注明原出处链接 https://blog.csdn.net/pengzhouzhou/article/details/89029153

                                             本文介绍了如何通过git bisect来快速定位大型工程中所存在的问题

背景

在开发测试一个重IO操作的应用场景时,我们发现SSD的随机混合读写的数值,在 linux 4.9.2内核上和在linux 4.8.2上有很大的差异,基于此我们开始探索各种方法来解决定位的问题。

   

方法探索

初期思路

解决问题初期,我们尝试用以下三种方式来定位问题所在

  • 搜索相关文献

  • 求助于相关社区

  • 逐一测试可行方案

但是,经过大约两周的搜索、源码修改、编译和测试,我们仍未定位到问题所在。于是,我们开始寻找其他的解决办法。

扫描二维码关注公众号,回复: 5948197 查看本文章

二分查找

二分查找(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 bisect 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 <[email protected]>
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 <[email protected]>
    Signed-off-by: Theodore Ts'o <[email protected]>

:040000 040000 fdd1a8714b64c422bb200d60e9822dfd63508951 0ac1c0ceaf0ddd0eb27bbb8e719179ed68bb79df M  fs

总结分析

为了解决内核性能损耗的问题,我们前前后后大概耗费了一个月的时间进行排查。

而我们决定通过git bisect直接排查内核代码以后,只花费了不到一周的时间。

由此可见,大型项目中遇到的问题,与其耗时搜索结论,不如直接上手逐个commit排查

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

猜你喜欢

转载自blog.csdn.net/pengzhouzhou/article/details/89029153
今日推荐