Page 44 - 《软件学报》2024年第6期
P. 44
2620 软件学报 2024 年第 35 卷第 6 期
针对算法 1 简要介绍如下.
1) 程序首先遍历 Soufflé 程序的抽象语法树, 并在遇到组件声明时创建一个 Component 对象.
2) 在第 2 次扫描的时候, 当程序遇到组件实例化时, 它会调用 Component 对象的 instantiate 方法. 这个方法负
责将组件的类型参数替换为实例化时提供的具体类型参数. 同时, 它还会处理组件的继承关系, 实例化所有父组
件, 并将它们的内容合并到当前组件实例中.
3) 在实例化过程中, 程序会处理.override 指令, 用于标记当前组件覆盖了哪些关系.
4) 最后, 程序将遍历组件体中的声明 (如关系、规则等), 并将它们重写为 DDlog 语法.
以 Soufflé 参考代码中的不包含继承关系的简单组件为例, 我们在扫描到.init graph = Graph 命令的时候, 我们
就会开始进行实例化, 由于这里没有.override 指令, 所以对 edge 的定义会被处理, 并且被实例化为 graph_edge, 之
后就是按照此前讨论的语法结构重写规则进行重写 (第 2.2.2 节).
3 实验评估
为了展示我们的 DDoop 增量指针分析框架在代码变更频繁的场景下的性能和对 Doop 框架现有指针分析规
则, 我们选定的实验基准都是在实际中广泛使用的
则的兼容性, 我们在一组代码变更上对 DDoop 框架进行了实证评估, 并与原始 Doop 框架及当前尝试为 Doop 框
架添加增量支持的现有工作进行了实验对比. 我们的实验评估主要试图回答以下 3 个研究问题.
• RQ1: 我们的增量 DDoop 框架与原始的非增量 Doop 框架相比性能表现如何?
• RQ2: 我们的增量 DDoop 框架对 Doop 中现有指针分析规则的兼容性如何?
• RQ3: 我们在 DDoop 前端中进行的剪枝操作对分析精度的影响如何?
3.1 实验设置
实验平台. 我们的所有实验在一台配备 Intel(R) Xeon(R) Gold 6240 @ 2.60 GHz 处理器 (75 核), 285 GB 内存,
1 TB 磁盘的 Ubuntu 20.04.6 LTS 服务器上运行. 在实验评估中我们设置最大可用线程数为 8.
基线工具. 我们在实验评估中对比的基线工具分别是原始 Doop 框架以及两种带基础增量支持的 Doop 框架.
基线工具的详细信息如下.
• Doop: 基于 Soufflé (2.0.3) 的原始 Doop 框架 (4.24.10).
• Doop-SE: 基于 Soufflé-elastic (540cf8d) 的带基础增量支持的 Doop 框架 (4.24.10). 在 Soufflé-elastic 工作中
并未提供与 Doop 框架的整合. 这里的 Doop-SE 是我们框架前端的一个修改版 (修改了增量指令格式以适配 Soufflé-
elastic) 与 Soufflé-elastic 增量引擎的一个简单组合.
• Doop-DDlog [17] : 初步整合了 DDlog 引擎 (0.4.0) 的 Doop 框架 (4.24.10).
我们的 DDoop 增量指针分析框架是基于 Doop (4.24.10) 和 DDlog (1.2.3) 进行实现的.
指针分析精度. 在实验中, 我们选择了来自 Doop 中的多种不同精度的指针分析规则, 旨在证明我们的框架对
于现有的 Doop 中丰富的指针分析规则的高度兼容性. 具体而言, 我们选择了如下几种精度: 上下文不敏感、k 对
象敏感 (k=1 或 2)、k 调用点敏感 (k=1)、k 类型敏感 (k=1 或 2)、选择性对象敏感.
实验基准集. 我们的增量指针分析框架针对的是在变更频繁且单次变更的变化相对局部的场景. 按照这个原
Java 项目, 并且在其 GitHub 存储库中代码变更频繁, 如表 1 所
示. 我们的实验都集中在它们的 master 分支上, 对从表 1 中记录的起始提交开始, 按照提交历史中的顺序对连续
20 次代码提交进行增量分析. 当然, 在实际的增量分析场景下我们可能会针对一次 PR 甚至一次发布进行增量分
析, 但是我们同样可以将 PR 或者发布视为一次较大的代码提交.
我们对 5 个选定的 Java 项目做简要的介绍.
1) Jedis 是 Redis 的 Java 客户端, 专为性能和易用性而设计.
2) ErrorProne 是 Java 的静态分析工具, 可在编译时捕获常见的编程错误.
3) ZooKeeper 是一个分布式协调服务, 用于管理和维护分布式系统中的配置、命名等信息.