Skip to content

Práctica 2 de la asignatura de Programación Concurrente. Realizada por Pablo García, Juan Sepúlveda y Nerea Quintanilla

Notifications You must be signed in to change notification settings

nquinbla/PC-2_Benchmarking

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

[ PC ] BENCHMARKING DE ESTRATEGIAS DE PROGRAMACIÓN MULTIHILO CON SPRING BOOT

Enlace GitHub: https://github.com/nquinbla/PC-2_Benchmarking.git

[👥] Integrantes

Nombre completo NPS
Pablo García 165210
Juan Sepúlveda 154412
Nerea Quintanilla 154409

[📝] Descripción del proyecto

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.

[📑] Índice

[🗂️] Estructura del proyecto

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

[🌳] Árbol de directorios

Ver bloque anterior. Se sigue la convención estándar de Spring Boot y Maven.

[🧭] Estrategia

  • 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 BenchmarkSummary con totalTasks, threadsUsed y la lista results[].

[🛠️] Metodología y diseño

  • Arquitectura: Controller + Service + DTOs.
  • Concurrencia: ExecutorService (FixedThreadPool) y ThreadPoolTaskExecutor (Spring).
  • Asíncrono: @EnableAsync en la app y @Async en AsyncTaskService.
  • Configuración de hilos: application.properties
    • benchmark.executor.core, benchmark.executor.max, benchmark.executor.queue.
  • Seguridad de estado: el último resultado se guarda en AtomicReference para lecturas seguras.

[▶️] Cómo ejecutar la práctica

Desde IntelliJ: Run la clase app.BenchmarkingApp.

Desde terminal (Windows, con Maven instalado):

mvn spring-boot:run

Generar JAR y ejecutar:

mvn clean package -DskipTests
java -jar target\pc-2-benchmarking-0.0.1-SNAPSHOT.jar

Abrir en el navegador:

[🔌] Endpoints

  • 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 Content si no hay.
  • GET /benchmark/modes
    • Lista los modos disponibles y su descripción.

[🎯] Resultados esperados

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 }
  ]
}

[📏] Medición y benchmarking

  • 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 usa min(threads, maxPoolSize) como hilos efectivos del executor.
  • Throughput: tasks / (timeMs / 1000).

[📊] Análisis de resultados

  • No se espera escalado lineal por overhead de scheduling y contención.
  • Aumentar iterations ayuda a reducir ruido cuando los tiempos son muy bajos.
  • Para cargas CPU‑bound, una guía para threads es ≈ núcleos lógicos.

[✅] Conclusiones

  • La comparación entre Executor manual y @Async suele arrojar rendimientos similares si comparten límites del pool.
  • SEQUENTIAL aporta la línea base para calcular speedup y efficiency.

[⚠️] Problemas conocidos

  • Si no se ha ejecutado ningún benchmark, GET /benchmark/result devuelve 204.
  • Los resultados pueden variar entre ejecuciones por interferencia de otras cargas del sistema.

[🔗] Referencias

[🧾] Licencia

MIT License. Significa que puedes usar, copiar, modificar y distribuir este código libremente, siempre que mantengas el aviso de copyright y la licencia.

About

Práctica 2 de la asignatura de Programación Concurrente. Realizada por Pablo García, Juan Sepúlveda y Nerea Quintanilla

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published