【性能调优】真实体验 “系统调用是重开销”

实践背景是开发云原生背景下的指纹识别插件,主要针对的是镜像、容器等云时代的软件资产。

信息安全语境下的 指纹识别 指的是定位软件的特征,如名称、版本号、开源许可证等,就像指纹是人的独特生物凭证,这些特征是软件的独特电子凭证。除了识别软件外,指纹识别还用于上报资产,即辅助探针发现镜像中的软件资产,包括组件、中间件、系统工具、系统库、CMS(Content Management System)等。

一、调优背景

Trivy 是一个优秀的用于扫描镜像漏洞的开源工具,但商业场景下需要定制化开发,因此自研指纹识别工具。
根据知乎文章的介绍,Trivy 有以下特点:

【性能调优】真实体验 “系统调用是重开销”_第1张图片

因此自研产品应当对标 Trivy 且有一定改进,但在首次 Benchmark 测试时,针对 4.9G 大小的镜像,自研产品扫描用时 53 秒,且占用了一个 CPU 核。这个时间和硬件开销和 Trivy 相比是不可接受的,因此分析 CPU 用时信息。具体如何分析,见之前的博客 单元测试、基准测试和性能分析 。

二、分析 CPU Profile ⚛︎

分析 cpu.prof 后发现系统调用占了 38 秒,往上查找,发现 IsExist() 是主要的时间消耗对象,其底层实现是 Stat() 系统调用 。IsExist() 用于判断文件是否存在,但在遍历镜像的文件系统时,各个检测器都要对所有的文件进行检测(Detect 函数),而 Detect 函数中都有一个 IsExist() 判断,这将造成海量的系统调用,使检测速度大幅下降。

解决策略:

  1. 根据计算机领域的万能准则,以空间换时间,只考虑遍历一次文件系统,记录下有用信息到 map 中,后续使用时从 map 中取出。
  2. 后续详细阅读代码,发现 IsExist() 函数逻辑根本没必要,因为在遍历文件系统时不可能遍历到不存在的文件。

因此修改代码逻辑后,系统调用大大减少,整体扫描时间下降至 14 秒。

三、为什么系统调用是重开销

所谓的重开销指的是消耗 CPU 资源,CPU 资源较为宝贵,因此需要合理分配。此外,从用户态陷入内核态时,还有上下文切换和现场保护,这部分也需要消耗较多资源。要理解为什么系统调用是重开销,就需要知道系统调用时发生了什么,进而分析哪些部分是开销大头。

3.1 什么是系统调用

系统调用(System Call,syscall)是用户态进程在请求系统资源时向操作系统内核发起的请求,如文件 I/O 操作、进程间通信等。这种将用户态与内核态隔离的方式,便于集中管理计算机资源,也使用户态的程序开发不需过多关注与硬件的交互。

【性能调优】真实体验 “系统调用是重开销”_第2张图片

根据中断触发来源的不同,可以将中断(Interrupt)分为 软件中断硬件中断

一般而言,系统调用是通过软件中断实现的,即 CPU 在执行特定指令时触发的。

你可能感兴趣的:(底层剖析,性能优化)