Skip to content

Frtrillo/spring-boot-virtual-threads-off-vs-on-vs-nodejs-typescript-benchmark

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Suite de Benchmarks IoT: Análisis Integral de Rendimiento

🎯 Resumen Ejecutivo

Este repositorio contiene una suite completa de benchmarks comparando Java (Spring Boot), Node.js y Bun a través de diferentes patrones de carga de trabajo. Nuestros hallazgos desafían la sabiduría convencional sobre el rendimiento de aplicaciones empresariales y revelan insights sorprendentes sobre los runtimes modernos de JavaScript.

🏆 Hallazgos Clave

  1. Los runtimes de JavaScript superan consistentemente a Java en tareas intensivas en CPU por 3-6x
  2. El Modo Cluster de Node.js domina cargas I/O pesadas con 87,000+ RPS (196x más rápido que Java)
  3. Bun sobresale en cargas computacionales y muestra rendimiento excepcional con SQLite
  4. Los Virtual Threads de Java son mejores para escenarios específicos de bloqueo I/O, no rendimiento general
  5. El overhead del framework importa - las decisiones arquitectónicas impactan más el rendimiento que la selección del lenguaje

📊 Categorías de Benchmarks

1. Rendimiento Computacional Puro (Cálculo de Pi)

Prueba las capacidades de computación matemática a través de diferentes runtimes.

2. Rendimiento Computacional a Nivel Framework (Pi con NestJS vs Spring Boot)

Rendimiento real de frameworks web para tareas intensivas en CPU.

3. Rendimiento de Lógica de Negocio Empresarial (Procesamiento Realista de Órdenes)

Lógica de negocio intensiva en CPU con operaciones I/O mínimas.

4. Rendimiento I/O Multi-Core (Cargas Empresariales)

Aplicaciones de alta concurrencia intensivas en I/O con utilización adecuada de múltiples núcleos.


🥇 Resumen de Resultados de Rendimiento

Rendimiento Computacional Puro (Cálculo de Pi)

100 Millones de Iteraciones:

Posición Runtime Tiempo Tasa (ops/seg) Rendimiento vs Java
🥇 Bun 96.66ms 1,034,587,555 1.82x más rápido
🥈 Node.js 111.15ms 899,676,344 1.58x más rápido
🥉 Java 175.71ms 569,132,664 Línea base

1 Billón de Iteraciones:

Posición Runtime Tiempo Tasa (ops/seg) Rendimiento vs Java
🥇 Bun 958.33ms 1,043,486,926 1.03x más rápido
🥈 Java 984.05ms 1,016,203,578 Línea base
🥉 Node.js 1,788.66ms 559,079,217 0.55x más lento

Rendimiento de Framework (NestJS vs Spring Boot)

Cálculo de Pi con Stack Completo de Framework Web:

Framework Tiempo (100M iteraciones) Iteraciones/seg Ventaja de Rendimiento
🥇 NestJS 114.4ms 874,090,215 1.50x más rápido
🥈 Spring Boot 171.43ms 583,316,988 Línea base

Lógica de Negocio Empresarial (Procesamiento Realista de Órdenes)

Lógica de Negocio Intensiva en CPU con I/O Mínimo:

Framework RPS Latencia Rendimiento vs Java VT
🥇 Bun Single Thread 25,345 58.90ms 6.1x más rápido
🥈 Node.js Cluster 14,725 104.46ms 3.5x más rápido
🥉 Node.js Single 6,185 237.93ms 1.5x más rápido
Java Tradicional 4,497 4.52ms 1.08x más rápido que VT
Java Virtual Threads 4,161 2.35ms Línea base

Rendimiento I/O Multi-Core (Comparación Justa)

Cargas Empresariales Intensivas en I/O:

Framework RPS Latencia Núcleos CPU Arquitectura
🥇 Node.js Cluster 87,047 35ms 8 núcleos 8 procesos worker
🥈 Java Virtual Threads 444 1.72s 8 núcleos Virtual threads
🥉 Bun Single 248 6.05s 1 núcleo Single-threaded

