Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions persistence-modules/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
<module>spring-data-jpa-repo</module>
<module>spring-data-jpa-repo-2</module>
<module>spring-data-jpa-repo-4</module>
<module>spring-data-jpa-repo-5</module>
<module>spring-data-jdbc</module>
<module>spring-data-jpa-simple</module>
<module>spring-data-keyvalue</module>
Expand Down
27 changes: 27 additions & 0 deletions persistence-modules/spring-data-jpa-repo-5/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-data-jpa-repo-5</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>

<modules>
<module>spring-data-jpa-aot</module>
<module>spring-data-jpa-aot-repository</module>
<module>spring-data-jpa-not-aot</module>
</modules>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.0-RC1</version>
</parent>

<properties>
<java.version>25</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
213,870 changes: 213,870 additions & 0 deletions persistence-modules/spring-data-jpa-repo-5/sample_output.txt

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions persistence-modules/spring-data-jpa-repo-5/scripts/load-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
set -euo pipefail

APP_COMMAND=""

case "$1" in
aot)
APP_COMMAND="java -Dspring.aot.enabled=true \
-Dspring.aot.repositories.enabled=false \
-agentlib:native-image-agent=config-output-dir=target/native-image-hints \
-jar spring-data-jpa-aot/target/spring-data-jpa-aot-0.0.1-SNAPSHOT.jar"
;;
aot-repo)
APP_COMMAND="java -Dspring.aot.enabled=true \
-Dspring.aot.repositories.enabled=true \
-agentlib:native-image-agent=config-output-dir=target/native-image-hints \
-jar spring-data-jpa-aot-repository/target/spring-data-jpa-aot-repository-0.0.1-SNAPSHOT.jar"
;;
non-aot)
APP_COMMAND="java -jar spring-data-jpa-not-aot/target/spring-data-jpa-not-aot-0.0.1-SNAPSHOT.jar"
;;
*)
echo "Error: Unknown mode '$1'. Use 'aot', 'aot-repo' or 'non-aot'."
exit 1
;;
esac

# --- 1. Start your script in the background ---
# Record start time in milliseconds
start_ns=$(date +%s%N)
$APP_COMMAND &
APP_PID=$!
echo "Started APP with PID $APP_PID"

# --- 2. Start sampling in the background ---
sudo sample $APP_PID > sample_output.txt &
SAMPLE_PID=$!
echo "Sampling process started (PID $SAMPLE_PID)"
echo "Waiting for service at http://localhost:8080/get-user ..."

# --- 3. Poll the endpoint until it returns HTTP 200 ---
while [ "$(curl -s -o /dev/null -L -w ''%{http_code}'' http://localhost:8080/get-user)" != 200 ]
do sleep 0.001;
done

# Capture elapsed time (SECONDS has fractional part) and the memory info
end_ns=$(date +%s%N)
elapsed_ms=$(((end_ns - start_ns) / 1000000))
MEMINFO_START=$(ps -o rss,vsz,pcpu,time -p $APP_PID | tail -1)

## load test
ab -n 1000 -t 10 -c 50 http://localhost:8080/get-user/ > ab_output.txt
MEMINFO_END=$(ps -o rss,vsz,pcpu,time -p $APP_PID | tail -1)

## --- 4. Stop sampling and show results ---
#echo "Stopping sample..."
#sudo kill -INT "$SAMPLE_PID"
#wait "$SAMPLE_PID" 2>/dev/null || true
#
## Give sample a moment to flush output
#sleep 2

# --- 5. Clean up ---
echo "Stopping startup process..."
kill "$APP_PID" 2>/dev/null || true

# Give app a moment to shutdown
sleep 3

echo "Done."

THREADS=$(grep -E "Thread_[0-9]+" sample_output.txt | wc -l)
echo "time elapsed $elapsed_ms millis"
echo "Threads: $THREADS"
echo "Memory/CPU START (RSS KB / VSZ KB / %CPU / CPU Time): $MEMINFO_START"
echo "Memory/CPU END (RSS KB / VSZ KB / %CPU / CPU Time): $MEMINFO_END"
71 changes: 71 additions & 0 deletions persistence-modules/spring-data-jpa-repo-5/scripts/startup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env bash
set -euo pipefail

APP_COMMAND=""

case "$1" in
aot)
APP_COMMAND="java -Dspring.aot.enabled=true \
-Dspring.aot.repositories.enabled=false \
-agentlib:native-image-agent=config-output-dir=target/native-image-hints \
-jar spring-data-jpa-aot/target/spring-data-jpa-aot-0.0.1-SNAPSHOT.jar"
;;
aot-repo)
APP_COMMAND="java -Dspring.aot.enabled=true \
-Dspring.aot.repositories.enabled=true \
-agentlib:native-image-agent=config-output-dir=target/native-image-hints \
-jar spring-data-jpa-aot-repository/target/spring-data-jpa-aot-repository-0.0.1-SNAPSHOT.jar"
;;
non-aot)
APP_COMMAND="java -jar spring-data-jpa-not-aot/target/spring-data-jpa-not-aot-0.0.1-SNAPSHOT.jar"
;;
*)
echo "Error: Unknown mode '$1'. Use 'aot', 'aot-repo' or 'non-aot'."
exit 1
;;
esac

