CDS(Class Data Sharing)在 Spring 6.1 中的应用

正如 官方文档 所述,类数据共享(CDS)通过将类元数据缓存在 Archive(归档/存档) 文件中,使其可以快速预加载到新启动的 JVM 中,从而帮助缩短 JVM 的启动时间和内存占用。这加快了类加载速度,而类加载速度是启动时间的一个重要因素。大多数最新的 JDK 发行版中预先打包了默认的 CDS 归档,其中包含了常见 JDK 类的元数据。你也可以创建自定义的 CDS 归档,以加快类在自己应用中的加载速度。

GraalVM 原生镜像Project CRaC 都能让 Spring Boot 应用在几十毫秒内启动。那么,为什么要关注 CDS 呢?

主要有三个原因:

  • 它是 OpenJDK 主线中成熟且可用于生产的技术,与 GraalVM 和 Project CRaC 相比,它更易于使用,因为它具有较少的限制和副作用。
  • 正如 Brian Goetz 在他在 Devoxx 上的 Project Leyden 演讲 中提到的:“大多数人今天不使用 CDS,但可能应该使用,因为他们可以通过相对较少的工作获得合理的启动性能提升。”
  • 在每一个新的 JVM 版本中,这项技术都会变得越来越好,Project Leyden 的目标是在不久的将来增加更多的优势。

接下来,让我们一起探究 CDS 能为你的 Spring 应用带来什么?

在 Spring 6.1 中引入 CDS 初始支持

Spring 6.1 带来了一个新的 “类数据共享” 文档章节,解释了优化应用的两个步骤:

  1. 使用新增的 -Dspring.context.exit=onRefresh JVM 系统属性,可以通过训练运行创建 CDS 归档,在大多数使用情况下,无需启动 Bean 或访问远程服务。
  2. 使用归档来优化生产环境的启动。

要使 CDS 优化发挥最大效果,必须确保创建归档和启动应用时所使用的 JDK 和类路径完全相同。

还要注意的是,要有效地缓存类:

  • classpath 应指定为一个常规的非嵌套 JAR 列表。
  • 避免使用目录。
  • 避免 * 通配符扩展。

由于 Spring Boot 可执行 JAR 或 非打包部署 目前还不能满足所有这些条件,因此它们还不能实现最佳的 CDS 性能。

因此,我们与 Stéphane Nicoll 合作,开发了一个 CDS 友好的非打包部署方案,以便能够获取相关的数据点,并为 Spring 开发人员提供探索 CDS 支持的途径,而不对 Spring Boot 在更集成的方式下提供 CDS 支持 做出任何假设。请参阅相关的 spring-boot#38276 issue 以获取更多详细信息。

如果你想在自己的应用中使用 CDS 并提供反馈,可以尝试从 spring-cds-demo 仓库中获得灵感,该仓库包含一个自带的 unpack-executable-jar.sh 脚本,它能以最佳方式解压缩 Spring Boot 可执行 JAR,从而实现 CDS 的最佳性能。你还可以试试 Stéphane 制作的 cds-log-parser 工具,它能生成报告,显示哪些类是从 CDS 缓存中加载的。

Spring Petclinic 和 CDS

来看看从著名的 Spring Petclinic 应用的数据点中能学到什么,该应用部署了 CDS 优化,运行在 Java 21 上,并可选择与 Spring AOT 优化相结合。

可执行 JAR、解压缩、CDS 和 CDS + Spring AOT 的性能对比

第一个要点与 CDS 无关,但已经被广泛认知和记录,但值得强调:为了实现最佳的启动时间,Spring Boot 应用的生产部署应该是 非打包部署。如果你正在使用 Buildpacks,则已经符合此要求。如果没有,你可能需要检查并可能改进你的自定义部署方式。

与非打包部署相比,CDS 优化可以将启动时间减少 30 %至 35%,只需创建几十 Mb 大小的 CDS 归档并将其与应用一起使用。当然,与 GraalVM 或 Project CRaC 相比,这种收益并不那么显著,但你也不需要做很多工作就能获得这些好处。因此,如果集成得当,CDS 可能具有被广泛采用的巨大潜力。如果将 CDS 与 Spring AOT 优化相结合,可以将 Petclinic 的启动时间减少 36% 至 42%。

总结

像往常一样,我们期待 Spring 社区的反馈,以帮助我们思考下一步可能采取的措施,从而实现更加集成的体验。例如,你是否对通过 CDS 缓存自动构建 Spring Boot 优化容器的功能感兴趣?

展望未来,Spring 团队将继续与 Java Platform 团队合作,研究如何利用这些改进和发现与 Project Leyden premain 优化 相结合,在 JVM 上提高运行时效率,同时尽可能减少对 Spring 开发人员和操作人员的限制。


Ref:https://spring.io/blog/2023/12/04/cds-with-spring-framework-6-1