🔍 Análisis Técnico

Por Qué Sobresalen los Runtimes de JavaScript

1. Optimización JIT Agresiva

  • V8 (Node.js): El compilador TurboFan optimiza operaciones matemáticas
  • JavaScriptCore (Bun): Optimización aún más agresiva para computaciones
  • Inline caching: Las llamadas a métodos se convierten en acceso directo a memoria
  • Especialización de tipos: Los números se convierten en enteros nativos de máquina

2. Eficiencia Single-Threaded

  • Sin cambio de contexto: La CPU permanece en rutas de ejecución calientes
  • Localidad de caché: Todos los datos permanecen en caché de CPU
  • Sin overhead de sincronización: Sin locks, sin coordinación
  • Ejecución predecible: Sin interrupciones de programación de threads

3. Ingeniería Moderna de Runtime

  • Operaciones de punto flotante rápidas: Optimizadas para cálculos matemáticos
  • Creación eficiente de objetos: Overhead mínimo de asignación
  • Recolección inmediata de basura: Objetos de vida corta limpiados instantáneamente

Por Qué Java Lucha en Estos Benchmarks

1. Overhead de Asignación de Objetos

// Cada cálculo crea objetos
BigDecimal discount = totalAmount.multiply(discountRate);
OrderCalculation calc = new OrderCalculation(total, discount, tax, final);
  • Presión de memoria: Las asignaciones frecuentes disparan GC
  • Overhead de constructor: Costos de creación de objetos
  • Dispatch de métodos: Las llamadas virtuales tienen overhead

2. Presión de Garbage Collection

  • Pausas stop-the-world: Incluso G1GC tiene micro-pausas
  • Alta tasa de asignación: Dispara ciclos frecuentes de GC
  • Fragmentación de memoria: Los objetos fragmentan el espacio heap

3. Overhead de Coordinación de Threads

  • Programación de Virtual Threads: Aún tiene costos de coordinación
  • Contención de recursos compartidos: Pools de base de datos, cachés
  • Sincronización de memoria: Coherencia de caché entre núcleos

🎯 Cuándo Elegir Cada Tecnología

Elegir Bun Cuando:

  • APIs de alto rendimiento: Necesitas el máximo de requests/segundo
  • Computaciones intensivas en CPU: Operaciones matemáticas, procesamiento de datos
  • Aplicaciones SQLite: El rendimiento nativo de SQLite es 11x más rápido que Node.js
  • Desarrollo moderno: Equipo cómodo con tecnología de vanguardia
  • Eficiencia de recursos: Menor uso de memoria y mejor rendimiento

Elegir Node.js Cuando:

  • Ecosistema maduro: Necesitas soporte extenso de librerías
  • Experiencia del equipo: Habilidades existentes en JavaScript/TypeScript
  • Cargas balanceadas: Mezcla de I/O y computación
  • Estabilidad en producción: Historial comprobado en empresas
  • Microservicios: Servicios ligeros y enfocados

Elegir Java + Spring Boot Cuando:

  • Aplicaciones empresariales complejas: Bases de código grandes y mantenibles
  • Requisitos de seguridad de tipos: Detección de errores en tiempo de compilación
  • Integraciones empresariales: Conectividad con sistemas legacy
  • Equipos grandes: Múltiples desarrolladores, mantenimiento a largo plazo
  • Cumplimiento regulatorio: Trails de auditoría, frameworks de seguridad
  • Aversión al riesgo: Stack tecnológico predecible y probado

Elegir Modo Cluster de Node.js Cuando:

  • Máximo throughput I/O: Necesitas 80,000+ RPS
  • APIs de alta concurrencia: Miles de conexiones simultáneas
  • Sistemas en tiempo real: Requisitos de ultra-baja latencia
  • Escalamiento horizontal: Puede utilizar todos los núcleos de CPU efectivamente

