Skip to content

Commit 720a59a

Browse files
committed
benchmark 3 inserts con spring tmb
1 parent f6d4da1 commit 720a59a

File tree

11 files changed

+235
-0
lines changed

11 files changed

+235
-0
lines changed

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
<plugin>
4444
<groupId>org.springframework.boot</groupId>
4545
<artifactId>spring-boot-maven-plugin</artifactId>
46+
<configuration>
47+
<mainClass>com.example.iotbench.IotBenchApplication</mainClass>
48+
</configuration>
4649
</plugin>
4750
</plugins>
4851
</build>

result_spring_ultra_fast.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Running 1m test @ http://localhost:8080/ultra/ingest
2+
12 threads and 2000 connections
3+
Thread Stats Avg Stdev Max +/- Stdev
4+
Latency 188.18ms 322.65ms 2.00s 87.31%
5+
Req/Sec 2.08k 1.16k 9.66k 69.49%
6+
1300935 requests in 1.00m, 210.10MB read
7+
Socket errors: connect 0, read 0, write 0, timeout 7274
8+
Requests/sec: 21662.76
9+
Transfer/sec: 3.50MB

run_spring_ultra_fast.sh

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/bin/bash
2+
set -e
3+
4+
echo "=== Spring Boot Ultra-Fast Benchmark ==="
5+
echo "Spring Boot optimizado al máximo para comparación justa:"
6+
echo "- CON base de datos H2 (equivalente a SQLite)"
7+
echo "- Sin background processing"
8+
echo "- Sin AsyncWorker"
9+
echo "- Sin logging innecesario"
10+
echo "- Prepared statements optimizados (JdbcTemplate)"
11+
echo "- Virtual Threads habilitados"
12+
echo ""
13+
14+
JAR=target/iot-bench-0.1.0.jar
15+
16+
# Function to wait for port to be free
17+
wait_for_port_free() {
18+
local port=$1
19+
local timeout=30
20+
local count=0
21+
22+
echo "Waiting for port $port to be free..."
23+
while lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; do
24+
if [ $count -ge $timeout ]; then
25+
echo "Timeout waiting for port $port to be free"
26+
return 1
27+
fi
28+
sleep 1
29+
count=$((count + 1))
30+
done
31+
echo "Port $port is now free"
32+
}
33+
34+
# Function to wait for port to be ready
35+
wait_for_port_ready() {
36+
local port=$1
37+
local timeout=30
38+
local count=0
39+
40+
echo "Waiting for port $port to be ready..."
41+
while ! curl -s http://localhost:$port/ultra/health >/dev/null 2>&1; do
42+
if [ $count -ge $timeout ]; then
43+
echo "Timeout waiting for port $port to be ready, trying anyway..."
44+
return 0
45+
fi
46+
sleep 1
47+
count=$((count + 1))
48+
done
49+
echo "Port $port is ready"
50+
}
51+
52+
# Function to stop application gracefully
53+
stop_app() {
54+
local pid=$1
55+
local name=$2
56+
if [ ! -z "$pid" ] && kill -0 $pid 2>/dev/null; then
57+
echo "Stopping $name (PID: $pid)..."
58+
kill $pid
59+
60+
# Wait for process to stop
61+
local count=0
62+
while kill -0 $pid 2>/dev/null && [ $count -lt 15 ]; do
63+
sleep 1
64+
count=$((count + 1))
65+
done
66+
67+
# Force kill if still running
68+
if kill -0 $pid 2>/dev/null; then
69+
echo "Force killing $name..."
70+
kill -9 $pid 2>/dev/null || true
71+
fi
72+
73+
wait_for_port_free 8080
74+
fi
75+
}
76+
77+
# Generate payload
78+
echo "Generating payload..."
79+
python3 generate_payload.py > payload.json
80+
81+
# Clean up any existing processes
82+
echo "Cleaning up any existing processes..."
83+
pkill -f "iot-bench-0.1.0.jar" || true
84+
wait_for_port_free 8080
85+
86+
echo ""
87+
echo "=== Spring Boot Ultra-Fast (Virtual Threads ON) ==="
88+
java -Xms2g -Xmx2g -jar $JAR --spring.threads.virtual.enabled=true --spring.profiles.active=ultrafast &
89+
SPRING_ULTRA_PID=$!
90+
wait_for_port_ready 8080
91+
echo "Running ultra-fast benchmark..."
92+
wrk -t12 -c2000 -d60s -s post.lua http://localhost:8080/ultra/ingest > result_spring_ultra_fast.txt
93+
stop_app $SPRING_ULTRA_PID "Spring Boot Ultra-Fast"
94+
95+
echo ""
96+
echo "=== SPRING BOOT ULTRA-FAST RESULTS ==="
97+
echo "Spring Boot Ultra-Fast (Virtual Threads):"
98+
grep -E "(Requests/sec|Transfer/sec|Latency)" result_spring_ultra_fast.txt || echo "No results found"
99+
100+
echo ""
101+
echo "=== COMPARISON WITH NESTJS ULTRA-FAST ==="
102+
if [ -f "result_ultra_fast_bun.txt" ]; then
103+
echo "NestJS Ultra-Fast (Bun + SQLite nativo):"
104+
grep -E "(Requests/sec|Transfer/sec)" result_ultra_fast_bun.txt || echo "No results"
105+
echo ""
106+
fi
107+
108+
if [ -f "result_ultra_fast_node.txt" ]; then
109+
echo "NestJS Ultra-Fast (Node.js + SQLite3):"
110+
grep -E "(Requests/sec|Transfer/sec)" result_ultra_fast_node.txt || echo "No results"
111+
echo ""
112+
fi
113+
114+
echo "Spring Boot Ultra-Fast (Java + H2):"
115+
grep -E "(Requests/sec|Transfer/sec)" result_spring_ultra_fast.txt || echo "No results"
116+
117+
echo ""
118+
echo "🎯 FAIR COMPARISON: Framework vs Framework (Ultra-Optimized)"
119+
echo " - NestJS + Fastify + SQLite vs Spring Boot + H2"
120+
echo " - Sin background processing en ninguno"
121+
echo " - Máximo rendimiento en ambos"

