Files
Ankur Mhatre 958b401f0f Spring Boot startup time: bean-by-bean diagnosis, and one directory per post
Adds spring-boot-startup-time/, the companion project for BLOG-618: a runnable
Spring Boot 4.1.1 application on JDK 25 that installs BufferingApplicationStartup
and FlightRecorderApplicationStartup behind a system property, and a /diag/startup
endpoint that computes step self time -- the number /actuator/startup does not give
you and the one that names the actual culprits.

Captured under docs/output/: the step tree sorted both ways, the same startup as JFR
events, a +5000-class experiment putting 0.11 ms per scanned class on the classpath
scan tax, the silent truncation a 2048-step buffer performs, and JDK 25 AOT cache
timings (6.93 s to 4.82 s). Post body and metadata live in post/.

Moves the existing Actuator project into actuator-in-production/ so the repository
holds one directory per article; the root README is now an index.
2026-09-05 00:17:37 +05:30

61 lines
2.7 KiB
Plaintext

Started StartupDiagnosisApplication in 7.441 seconds (process running for 8.49)
=== jfr summary (Spring rows only) ===
Version: 2.1
Chunks: 1
=========================================================================================
org.springframework.core.metrics.jfr.FlightRecorderStartupEvent 398 33261
=== the event type, in full ===
@Name("org.springframework.core.metrics.jfr.FlightRecorderStartupEvent")
@Category("Spring Application")
@Label("Startup Step")
@Description("Spring Application Startup")
class FlightRecorderStartupEvent extends jdk.jfr.Event {
@Label("Start Time")
@Timestamp("TICKS")
long startTime;
@Label("Duration")
@Timespan("TICKS")
long duration;
@Label("Event Thread")
@Description("Thread in which event was committed in")
Thread eventThread;
@Label("Stack Trace")
@Description("Stack Trace starting from the method the event was committed in")
StackTrace stackTrace;
long eventId;
=== the selector matters: the event is named by its FQCN, not 'StartupEvent' ===
--events StartupEvent -> 0 events
--events 'org.springframework.core.*' -> 398 events
=== 8 slowest startup steps, straight out of the recording ===
398 StartupEvent records in the recording
duration name / tags
PT6.544849841S spring.context.refresh
PT2.263845435S spring.beans.instantiate beanName=&entityManagerFactory,beanType=interface org.springframework.context.weaving.LoadTimeWeaverAware,
PT1.500763631S spring.context.beans.post-process
PT1.202591188S spring.context.beandef-registry.post-process postProcessor=org.springframework.context.annotation.ConfigurationClassPostProcessor@76b224cd,
PT1.176668418S spring.context.config-classes.parse classCount=130,
PT0.538651275S spring.beans.instantiate beanName=reportTemplateRegistry,
PT0.53548451S spring.beans.instantiate beanName=tariffCacheWarmer,beanType=class com.ankurm.startup.slow.TariffCacheWarmer,
PT0.515340537S spring.boot.webserver.create factory=class org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory,
=== what JFR gives you that the buffer does not: JVM context in the same file ===
jdk.ExecutionSample 345 3787
jdk.GCPhasePauseLevel1 132 5281
jdk.GCPhasePauseLevel2 50 1744
jdk.GCPhasePause 39 937
jdk.Compilation 16 452
jdk.ClassLoaderStatistics 10 260
total GC pause time during this startup: 39 events, 289.8 ms