Enlace GitHub: https://github.com/nquinbla/PC-2_Benchmarking.git
| Nombre completo | NPS |
|---|---|
| Pablo García | 165210 |
| Juan Sepúlveda | 154412 |
| Nerea Quintanilla | 154409 |
Aplicación Spring Boot (Java 21) para comparar el rendimiento de tres estrategias de ejecución de tareas CPU‑bound:
- SEQUENTIAL (monohilo)
- EXECUTOR_SERVICE (pool manual configurable)
- SPRING_ASYNC (@Async con ThreadPoolTaskExecutor)
Cada benchmark se lanza vía API REST y devuelve métricas de tiempo, aceleración (speedup), eficiencia y promedio por tarea.
- Estructura del proyecto
- Estrategia
- Metodología y diseño
- Cómo ejecutar la práctica
- Endpoints
- Medición y benchmarking
- Resultados esperados
- Análisis de resultados
- Problemas conocidos
- Historial de cambios
- Referencias
- Licencia
Proyecto Maven con Spring Boot 3.3.4.
PC-2_Benchmarking/
├─ src/
│ ├─ main/
│ │ ├─ java/app/
│ │ │ ├─ BenchmarkingApp.java # @SpringBootApplication + @EnableAsync
│ │ │ ├─ config/ExecutorConfig.java # ThreadPoolTaskExecutor "benchmarkExecutor"
│ │ │ ├─ controller/BenchmarkController.java
│ │ │ ├─ service/BenchmarkService.java # Ejecuta los 3 modos y calcula métricas
│ │ │ ├─ service/AsyncTaskService.java # @Async para modo SPRING_ASYNC
│ │ │ ├─ model/BenchmarkParams.java # DTO de entrada
│ │ │ ├─ model/BenchmarkSummary.java # DTO de salida (global)
│ │ │ ├─ model/Mode.java # Enum de modos
│ │ │ ├─ model/ModeInfo.java # DTO informativo de modos
│ │ │ ├─ model/ModeResult.java # DTO de métricas por modo (incluye avgMsPerTask)
│ │ │ └─ workload/CpuIntensiveTask.java # Carga CPU-bound simulada
│ │ └─ resources/
│ │ ├─ application.properties
│ │ └─ static/
│ │ ├─ index.html # UI minimal para lanzar el benchmark
│ │ ├─ css/styles.css # Estilos modernos + modal de ayuda
│ │ └─ js/{api.js, app.js} # Llamadas y renderizado de resultados
│ └─ test/
│ └─ java/app/
│ ├─ controller/BenchmarkControllerTest.java
│ ├─ service/BenchmarkServiceTest.java
│ └─ workload/CpuIntensiveTaskTest.java
├─ pom.xml
└─ README.md
Ver bloque anterior. Se sigue la convención estándar de Spring Boot y Maven.
- Ejecutar N tareas CPU‑bound en 3 modos (secuencial, pool manual, @Async).
- Medir con
System.nanoTime()tiempos totales por modo. - Calcular métricas:
timeMs,avgMsPerTask,speedup,efficiency,throughput. - Devolver un
BenchmarkSummarycontotalTasks,threadsUsedy la listaresults[].
- Arquitectura: Controller + Service + DTOs.
- Concurrencia:
ExecutorService(FixedThreadPool) yThreadPoolTaskExecutor(Spring). - Asíncrono:
@EnableAsyncen la app y@AsyncenAsyncTaskService. - Configuración de hilos:
application.propertiesbenchmark.executor.core,benchmark.executor.max,benchmark.executor.queue.
- Seguridad de estado: el último resultado se guarda en
AtomicReferencepara lecturas seguras.
Desde IntelliJ: Run la clase app.BenchmarkingApp.
Desde terminal (Windows, con Maven instalado):
mvn spring-boot:runGenerar JAR y ejecutar:
mvn clean package -DskipTests
java -jar target\pc-2-benchmarking-0.0.1-SNAPSHOT.jarAbrir en el navegador:
POST /benchmark/start?tasks=50&threads=8&iterations=1000- Lanza el benchmark en los 3 modos y devuelve el resumen.
GET /benchmark/result- Devuelve el último resultado o
204 No Contentsi no hay.
- Devuelve el último resultado o
GET /benchmark/modes- Lista los modos disponibles y su descripción.
Respuesta (ejemplo):
{
"totalTasks": 50,
"threadsUsed": 8,
"results": [
{ "mode": "SEQUENTIAL", "timeMs": 4321, "avgMsPerTask": 86.42, "speedup": 1.0, "efficiency": 1.0, "throughput": 11.57 },
{ "mode": "EXECUTOR_SERVICE", "timeMs": 987, "avgMsPerTask": 19.74, "speedup": 4.38, "efficiency": 0.55, "throughput": 50.66 },
{ "mode": "SPRING_ASYNC", "timeMs": 1012, "avgMsPerTask": 20.24, "speedup": 4.27, "efficiency": 0.53, "throughput": 49.41 }
]
}- Tiempo total por modo: cronometraje con
System.nanoTime(). - Promedio por tarea:
timeMs / tasks. - Aceleración (speedup):
T_secuencial / T_modo. - Eficiencia:
speedup / hilos.- En
SPRING_ASYNC, se usamin(threads, maxPoolSize)como hilos efectivos del executor.
- En
- Throughput:
tasks / (timeMs / 1000).
- No se espera escalado lineal por overhead de scheduling y contención.
- Aumentar
iterationsayuda a reducir ruido cuando los tiempos son muy bajos. - Para cargas CPU‑bound, una guía para
threadses ≈ núcleos lógicos.
- La comparación entre Executor manual y
@Asyncsuele arrojar rendimientos similares si comparten límites del pool. SEQUENTIALaporta la línea base para calcularspeedupyefficiency.
- Si no se ha ejecutado ningún benchmark,
GET /benchmark/resultdevuelve204. - Los resultados pueden variar entre ejecuciones por interferencia de otras cargas del sistema.
- Campus UAX — Asignatura: Programación Concurrente (requiere login): https://campus.uax.es/
- CodePen — Prototipado y ejemplos de interfaz: https://codepen.io/
- Documentación Spring Boot: https://spring.io/projects/spring-boot
- Concurrencia en Java (java.util.concurrent): https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/package-summary.html
- Documentación oficial de Java SE: https://docs.oracle.com/en/java/javase/
MIT License. Significa que puedes usar, copiar, modificar y distribuir este código libremente, siempre que mantengas el aviso de copyright y la licencia.