# --- 1. Start your script in the background ---
# Record start time in milliseconds
start_ns=$(date +%s%N)
$APP_COMMAND &
APP_PID=$!
echo "Started APP with PID $APP_PID"

# --- 2. Start sampling in the background ---
sudo sample $APP_PID > sample_output.txt &
SAMPLE_PID=$!
echo "Sampling process started (PID $SAMPLE_PID)"
echo "Waiting for service at http://localhost:8080/get-user ..."

# --- 3. Poll the endpoint until it returns HTTP 200 ---
while [ "$(curl -s -o /dev/null -L -w ''%{http_code}'' http://localhost:8080/get-user)" != 200 ]
do sleep 0.001;
done

# Capture elapsed time (SECONDS has fractional part) and the memory info
end_ns=$(date +%s%N)
elapsed_ms=$(((end_ns - start_ns) / 1000000))
MEMINFO=$(ps -o rss,vsz,pcpu,time -p $APP_PID | tail -1)

## --- 4. Stop sampling and show results ---
#echo "Stopping sample..."
#sudo kill -INT "$SAMPLE_PID"
#wait "$SAMPLE_PID" 2>/dev/null || true
#
## Give sample a moment to flush output
#sleep 2

# --- 5. Clean up ---
echo "Stopping startup process..."
kill "$APP_PID" 2>/dev/null || true

# Give app a moment to shutdown
sleep 3

echo "Done."

THREADS=$(grep -E "Thread_[0-9]+" sample_output.txt | wc -l)
echo "time elapsed $elapsed_ms millis"
echo "Threads: $THREADS"
echo "Memory/CPU (RSS KB / VSZ KB / %CPU / CPU Time): $MEMINFO"
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
Compile AOT

```shell
mvn clean install -Paot-repo
```

Compilation time: `14.200 s`

1) run using maven and the spring-boot plugin:

```shell
mvn spring-boot:run -Dspring.aot.enabled=true -Dspring.aot.repositories.enabled=true
```

Startup times:
`Root WebApplicationContext: initialization completed in 477 ms`
`Started Application in 2.031 seconds`

2) run using the jar (same as 1 mostly)

```shell
java -Dspring.aot.enabled=true \
-Dspring.aot.repositories.enabled=true \
-agentlib:native-image-agent=config-output-dir=target/native-image-hints \
-jar target/spring-data-jpa-aot-repository-0.0.1-SNAPSHOT.jar
```

Startup times:
`Root WebApplicationContext: initialization completed in 452 ms`
`Started Application in 3.26 seconds`

## Performance

### Time startup
from root `sudo ./scripts/startup.sh aot-repo`:
```shell
time elapsed 5296 millis
Threads: 58
Memory/CPU (RSS KB / VSZ KB / %CPU / CPU Time): 406992 523697872 167.5 0:10.91
```

### Time startup
from root `sudo ./scripts/load-test.sh aot-repo`:
```shell
time elapsed 5298 millis
Threads: 93
Memory/CPU START (RSS KB / VSZ KB / %CPU / CPU Time): 450816 557256448 205.1 0:11.72
Memory/CPU END (RSS KB / VSZ KB / %CPU / CPU Time): 439568 523846176 830.3 1:18.58
```

**NOTE**:
AOT is a mandatory step to transform a Spring application to a native executable, so it is automatically enabled when running within a native image. However it is also possible to use AOT optimizations on the JVM by setting the spring.aot.enabled System
property to true.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)


Server Software:
Server Hostname: localhost
Server Port: 8080

Document Path: /get-user/
Document Length: 93 bytes

Concurrency Level: 50
Time taken for tests: 10.002 seconds
Complete requests: 1501
Failed requests: 0
Non-2xx responses: 1504
Total transferred: 297792 bytes
HTML transferred: 139872 bytes
Requests per second: 150.07 [#/sec] (mean)
Time per request: 333.186 [ms] (mean)
Time per request: 6.664 [ms] (mean, across all concurrent requests)
Transfer rate: 29.07 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.0 0 6
Processing: 34 327 179.9 307 836
Waiting: 32 307 170.7 292 795
Total: 34 327 180.2 307 840

Percentage of the requests served within a certain time (ms)
50% 307
66% 402
75% 468
80% 502
90% 576
95% 625
98% 685
99% 723
100% 840 (longest request)
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

<parent>
<groupId>com.baeldung</groupId>
<artifactId>spring-data-jpa-repo-5</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../spring-data-jpa-repo-5</relativePath>
</parent>

<artifactId>spring-data-jpa-aot-repository</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<profiles>
<profile>
<id>aot-repo</id>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.baeldung.spring.aotrepository.Application</mainClass>
<jvmArguments>
-agentlib:native-image-agent=config-output-dir=target/native-image-hints/
</jvmArguments>
</configuration>
<executions>
<execution>
<id>process-aot</id>
<goals>
<goal>process-aot</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.baeldung.spring.aotrepository;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

private static final Log logger = LogFactory.getLog(Application.class);

public static void main(String[] args) {
logger.info("Application starts..");

SpringApplication.run(Application.class, args);
}
}
Loading