@article{drosos2024bloat,
title={Bloat beneath Python’s Scales: A Fine-Grained Inter-Project Dependency Analysis},
author={Drosos, Georgios-Petros and Sotiropoulos, Thodoris and Spinellis, Diomidis and Mitropoulos, Dimitris},
journal={Proceedings of the ACM on Software Engineering},
volume={1},
number={FSE},
pages={2584--2607},
year={2024},
publisher={ACM New York, NY, USA}
}
0 ABSTRACT
- 问题:软件复用带来 依赖膨胀 的挑战,其表示无用的和过多的代码通过服用库集成到了项目中。 这些膨胀的以来代码的存在带来了 安全问题,维护成本,提升了存储需求,减缓了应用加载时间。
- 这篇工作中,我们进行了一个大规模细致分析,来理解PyPI系统中膨胀的依赖。
- 我们的分析是第一个关注在不同维度上的,包括膨胀依赖,膨胀文件和膨胀方法,这使得我们可以具体到库中的膨胀代码
- 我们分析了1302个Python项目以及他们的3232个依赖。对每个项目使用了SOTA静态分析器细粒度的构造fine-grained project dependency graph(FPDG),代表了项目内方法级的依赖
- 我们对FPDG的可达性分析使得可以从多个方面评估膨胀依赖代码,包括其在PyPI生态系统中的普遍性、与软件漏洞的关系、其根因以及开发者的认知。
- 我们的结果显示
- PyPI系统中展示出显著的资源不充分利用,超过50%的依赖是膨胀的,当考虑的膨胀依赖代码级别更细致时,这一比例更高,如膨胀文件和膨胀方法
- 在利用的包的膨胀区域中存在许多漏洞(PyPI中存在的缺陷有15%)
- 膨胀代码主要源于代码重构过程中的遗漏,而且开发者愿意对他们的代码进行去膨胀处理:在提交的36个合并请求中,开发者接受并合并了28个,总共移除了33个膨胀依赖。
- 我们相信我们的发现可以帮助研究人员和从业者提出新的去膨胀技术和开发实践来检测和避免膨胀代码,保证依赖资源高效地使用
1 INTRODUCTION
- 本研究专注于 bloated dependency code的存在
- bloated dependency会带来很多问题
- (1)引入依赖冲突,提升维护成本
- (2)与弱点代码相关
- 膨胀依赖代码的研究很少,且都在包级别,然而代码复用通常在函数或者方法级别。
- 本研究中,我们是第一个在Python项目中的膨胀依赖中进行细粒度的依赖分析。Python Package Index(PyPI) ,托管了众多py项目。我们探究了以下研究问题
- RQ1(Prevalence)膨胀依赖代码在PyPI中的普遍性?膨胀依赖代码在不同粒度上具有哪些定性特征
- RQ2(Security)膨胀依赖代码和软件漏洞的关系?漏洞位于膨胀代码区域吗
- RQ3(Causes)膨胀的PyPI以来的主要原因是什么?这些原因的频率如何
- RQ4(Developer perception)开发者愿意移除膨胀的PyPI依赖的意愿如何?他们是否愿意去除这些代码
- 为了回答这些问题,我们在受欢迎的安卓项目上设计实现了一个大规模,细粒度的分析。
- 我们从一个建立好的数据集中选择了1302个github 上的python项目。
- 对每个项目,我们生成了FPDG,在方法级别上构成了依赖网络
- 我们使用PyCG,Python SOTA静态分析器,构建每个Python项目和以来的 调用图。通过stitching 过程,我们合并所有的调用图得到最后的FPDG
- 在FPDG上进行可达性分析,即可评估膨胀依赖代码。
- 贡献
-
- 我们进行了首次大规模分析,用于构建PyPI生态系统中的细粒度依赖网络。我们提供了一个包含来自1,302个Python项目和3,232个PyPI版本的依赖网络的相应参考数据集(第2节)。
-
- 我们量化了PyPI生态系统中的膨胀现象,并对其普遍性、安全影响、主要原因以及开发者的认知进行了全面评估(第3节)。
-
- 我们列举了我们的研究结果的含义,并讨论了软件依赖管理中潜在的未来方向(第4节)。
-
- 发现总结
- RQ1:PyPI系统存在着依赖显著使用不充分的现象
- RQ2:在使用的包的膨胀区域我们发现了漏洞
- RQ3:主要由开发者代码库中的普遍变更(例如,功能移除)引入
- RQ4:开发者愿意移除膨胀的依赖,尤其在他们知道膨胀引入的原因时
- 影响
- 通过我们的分析,我们通过提交pull request来解决膨胀依赖。我们成功简化了28个项目中的依赖,
- 我们相信,我们的研究可以帮助研究人员和从业者构建合适的linters和自动化重构工具,以检测并消除Python项目中的膨胀依赖代码。
2 METHODOLOGY
2.1 Definition of Bloated Dependency Code
2.2 Project Selection and Dependency Resolution
2.3 Construction of Fine-Grained Project Dependency Graphs
2.4 Analyzing Reachability Results
RQ1 软件膨胀的普遍性:使用膨胀方法,膨胀文件和膨胀依赖的大小衡量
RQ2 软件膨胀和软件漏洞间的关系:使用可达性分析漏洞是否在膨胀代码中
RQ3 根因定位分析:对git提交记录进行分析,获得膨胀依赖出现的时机,分析可能的原因
RQ4 开发者对软件膨胀的观点:对膨胀依赖提出pull request,观察开发者的反应
- pr包含四部分:(1)总结(2)推理(3)源文件变化列表(4)影响和改变
3 RESULTS
3.1 RQ1 软件膨胀的普遍性
Package level: 51%依赖是膨胀的,对应代码的膨胀比例是34%
File level:87%的依赖源文件是膨胀的
Method level:95%的外部方法是膨胀的,对应代码是93%
3.2 RQ2 软件膨胀和软件漏洞间的关系
89%的PyPI依赖中的漏洞被发现在臃肿的代码部分,值得注意的是,有15%存在于已使用的依赖中。
3.3 RQ3 根因定位分析
手工分析了50个膨胀依赖,我们分析了6类原因
-
Replacement with build-in or alternate library:开发者将第三方库使用内置库或其它库替换,但忘了移除之前库的依赖。 9个实例
-
Feature removal:移除了一些功能,但忘了移除依赖。 10个实例
-
Unused from the first time:没有任何使用情况,可能是开发阶段遗留 8个实例
-
Redundant declaration of a transitive dependency:项目将传递依赖项列为了直接依赖项 15个实例
-
Security constraint:处于安全考虑有目的地限制传递依赖的版本 5个实例
-
Compatibility constraint:版本适配限制 3个实例
-
结论:
-
- 代码重构后,维护和更新配置文件的重要性
-
- 在传递性依赖上更好地管理,以避免冗余依赖的生命
-
3.4 RQ4 开发者对软件膨胀的观点
- 在收到回复的PR里,90%(28/31)被接收
- 68%在没有讨论的需要下被接收,其余的进行了讨论
4 KEY TAKEWAYS AND SUGGESTIONS
RQ1:
- 1. The PyPI ecosystem exhibits considerable resource underutilization
- 2. Dependency code bloat becomes more prevalent via find-grained analysis
RQ2: - 3. “Time-bombs in bloated dependency code”
- 这里可以有自动化移除膨胀依赖的工具,减小漏洞
- 同时也可以在commits时,分析可能的漏洞,提醒开发者是否可以去除
RQ3:
- 4. Code refactoring introduces bloated dependencies
RQ4: - 5. Developers are willing to remove bloated dependency code especially they are aware if its major causes
- 简化工具应明确说明移除某个膨胀依赖代码的原因,并且提供类似我们pull request请求的步骤,指导开发者有效地进行更改
- 我们的发现表明,未来的工具应根据膨胀代码发生的原因优先发出警告
5 THREATS TO VALIDITY
Internal validity
- FPDG可能包含错误的边
- Python项目的代表性
- 与我们的stitching过程和外部调用的解决措施有关
External validity - 研究的泛化性,只在Python和PyPI系统上
- RQ3和RQ4选择的膨胀例子较少
6 RELATED WORK
Software bloat
- 许多专注于减小源程序大小的技术,使用了程序转换,语法感知技术(Perses),强化学习(Chisel)
- 一些专注于C/C++二进制文件上,减小攻击面
- 简化Java应用,使用静态分析和动态分析在Java字节码上
- 还有一些专注JavaScript,PHP web应用上
- 软件去膨胀也被应用在具体领域的应用上,如Chromium浏览器,共享连接库
- 然而,目前没有面向Python的简化技术,我们的工作为面向Python系统的简化工具的设计停工了见解
Bloated dependencies - "bloated dependencies"在[A comprehensive study of bloated dependencies
in the Maven ecosystem]中首先被提出。通过分析Java字节码,他们识别并移除了Maven POM文件中未使用的依赖,他们的研究揭示了依赖关系中高达75%的膨胀率,主要源自于传递性依赖。 - Hejderup et al. [2022] 使用调用图构建Rust系统的依赖网络,他们发现60%包依赖是膨胀的
- Jarfari et al. [2022]在npm系统中发现了类似的趋势
- Cao et al.[2023]与我们的工作最接近,他们探究了132个项目中的"dependency smells",其描述了一系列依赖问题,包括膨胀依赖。
- 为了识别膨胀以来,作者解析了配置文件,分析了源代码中的import语句
- 其通过 prevalence, evolution, causes, and developer perceptions描述膨胀的依赖项。
- 研究发现86%的项目存在直接依赖膨胀,其中75%的这些依赖项来自于新的依赖声明,而没有后续的源代码使用。
- 然而,我们的方法更精细,在文件和方法级别量化膨胀,此外我们可以区分直接依赖和见解依赖
- 更进一步,他们的研究指出开发者在移除膨胀依赖很犹豫(0/10 reported issues fixed,4/10 rejected),相反,我们的研究表明开发者愿意移除膨胀依赖,尤其是在他们知道膨胀引入的原因时
Access path reasoning
Software ecosystem analysis
- Hejderup et al. [2018] 引入了使用调用图表示软件系统的真实调用关系的想法,基于此,Miret al. [2023]在Maven系统上进行了细粒度的分析,发现了1/3的包是有漏洞的因为传递依赖,只有1%的包是可达的
- Duan et al.[2020]对 PyPI,RubyGems,npm 构建了程序分析流水线来检测有问题的包
- Zahan et al.[2022]专注JavaScript,分析了160万个软件包的元数据,并提出了一些特定的指标,这些指标可以作为供应链脆弱性的预警信号。
- Staicu et al. [2018]揭示了npm生态系统中注入攻击的高发性
- 等等
7 CONCLUSION
- 我们进行了PyPI生态系统中膨胀依赖代码的首次细粒度研究。我们构建了大型的跨项目依赖图,这些图在方法级别上捕捉了1,032个Python项目与3,232个PyPI版本之间的关系。通过使用标准的图可达性算法,我们研究了不同粒度下的膨胀依赖代码。
- Finding 1:我们发现PyPI生态系统充满了膨胀:一个典型的Python项目中超过一半的依赖项完全没有被使用。更糟糕的是,当考虑到文件和方法的粒度时,这种膨胀显著增加。
- Finding 2:我们已经识别出一些“定时炸弹”(15%),即那些没有被不同项目调用但存在于项目使用的包中的易受攻击的代码。
- Finding 3:膨胀的依赖代码主要源于普遍的代码更改(例如,功能移除)。
- Finding 4:开发者愿意移除他们的膨胀依赖:我们提交的36个拉取请求中有28个已经被开发者合并,共移除了33个直接依赖。
- 影响
- 我们相信我们的工作可以指导未来Python的膨胀检测和预防工具的设计。这样的工具应该有效处理超出包级别的粒度上的膨胀,从而显著降低Python应用程序的维护风险。
- 最后,膨胀预防工具需要向开发者提供信息丰富且可操作的消息,并根据膨胀的根本原因优先排序警告。
个人总结
- 本文对Python的PyPI中的项目进行了依赖分析,分析了膨胀的普遍性,带来的安全问题,膨胀来源,以及开发者应对膨胀的态度
- 通过pull request体现开发者态度是一个不错的选择,类似的做法可以在其它语言的项目上
- 同样,语言的包生态系统分析也可以在不同的语言上进行,这是未来的研究方向
- 同时,未来的软件简化工具应该更偏向辅助作用,并对可能的简化措施提供理由和指导