继续和Bug定位打交道!
分享一篇来自ISSTA' 20的论文,题目为:Scaffle: Bug Localization on Millions of Files。
本文关注超大规模异构代码库(包含数百万个由多种编程语言编写的代码文件的代码库)。当软件出现崩溃时,开发人员通常能够得到的唯一信息是Crash Trace。Crash trace包含了Stack Trace、错误消息崩溃前的程序状态等重要信息。然而,在大型的组织中,在给定崩溃的条件下定位bug是不容易的。虽然crash trace包含了与bug相关的信息,但是也包含了大量与bug定位无关的噪音,为bug定位带来了挑战。
插一句,作者在Introduction中总结了bug定位相关的研究,如表1所示。值得参考。
本文所提模型名为Scaffle,框架如图1所示。该模型的创新在于:(1)将crash trace中的特定行与代码库中的文件路径进行匹配,而无需分析文件内容;(2)不针对特定的编程语言,因此对crash trace的结构和格式没有要求。作者通过将基于crash trace的bug定位分解为两个子问题,以实现将所提模型扩展到超大规模代码库上。具体而言,针对单一语言的bug定位模型采用的是端到端的方式,通过直接将crash trace和代码库中的文件进行比较以实现定位。而在Scaffle中,则将整个流程用两个组件断开,分别是Trace-Line Model和IR-based Search。
大多数大型项目都有大量关于崩溃的历史数据,以及关于修复崩溃根本原因的代码更改的历史数据。因此,给定崩溃的修复位置,我们根据crash trace的每一行是否包含错误位置的文件路径的相关部分,推导出崩溃跟踪的每一行与查找错误位置的相关性得分(如下图红框部分所示)。
Trace-line model的训练数据由对组成,其中,是一个有n行trace组成的crash trace;,是t中每一行对应的相关性分数向量。
对于t和用于代码变更集c,采用算法1以获取对。具体来说:通过对t中的每一行和受c影响的每个文件路径进行成对比较,产生与预测路径相关的行。为进行比较,Scaffle将文件路径标记为单独的路径段,将行标记为单独的单词(基于非字母字符进行分词)。给定一个tokenized的文件路径和一个tokenized的行,计算既包含在路径中,也包含在行中的单词的百分比将其作为文件路径与行的相关性分数。找出所有行中最大的相关性得分,将其添加到r中。参考上图示例,第27行被tokenize为("at", "dostuff", "DostuffBrowserController", "clearBrowserFragment", "java", "775")。假设c包含单一路径projectX/packageA/dostuff/DoStuffBrowserController.java
,将其tokenize为("projectX", "packageA", "dostuff", "DostuffBrowserController", "java")。由于27行包含了该路径5个词中的3个,因此27行与该路径的相关性得分为。
图3是trace-line model的基本框架,由两个不同层级的RNN网络串联而成。行级RNN用于学习t中每一行的向量表示,trace级RNN用于学习行的向量特征并进行预测。
这部分涉及两个挑战:(1)如何将模型应用到百万级的代码库中,(2)最相关的跟踪行可能没有提到错误所在的确切文件路径。对于挑战(1),通过关注跟踪的单行,而不是将每行与代码库进行比较,能够在一定程度上应对。对于挑战(2),可能的原因是由于crash trace使用相对于崩溃位置的路径,文件路径的前缀可能缺失,或者根本不包含文件名。为此,本文使用了基于IR的检索方法,也就是bug定位领域常用的排名(ranking)模型。注意,本文使用的是现有的IR模型。
在IR搜索的过程中,crash trace的相关性得分最高的行作为一个查询,而代码库中的每一个文件路径都是一个文档。通过将所有文件路径标记为段,标记出现在最相关行的单词,将其作为查询提供给基于IR的搜索引擎,并将搜索结果中的文件路径作为可能有bug的文件的排序列返回。如上面提到的crash trace实例图,第28行的trace的相关性得分最高,因此使用起作为查询。对于该查询,相对于projectX/packageB/some/other/path/Logger.java
,projectX/packageA/dostuff/DoStuffBrowserController.java
更与之相关。
这篇文章没有用到任何表格,全是图片。对于实验结果部分的展示,如下图所示,感觉比表格更直观,值得借鉴。