实践背景是开发云原生背景下的指纹识别插件,主要针对的是镜像、容器等云时代的软件资产。
信息安全语境下的 指纹识别 指的是定位软件的特征,如名称、版本号、开源许可证等,就像指纹是人的独特生物凭证,这些特征是软件的独特电子凭证。除了识别软件外,指纹识别还用于上报资产,即辅助探针发现镜像中的软件资产,包括组件、中间件、系统工具、系统库、CMS(Content Management System)等。
一、调优背景 🂠
Trivy 是一个优秀的用于扫描镜像漏洞的开源工具,但商业场景下需要定制化开发,因此自研指纹识别工具。
根据知乎文章的介绍,Trivy 有以下特点:
因此自研产品应当对标 Trivy 且有一定改进,但在首次 Benchmark 测试时,针对 4.9G 大小的镜像,自研产品扫描用时 53 秒,且占用了一个 CPU 核。这个时间和硬件开销和 Trivy 相比是不可接受的,因此分析 CPU 用时信息。具体如何分析,见之前的博客 单元测试、基准测试和性能分析 。
二、分析 CPU Profile ⚛︎
分析 cpu.prof
后发现系统调用占了 38 秒,往上查找,发现 IsExist()
是主要的时间消耗对象,其底层实现是 Stat()
系统调用 。IsExist()
用于判断文件是否存在,但在遍历镜像的文件系统时,各个检测器都要对所有的文件进行检测(Detect
函数),而 Detect
函数中都有一个 IsExist()
判断,这将造成海量的系统调用,使检测速度大幅下降。
解决策略:
- 根据计算机领域的万能准则,以空间换时间,只考虑遍历一次文件系统,记录下有用信息到 map 中,后续使用时从 map 中取出。
- 后续详细阅读代码,发现
IsExist()
函数逻辑根本没必要,因为在遍历文件系统时不可能遍历到不存在的文件。
因此修改代码逻辑后,系统调用大大减少,整体扫描时间下降至 14 秒。
三、为什么系统调用是重开销 💸(待详写)
所谓的重开销指的是消耗 CPU 资源,CPU 资源较为宝贵,因此需要合理分配。此外,从用户态陷入内核态时,还有上下文切换和现场保护,这部分也需要消耗较多资源。