-
Notifications
You must be signed in to change notification settings - Fork 40.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Executable JAR application startup is slower after 3.2.0 when Hibernate scanner is not disabled #40125
Comments
Thanks for reporting this @deathy. Do you by any chance have a sample application that replicates the performance issues you're seeing? |
Yes I'll try to create a proper sample in the next days. Might take some time, have to see with different numbers/sizes of files and need to see if it's the same with an in-memory database. Meanwhile I have some numbers from debugging my app startup:
Grouping the 14033 parts by DataBlock::size, top 5:
Also ran async-profiler with event=alloc: |
Observed during debugging: JDK JarInputStream/ZipInputStream called from hibernate loader read sequentially. Reading sequentially next 512 or how ever many bytes (saw some 3 byte reads for iterating entries) re-incur the whole traversal that was already done since It can't skip ahead even though |
@deathy just to double check, are you using the latest 3.2.x release? |
@philwebb yes I'm on 3.2.4 with original application. I finally managed to make a sample: https://github.com/deathy/spring-startup-test In automatic configuration since #15565 and #15321 the Hibernate Scanner is disabled by default. In my original app I added There I also had two persistence contexts (separate DBs) so the scan was being performed twice. The sequential iteration through Hibernate Scanner questions:
|
@deathy I've added a few optimization but unfortunately I don't think there is much that we can do to solve this one. It looks like If the Hibernate Scanner could be changed, I think it could be a lot more optimal with our nested jars. Specifically, if they could do This might be something that could be prototyped, but hopefully a typical Boot application won't hit the problem. For your application, you might want to consider using moving to the exploded archive format. We've been doing some work in Spring Boot 3.3 that should make exploded archives easier to create. See https://docs.spring.io/spring-boot/reference/deployment/efficient.html#deployment.efficient.unpacking. |
I investigated some slow application startup behavior and it seems Executable JAR can be extremely slower than alternatives.
The docs mention "slight" differences but it seems there are some cases where this can be a big difference
Times observed:
java -jar myapp.jar
jar -xf myapp.jar
java org.springframework.boot.loader.launch.JarLauncher
java -cp "BOOT-INF/classes:BOOT-INF/lib/*" com.example.MyApplication
So 4-5X difference between executable jar and JarLauncher, minimal difference unpacked with/without JarLauncher
I dug into my logs and saw that there was a 3X jump in November last year that coincided with upgrading to Spring Boot 3.2.0
That lead me to possible cause from rewriting of nested jar support in #37668
Another big jump I observed afterwards was after adding more static resources in
/static/
(CSS/JS/source maps, fonts .ttf/.woff2).The application does have a lot of static resources inside, especially in development/test (source maps, unminified JS/CSS).
Profiled using async-profiler launched as agent on startup. Lots of C2/other tasks but biggest part of spring init was this:
So the initial trigger is EntityManager lookup and Hibernate scanning classpath for entities.
But most of the time is spent in
org.springframework.book.loader.zip.
DataBlockInputStream
andVirtualDataBlock
which leads again to #37668 where those were created.Actual disk reads are minimal and hibernate parsing is a thin slice of it. Hibernate is only parsing
.class
files not static resources but it seems the boot loader fully reads all static resources and also creates a lot of virtual blocks.The difference is quite large so I think it merits some further investigation.
It's also quite counter-intuitive, adding static resources can drastically increase time for EntityManager initialization.
The text was updated successfully, but these errors were encountered: