原文:A study of Linux file system evolution, in FAST'13.
这是会议的最佳论文,分析了8年时间内六个主流Linux文件系统(Ext3,Ext4,XFS, Btrfs, ReiserFS, JFS)的5079个补丁,详细解答了什么补丁最多,什么bug最多等问题。这里将几个有意思的结论列出来。
1. 维护型补丁最多
维护型补丁包括改善代码的可读性,简化代码结构等等,此类补丁占了60%之多,足见良好的可维护性对于一个复杂的开源项目是十分重要的。
2. bug修复型补丁第二多,并且伴随着软件的整个生命周期
有40%的补丁是bug修复型补丁。对于像Btrfs这种仍在开发的文件系统,bug很多不奇怪。最让人吃惊的,是Ext3这种老牌的成熟的文件系统仍然有很多bug修复型补丁,事实上,一点也不必Btrfs少。新发现的bug数量并不会随着软件成熟而慢慢减少,这意味着修复bug是软件开发的永恒主题。看来软件开发人员必须要学会享受debug。
3. 大多数bug出现在元数据管理相关模块,而使用复杂的数据结构并不会增加bug
研究发现inode、superblocks相关的元数据管理模块的代码量不多,但是bug却非常多。它们保存了系统的关键信息,被频繁访问和修改,因此出现更多的bug也正常。其次,使用树这样的复杂数据结构并不会增加很多bug,原因可能是开发人员比较重视,因此我们应该鼓励使用合适的数据结构。
4. 语义bug最多
文件系统的bug可以分为四大类:语义bug,并发bug,内存bug,错误码bug。其中语义bug最多,占了60%左右。所谓语义bug,包括错误地更新了文件系统的状态,算法错误,错误的IO请求顺序,打字错误等。通常修复语义bug需要对文件系统有相当了解,现有debug工具很难发现和解决此类bug。
5.与用户程序相比,并发bug更多,内存bug更少
文件系统的并发bug大约占20%,而用户程序中,并发bug只占3%;文件系统的内存bug大约占10%,要比用户程序少得多。并发bug包括死锁、忘记解锁、多次解锁、原子性问题等;内存bug包括内存泄漏、空指针、悬挂指针、多次释放、缓冲区溢出等。
6.大多数bug会造成严重的后果
40%的bug会造成数据损坏,20%的bug会造成系统崩溃,10%会造成死锁,10%会造成系统进入未知状态。
7. 不同种类的bug会造成不同的后果
数据损坏、系统崩溃等大多是由语义bug导致的,死锁大多是由并发bug导致的,内存泄漏大多是由内存bug导致的。错误码bug可能导致各种后果,但是比例都不大。
8.大多数bug修复型补丁很小,只有几行代码
50%以上的bug修复型补丁小于10行代码,说明修正一个bug并不复杂,debug难在分析和重现一个bug。论文还给出了各种bug的例子,补丁都很短,如下图。
可以看到这些bug都很简单,并不比我们平常写程序遇到的bug更高级。除了semantic bugs以外,其它的bug应该是共通的,大多数程序员都迟早也面临着内存、并发的坎。