Lean spring-boot Application

Abstract

Some tips and tricks to improve Spring Boot startup time:

  • use Packeto Buildpack to build your Docker images
    • more secure
    • more optimized
  • can use spring-context-indexer to generate a META-INF/spring.components file that included in the jar file in order to accelerate startup time
  • lazy spring beans can be activated globally with -e spring.main.lazy-initialization=true
    • pros
      • faster startup time
      • application startup is a CPU intensive tasks, spreading the load over time
    • cons
      • initial requests may take more time
      • class loading issues and missconfiguration unnoticed at startup
      • beans creation erros only be found at the time of loading the bean
  • tiered compilation is enabled by default since Java 8. Unless explicitly specified, the JVM decides with JIT compiler to use based on our CPU. For multi-core processors or 64-bit VMs, the JVM wil select C2.
    • In order to disable C2 and only use C1 compiler with no profiling overhead, we can apply the -XX:TieredStopAtLevel=1 parameter
    • -e "JAVA_TOOL_OPTIONS=-XX:TieredStopAtLevel=1"
    • it will slow down the JIT later at the expense of the saved startuptime
  • no spring boot actuator to accelerate startup time
  • fixing spring boot config location with -e spring.config.location=classpath:application.properties to gain a bit of time
  • dependency cleanup using decpclean-maven-plugin to detect and remove all unused dependencies declared in the pom.xml of a project:
< plugin>
  <groupId>se.kth.castor</groupId>
  <artifactId>depclean-maven-plugin</artifactId>
  <version>2.0.6</version>
  < executions>
    < execution>
      <goals><goal>depclean</goal></goals>
    </execution>
  </executions>
</plugin>
  • using jlink, that assembles and optimizes a set of modules and their dependencies into a custom runtime image for your application, to reduce image size:
< plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  < configuration>
    < image>
      < env>
        <BP_JVM_JLINK_ENABLED>true</BP_JVM_JLINK_ENABLED>
        <BP_JVM_JLINK_ARGS>...</BP_JVM_JLINK_ARGS>
      </env>
    </image>
  </configuration>
</plugin>
  • native build with GraalVM
    • long build time
    • result can be different from what you run in your IDE
  • CRaC - OpenJDK (Checkpoint and Restart in Java): feature that allows to checkpoint the state of a Java application and restart it from the checkpointed state application starts within milliseconds!
    • still experimental
    • does not work with spring boot 3
    • does not work in Docker containers
    • does not work on Windows or on macOS
  • bytecode obfuscating and shrinking can be used to reduce the size of the application
    • Use Proguard and YGuard (tools used for Android)