🚨 La Paradoja Empresarial

Por Qué las Empresas Eligen Java A Pesar de la Desventaja de Rendimiento

Nuestros benchmarks muestran que JavaScript supera consistentemente a Java, sin embargo las empresas continúan eligiendo Java. Aquí está el por qué:

1. Productividad del Desarrollador Sobre Rendimiento Bruto

  • Seguridad de tipos: Prevención de errores en tiempo de compilación
  • Soporte de IDE: Herramientas superiores y debugging
  • Mantenibilidad del código: Refactoring y extensión más fáciles
  • Escalamiento del equipo: Mayor pool de desarrolladores Java empresariales

2. Madurez del Ecosistema

  • Ecosistema masivo de librerías: Soluciones para cada necesidad empresarial
  • Madurez de frameworks: Spring, Hibernate, patrones establecidos
  • Integraciones empresariales: Conectividad SAP, Oracle, mainframe
  • Monitoreo y observabilidad: Herramientas JMX, APM, profiling

3. Gestión de Riesgos

  • Comportamiento predecible: Características de rendimiento conocidas
  • Soporte a largo plazo: Ciclos de lanzamiento estables
  • Comodidad corporativa: "Nadie es despedido por elegir Java"
  • Cumplimiento: Frameworks de seguridad y auditoría establecidos

4. Los Cuellos de Botella Reales

Las aplicaciones empresariales típicamente están limitadas por:

  1. Consultas a base de datos (no lógica de aplicación)
  2. I/O de red (llamadas a APIs externas)
  3. Procesos humanos (flujos de aprobación)
  4. Productividad del equipo (velocidad de desarrollo)

El rendimiento rara vez es el cuello de botella real en sistemas empresariales.


📈 Metodología de Benchmarks

Entorno de Prueba

  • Hardware: Apple M1/M2, 8 núcleos, 16GB RAM
  • Sistema Operativo: macOS 14.6.0
  • Java: OpenJDK 21+ con Virtual Threads
  • Node.js: v20+ con motor V8
  • Bun: Última versión con motor JavaScriptCore

Configuración de Prueba

  • Duración: 60 segundos por prueba
  • Conexiones: 1,000-2,000 concurrentes
  • Threads: 8-12 threads
  • Warmup: 10-15 segundos (extendido para JIT de Java)
  • Herramienta: wrk HTTP benchmarking tool

Tipos de Carga de Trabajo

  1. Computación pura: Algoritmos matemáticos
  2. Overhead de framework: Stack completo de framework web real
  3. Lógica de negocio: Cálculos empresariales complejos
  4. Operaciones I/O: Consultas a base de datos, operaciones de archivos
  5. Cargas mixtas: Combinación de CPU e I/O

💡 Insights Clave y Conclusiones

1. JavaScript Moderno es Rápido

Los runtimes de JavaScript han evolucionado hacia motores de alto rendimiento capaces de superar lenguajes tradicionalmente "compilados" en muchos escenarios.

2. La Arquitectura Importa Más Que el Lenguaje

  • El Modo Cluster de Node.js logra 196x mejor rendimiento que enfoques single-threaded
  • La utilización justa de múltiples núcleos es crucial para comparaciones significativas
  • El overhead del framework puede negar las ventajas del runtime

3. La Carga de Trabajo Determina el Ganador

  • Intensivo en I/O: El Modo Cluster de Node.js domina
  • Intensivo en CPU: Bun sobresale consistentemente
  • Complejidad empresarial: Java proporciona mejor mantenibilidad
  • Cargas mixtas: Node.js ofrece buen balance

4. Los Virtual Threads Son Especializados

Los Virtual Threads de Java sobresalen en escenarios específicos (bloqueo masivo de I/O) pero no proporcionan beneficios universales de rendimiento.

5. Trade-off Rendimiento vs Productividad

  • JavaScript: Alto rendimiento, requiere manejo cuidadoso de errores
  • Java: Rendimiento moderado, alta productividad del desarrollador
  • La elección depende de las capacidades del equipo y requisitos del proyecto