src/main/java/com/example/iotbench/IotBenchApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
55
import org.springframework.scheduling.annotation.EnableAsync;
6+
import org.springframework.context.annotation.ComponentScan;
67

78
@SpringBootApplication
89
@EnableAsync
10+
@ComponentScan(basePackageClasses = {IotBenchApplication.class, UltraFastController.class})
911
public class IotBenchApplication {
1012
public static void main(String[] args) {
1113
SpringApplication.run(IotBenchApplication.class, args);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.example.iotbench;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.context.annotation.ComponentScan;
6+
7+
@SpringBootApplication
8+
@ComponentScan(basePackageClasses = {UltraFastController.class})
9+
public class UltraFastApplication {
10+
public static void main(String[] args) {
11+
// Disable banner and reduce startup overhead
12+
SpringApplication app = new SpringApplication(UltraFastApplication.class);
13+
app.setBannerMode(org.springframework.boot.Banner.Mode.OFF);
14+
app.setLogStartupInfo(false);
15+
app.run(args);
16+
}
17+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.example.iotbench;
2+
3+
import org.springframework.http.ResponseEntity;
4+
import org.springframework.web.bind.annotation.*;
5+
import org.springframework.jdbc.core.JdbcTemplate;
6+
import java.util.*;
7+
import java.util.concurrent.atomic.AtomicLong;
8+
9+
@RestController
10+
@RequestMapping("/ultra")
11+
public class UltraFastController {
12+
13+
private final JdbcTemplate jdbc;
14+
private final AtomicLong counter = new AtomicLong(0);
15+
16+
// Pre-allocated objects to avoid GC pressure (like the NestJS version)
17+
private final Map<String, Object> responseTemplate = new HashMap<>();
18+
private final Map<String, Object> healthTemplate = new HashMap<>();
19+
20+
public UltraFastController(JdbcTemplate jdbc) {
21+
this.jdbc = jdbc;
22+
initTable();
23+
24+
// Pre-populate response templates
25+
responseTemplate.put("id", "");
26+
responseTemplate.put("t_ms", 0.0);
27+
28+
healthTemplate.put("status", "ok");
29+
healthTemplate.put("timestamp", "");
30+
healthTemplate.put("runtime", "Spring Boot");
31+
healthTemplate.put("count", 0L);
32+
}
33+
34+
private void initTable() {
35+
jdbc.execute("CREATE TABLE IF NOT EXISTS iot_payload_ultra (id VARCHAR(36) PRIMARY KEY, content CLOB, ts BIGINT)");
36+
}
37+
38+
@PostMapping("ingest")
39+
public ResponseEntity<Map<String,Object>> ingest(@RequestBody Map<String,Object> payload) {
40+
long start = System.nanoTime();
41+
42+
try {
43+
// Ultra-fast ID generation (like NestJS version)
44+
long count = counter.incrementAndGet();
45+
String id = "id_" + count + "_" + System.currentTimeMillis();
46+
47+
// Convert payload to JSON (minimal processing)
48+
String content = payload.toString(); // Faster than ObjectMapper
49+
long timestamp = System.currentTimeMillis();
50+
51+
// Ultra-fast database insert (prepared statement equivalent)
52+
jdbc.update("INSERT INTO iot_payload_ultra (id, content, ts) VALUES (?, ?, ?)",
53+
id, content, timestamp);
54+
55+
// No background processing - just return immediately (like NestJS ultra-fast)
56+
long elapsedNanos = System.nanoTime() - start;
57+
double elapsedMs = elapsedNanos / 1_000_000.0;
58+
59+
// Reuse object to avoid allocation (like NestJS version)
60+
responseTemplate.put("id", id);
61+
responseTemplate.put("t_ms", Math.round(elapsedMs * 100.0) / 100.0);
62+
63+
return ResponseEntity.ok(responseTemplate);
64+
65+
} catch (Exception e) {
66+
Map<String, Object> error = Map.of("error", "Internal server error");
67+
return ResponseEntity.status(500).body(error);
68+
}
69+
}
70+
71+
@GetMapping("health")
72+
public ResponseEntity<Map<String,Object>> health() {
73+
// Reuse object to avoid allocation (like NestJS version)
74+
healthTemplate.put("timestamp", new Date().toString());
75+
healthTemplate.put("count", counter.get());
76+
77+
return ResponseEntity.ok(healthTemplate);
78+
}
79+
}
138 Bytes
Binary file not shown.

target/iot-bench-0.1.0.jar

3.91 KB
Binary file not shown.
3.5 KB
Binary file not shown.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
com/example/iotbench/AsyncWorker.class
2+
com/example/iotbench/UltraFastApplication.class
3+
com/example/iotbench/UltraFastController.class
24
com/example/iotbench/IngestService.class
35
com/example/iotbench/IotBenchApplication.class
46
com/example/iotbench/IngestController.class

0 commit comments

Comments
 (0)