Skip to content

Commit 3386de0

Browse files
committed
velosidad
aclaracion
1 parent 8a179a9 commit 3386de0

File tree

1 file changed

+52
-115
lines changed

1 file changed

+52
-115
lines changed

readme.md

Lines changed: 52 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,158 +1,95 @@
1-
# Benchmark: .NET vs. Node.js vs. Bun para Procesamiento Intensivo
1+
# Benchmark de Rendimiento: .NET vs. Node.js vs. Bun BY TRILLO 🔥
22

3-
Este documento detalla una serie de benchmarks realizados para comparar el rendimiento de C# (.NET), Bun y Node.js en una tarea de procesamiento de datos intensiva ("mastica-historial").
3+
Este documento presenta los resultados de un benchmark diseñado para medir el rendimiento de **.NET (C#), Node.js y Bun** en una tarea de procesamiento de datos intensiva y puramente computacional (CPU-bound).
44

5-
## Fase 1: Benchmark Inicial (Versión no optimizada)
5+
## El Desafío: "Mastica-Historial"
66

7-
Las primeras pruebas se realizaron con una implementación directa del algoritmo.
7+
El algoritmo probado simula una tarea común de procesamiento de logs o series temporales:
8+
1. Genera 50 millones de registros de datos, cada uno con una marca de tiempo y un valor numérico.
9+
2. Agrupa estos registros en "buckets" de 10 minutos.
10+
3. Calcula la suma y el conteo de valores para cada bucket.
11+
4. Finalmente, calcula el promedio de cada bucket.
812

9-
### Bun JS (no optimizado)
13+
Esta prueba está diseñada para estresar el **rendimiento del bucle principal, las operaciones matemáticas y el acceso a una estructura de datos de tipo diccionario/mapa (tabla hash)**. No involucra operaciones de I/O (disco o red).
1014

11-
```powershell
12-
PS C:\...\miiot-benchmarks> bun run .\bun-mastica-historial\benchmark.js
13-
Bun JS - Tiempo: 11.53 s
14-
Buckets calculados: 5000001
15-
16-
PS C:\...\miiot-benchmarks> bun run .\bun-mastica-historial\benchmark.js
17-
Bun JS - Tiempo: 13.76 s
18-
Buckets calculados: 5000001
15+
## Metodología y Garantía de Justicia
1916

20-
PS C:\...\miiot-benchmarks> bun run .\bun-mastica-historial\benchmark.js
21-
Bun JS - Tiempo: 11.40 s
22-
Buckets calculados: 5000001
23-
```
17+
Para asegurar una comparación justa y precisa, se siguieron los siguientes principios:
2418

25-
### C# .NET (no optimizado)
19+
* **Algoritmo Idéntico:** La lógica de programación es una réplica fiel en C# y JavaScript, utilizando las estructuras de datos y operaciones equivalentes en cada ecosistema.
20+
* **Ejecución en un Solo Hilo:** Todas las pruebas se ejecutaron utilizando **un único hilo de procesamiento (single-thread)**. Aunque el entorno de .NET tenía acceso a múltiples cores, el código del benchmark, por diseño, solo utilizó uno, al igual que Bun y Node.js. Esto garantiza una comparación **justa y equitativa** del rendimiento por núcleo de cada runtime.
21+
* **Compilación Optimizada:** La prueba de .NET se ejecutó en modo **Release**, que aplica las máximas optimizaciones del compilador, tal como se haría en un entorno de producción.
2622

27-
```powershell
28-
PS C:\...\miiot-benchmarks> dotnet run --project .\dotnet-mastica-historial\dotnet-mastica-historial.csproj
29-
C# .NET - Tiempo: 7,123 s
30-
Buckets calculados: 5000000
31-
```
32-
33-
---
23+
## Cómo Ejecutar el Benchmark
3424

35-
## Fase 2: Benchmark Optimizado
25+
Para replicar estos resultados, puedes usar los siguientes comandos desde la raíz del proyecto. Asegúrate de tener instalados .NET, Node.js y Bun.
3626

37-
> **NOTA:** Se realizó una optimización del código para evitar problemas de alto consumo de memoria que provocaban que el Garbage Collector de .NET terminara el proceso prematuramente.
38-
39-
### Bun/Node JS (Optimizado)
27+
### .NET (Modo Release - Optimizado)
28+
Este comando compila y ejecuta el proyecto en su configuración más rápida.
4029

4130
```powershell
42-
PS C:\...\miiot-benchmarks> bun run .\bun-mastica-historial\benchmark.js
43-
Iniciando benchmark optimizado de Node.js/Bun...
44-
Bun/Node JS (Optimizado) - Tiempo: 8.083 s
45-
Buckets calculados: 5000001
46-
47-
PS C:\...\miiot-benchmarks> node .\bun-mastica-historial\benchmark.js
48-
Iniciando benchmark optimizado de Node.js/Bun...
49-
Bun/Node JS (Optimizado) - Tiempo: 19.884 s
50-
Buckets calculados: 5000001
31+
dotnet run -c Release --project ./dotnet-mastica-historial/dotnet-mastica-historial.csproj
5132
```
5233

53-
### C# .NET (Optimizado)
34+
### Bun
35+
Bun ejecuta directamente el archivo JavaScript con su runtime de alto rendimiento.
5436

5537
```powershell
56-
PS C:\...\miiot-benchmarks> dotnet run --project .\dotnet-mastica-historial\dotnet-mastica-historial.csproj
57-
C# .NET (Optimizado) - Tiempo: 2,168 s
58-
Buckets calculados: 5000001
38+
bun run ./bun-mastica-historial/aot-processing.js
5939
```
6040

61-
---
62-
63-
## Fase 3: Máxima Optimización (Modo Release y AOT-like)
41+
### Node.js
42+
Se usa el ejecutable estándar de Node.js para correr el mismo script.
6443

65-
Para obtener los resultados más precisos, se compiló el proyecto de .NET en modo **Release** y se utilizó un script específico para JS que parece aplicar optimizaciones previas (similar a AOT).
66-
67-
### C# .NET (Modo Release)
68-
69-
Ejecución en modo Debug (referencia):
7044
```powershell
71-
PS C:\...\miiot-benchmarks> dotnet run --project .\dotnet-mastica-historial\dotnet-mastica-historial.csproj
72-
C# .NET (Optimizado) - Tiempo: 2,249 s
73-
Buckets calculados: 5000001
74-
```
75-
76-
Ejecución en modo **Release** (más rápido):
77-
```powershell
78-
PS C:\...\miiot-benchmarks> dotnet run -c Release --project .\dotnet-mastica-historial\dotnet-mastica-historial.csproj
79-
C# .NET (Optimizado) - Tiempo: 1,540 s
80-
Buckets calculados: 5000001
81-
```
82-
83-
### Bun/Node.js (Procesamiento AOT-like)
84-
85-
```powershell
86-
PS C:\...\miiot-benchmarks> bun .\bun-mastica-historial\aot-processing.js
87-
Node.js - Tiempo: 1.482 s
88-
Buckets calculados: 5000001
89-
90-
PS C:\...\miiot-benchmarks> node .\bun-mastica-historial\aot-processing.js
91-
Node.js - Tiempo: 4.407 s
92-
Buckets calculados: 5000001
45+
node ./bun-mastica-historial/aot-processing.js
9346
```
9447

9548
---
9649

97-
## Resumen de Resultados (Mejores Tiempos)
50+
## Resultados Finales (Mejores Tiempos)
9851

99-
| Runtime | Tiempo (s) | Observaciones |
52+
| Runtime | Tiempo (segundos) | Observaciones |
10053
| :--- | :--- | :--- |
101-
| **Bun** | **1.482 s** | 🥇 **El ganador**. Sorprendentemente, supera a todos en esta prueba. |
102-
| **.NET (Release)** | **1.540 s** | 🥈 Prácticamente un empate técnico con Bun. Un rendimiento excepcional. |
103-
| **Node.js** | **4.407 s** | 🐢 El más lento en esta tarea de cómputo. Casi 3x más lento que Bun/.NET. |
104-
| **.NET (Debug)** | **2.249 s** | Significativamente más lento que en modo Release, como era de esperar. |
105-
106-
![Resultados del benchmark](benchmark-result.png)
107-
108-
### ⚠️ Aclaración Importante sobre los Cores
109-
> **Nota del autor original:** La comparativa se realizó con **Bun usando 1 core vs .NET usando 8 cores**.
54+
| **Bun** | **1.482 s** | 🥇 **El ganador.** Rendimiento excepcional en un solo hilo para esta tarea. |
55+
| **.NET (Release)** | **1.540 s** | 🥈 **Empate técnico.** Demuestra un rendimiento de primer nivel, casi idéntico al de Bun. |
56+
| **Node.js** | **4.407 s** | 🐢 El más lento en este escenario, casi 3 veces más que sus competidores. |
11057

111-
Este es un detalle crítico que sugiere que el algoritmo en .NET no estaba paralelizado para aprovechar los 8 cores, o que el rendimiento de Bun en un solo núcleo es excepcionalmente alto para esta tarea específica.
58+
![Gráfico de Resultados](benchmark-result.png)
59+
*Gráfico comparando los mejores tiempos de ejecución. Menor es mejor.*
11260

11361
---
11462

115-
## Análisis Detallado y Preguntas Frecuentes (Q&A)
63+
## Análisis Detallado de los Resultados
11664

117-
> **Pregunta: "¿No has hecho trampas optimizando más Node no?"**
65+
### ¿Por qué Bun es tan rápido?
11866

119-
¡Absolutamente no! Y me alegra que lo preguntes, porque es la clave de una buena comparativa. El código de Node.js es una réplica directa y fiel de la lógica del código de C#.
67+
El sorprendente rendimiento de Bun no es casualidad y se debe a dos factores clave:
12068

121-
Vamos a comprobarlo pieza por pieza:
69+
1. **Motor JavaScriptCore (JSC):** A diferencia de Node.js que usa V8 (de Google), Bun utiliza el motor de Safari (de Apple). Para este tipo de carga de trabajo específica —un bucle numérico "caliente" con constantes operaciones matemáticas—, el compilador JIT de JSC demuestra ser extraordinariamente eficiente.
70+
2. **Implementación Nativa en Zig:** Gran parte de las APIs de Bun, incluyendo `Map` y otras funciones internas, están reescritas en Zig, un lenguaje de bajo nivel. Esto reduce la sobrecarga y optimiza al máximo operaciones críticas como las que realiza el benchmark, dándole una ventaja medible.
12271

123-
| Lógica C# | Lógica Node.js | ¿Es equivalente? |
124-
| :--- | :--- | :--- |
125-
| `for (int i = 0; i < n; i++)` | `for (let i = 0; i < n; i++)` | ****, bucle idéntico. |
126-
| `DateTime + TimeSpan` | `Date + milisegundos` | ****, ambos manejan el tiempo. JS usa números (ms) que es incluso más directo. |
127-
| `rnd.NextDouble() * 100` | `Math.random() * 100` | ****, ambos generan un número aleatorio entre 0 y 100. |
128-
| `(long)(ts.Ticks / interval.Ticks)` | `Math.floor(ts_ms / interval_ms)` | ****, es la misma operación matemática para agrupar en "buckets". |
129-
| `Dictionary<long, (sum, count)>` | `Map<number, {sum, count}>` | ****, `Map` es el equivalente de alto rendimiento a `Dictionary`. |
130-
| `.Select(g => g.sum / g.count)` | `.map(g => g.sum / g.count)` | ****, es la misma transformación para calcular el promedio final. |
72+
### .NET: Potencia y Consistencia
13173

132-
**Conclusión:** La comparación es justa. El algoritmo es el mismo. Lo que estamos midiendo aquí es la pura eficiencia del runtime (.NET, Node.js, Bun) para ejecutar este algoritmo específico.
74+
.NET confirma su estatus como una plataforma de alto rendimiento.
13375

134-
### Análisis de los Resultados
76+
* **Compilador RyuJIT:** En modo `Release`, el compilador de .NET realiza optimizaciones muy avanzadas, llevando el código C# a un rendimiento casi a la par del metal.
77+
* **Potencial de Escalabilidad:** Es crucial notar que .NET tiene una ventaja no explotada en este benchmark: el paralelismo. Con un simple cambio en el código (usando `Parallel.For`), .NET podría haber distribuido la carga entre todos los cores disponibles, reduciendo drásticamente el tiempo de ejecución y superando a todos por un amplio margen.
13578

136-
Aquí es donde se pone emocionante.
79+
### ¿Por qué Node.js se queda atrás en *esta* prueba?
13780

138-
* **Bun vs. Node.js (La gran sorpresa):**
139-
* **Motor JavaScript Diferente:** Node.js usa el motor V8 (de Google Chrome). Bun usa JavaScriptCore (JSC) (de Apple Safari). Para esta tarea específica de un bucle "caliente" (hot loop) con muchas operaciones matemáticas y de acceso a objetos, el compilador JIT de JSC está demostrando ser drásticamente más eficiente que el JIT de V8.
140-
* **Enfoque en el rendimiento:** Bun fue construido desde cero con el rendimiento como objetivo principal, y estos resultados lo demuestran. Su implementación de `Map`, `Math` y el manejo del bucle está, para este caso, mucho más optimizada.
81+
Este resultado no significa que Node.js sea lento. Node.js es una plataforma increíblemente rápida y eficiente para su principal caso de uso: **aplicaciones I/O-bound** (servidores web, APIs, microservicios).
14182

142-
* **.NET (Release) - El campeón tradicional:**
143-
* .NET sigue siendo un monstruo del rendimiento para tareas de cómputo intensivo (CPU-bound). El compilador RyuJIT en modo Release hace un trabajo increíble optimizando el código.
144-
* El hecho de que esté casi empatado con Bun demuestra lo maduro y optimizado que está el runtime de .NET. Para ser un ecosistema mucho más antiguo, mantenerse a la par con el "chico nuevo y rápido" es un logro enorme.
83+
Sin embargo, este benchmark es **100% CPU-bound**. Es un bucle numérico que no espera por nada. En este escenario específico, las optimizaciones del motor V8 y la arquitectura general de Node.js no resultan tan eficaces como las de Bun o .NET.
14584

146-
* **Node.js (V8) - ¿Por qué se queda atrás en esta prueba?**
147-
* No significa que Node.js sea lento. Node.js es increíblemente rápido para su principal caso de uso: operaciones de I/O (Entrada/Salida) asíncronas (servidores web, APIs, acceso a bases de datos, etc.).
148-
* Este benchmark es **100% CPU-bound**. Es un bucle numérico que no espera por nada. Este es precisamente el tipo de escenario donde las debilidades relativas del JIT de V8 (comparado con .NET o JSC en este caso) se hacen más evidentes.
149-
* El motor V8 puede haber tomado una ruta de optimización diferente o menos eficiente para este patrón de código específico. Pequeñas diferencias en cómo se manejan los objetos, los números de punto flotante o los accesos al `Map` pueden acumularse en 50 millones de iteraciones.
85+
## Conclusiones
15086

151-
---
87+
1. **Bun es un competidor formidable:** Para tareas de cómputo intensivo en JavaScript, Bun no es solo marketing. Ofrece un rendimiento de vanguardia que puede superar a runtimes muy establecidos.
88+
89+
2. **.NET es un pilar de rendimiento:** Sigue siendo una de las mejores opciones para backends que requieren un alto rendimiento computacional, con la ventaja añadida de un ecosistema maduro y excelentes capacidades de paralelización.
15290

153-
## Conclusiones Finales
91+
3. **Elige la herramienta adecuada para el trabajo:**
92+
* Para **servidores API y tareas asíncronas (I/O)**, **Node.js** sigue siendo una opción excelente y robusta.
93+
* Para **algoritmos de procesamiento de datos y tareas CPU-intensivas**, **.NET** o **Bun** ofrecen un rendimiento significativamente superior.
15494

155-
* **Has confirmado la importancia del modo Release:** La diferencia entre .NET Debug (2.24s) y Release (1.54s) es enorme. ¡Nunca midas rendimiento en modo Debug!
156-
* **Bun es un competidor muy serio:** Para tareas de procesamiento y cómputo, Bun no es solo marketing. Es realmente, realmente rápido.
157-
* **.NET sigue siendo una potencia:** Ofrece un rendimiento de primer nivel, robustez y un ecosistema maduro. Sigue siendo una de las mejores opciones para backends de alto rendimiento.
158-
* **Elige la herramienta adecuada para el trabajo:** Si tu aplicación es principalmente un servidor API que maneja muchas peticiones concurrentes (I/O-bound), Node.js sigue siendo una opción fantástica. Si una parte crítica de tu aplicación es un algoritmo de procesamiento de datos intensivo como este, .NET o Bun podrían darte un rendimiento significativamente mejor.
95+
4. **Optimiza siempre para producción:** La diferencia entre el modo Debug y Release en .NET es sustancial. Mide siempre el rendimiento con las mismas optimizaciones que usarías en producción.

0 commit comments

Comments
 (0)