🔧 Ejecutar los Benchmarks

Prerrequisitos

# macOS
brew install node wrk
curl -fsSL https://bun.sh/install | bash

# Java 21+ requerido para Virtual Threads
java --version

Ejecutar Benchmarks

# Clonar el repositorio
git clone <repository-url>
cd iot-bench

# Benchmarks Spring Boot
./run_benchmark_fixed.sh
./run_spring_ultra_fast.sh

# Benchmarks Node.js
./run_nodejs_benchmark.sh
./run_clustered_benchmark.sh

# Benchmarks Bun
./run_js_benchmark.sh

# Comparaciones de frameworks
./run_framework_pi_benchmark.sh
./run_nestjs_benchmark.sh

# Cargas empresariales
./run_enterprise_benchmark.sh
./run_realistic_benchmark.sh

# Pruebas intensivas en CPU
./run_pi_benchmark.sh
./run_cpu_intensive_benchmark.sh

📁 Estructura del Repositorio

iot-bench/
├── README.md                          # Este resumen integral
├── BENCHMARK_RESULTS.md               # Benchmarks detallados de I/O y CPU
├── PI_BENCHMARK_RESULTS.md            # Rendimiento computacional puro
├── FRAMEWORK_PI_RESULTS.md            # Rendimiento a nivel framework
├── REALISTIC_ENTERPRISE_RESULTS.md    # Resultados de lógica empresarial
├── 
├── src/main/java/                      # Implementaciones Java/Spring Boot
├── *.ts *.js                          # Implementaciones Node.js/Bun
├── run_*.sh                           # Scripts de ejecución de benchmarks
├── *.lua                              # Scripts de benchmark wrk
└── package*.json, pom.xml             # Gestión de dependencias

🤝 Contribuciones

¡Las contribuciones son bienvenidas! Siéntete libre de:

  • Agregar nuevos frameworks o runtimes
  • Mejorar la metodología de benchmarks
  • Optimizar implementaciones existentes
  • Reportar issues o sugerir mejoras

⚠️ Notas Importantes

  1. Los resultados pueden variar basados en hardware, OS y configuración
  2. Los benchmarks reflejan cargas de trabajo específicas - las aplicaciones reales pueden comportarse diferente
  3. Considera el costo total de propiedad incluyendo desarrollo, mantenimiento y costos operacionales
  4. El rendimiento es solo un factor en la selección de tecnología
  5. Siempre benchmarkea tu caso de uso específico antes de tomar decisiones arquitectónicas

🎯 Reflexiones Finales

Esta suite completa de benchmarks revela que nuestras suposiciones industriales sobre rendimiento están desactualizadas. JavaScript ha evolucionado de un simple lenguaje de scripting a un runtime de alto rendimiento capaz de manejar cargas de trabajo empresariales con eficiencia excepcional.

La elección entre Java y JavaScript debería basarse en:

  1. Capacidades y experiencia del equipo
  2. Requisitos de mantenibilidad y escalabilidad
  3. Tolerancia al riesgo y necesidades de cumplimiento
  4. Requisitos de integración con sistemas existentes
  5. Dirección tecnológica estratégica a largo plazo

No solo rendimiento bruto - porque en la mayoría de escenarios, JavaScript gana esa batalla decisivamente.

La pregunta real no es "¿Cuál es más rápido?" sino "¿Cuál ayuda a tu equipo a construir software mantenible, confiable y escalable de manera más efectiva?"

Para muchas empresas, esa respuesta sigue siendo Java - a pesar del trade-off de rendimiento. Pero para proyectos nuevos, startups y aplicaciones críticas en rendimiento, los runtimes modernos de JavaScript merecen consideración seria.


Benchmarks realizados en Apple Silicon con metodología reproducible. Todo el código y scripts están disponibles en este repositorio para verificación y extensión.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published