Fiz alguns testes também sem bibliotecas em uma máquina linux com fedora 38 (dell Intel® Core™ i5-8350U × 8)
1. Teste de Operações com BigInt (Números de Fibonacci):
console.time("Execution Time");
const n = 1000000;
let a = BigInt(0), b = BigInt(1);
for (let i = BigInt(0); i < n; i++) {
[a, b] = [b, a + b];
}
console.timeEnd("Execution Time");
Resultados: Node.js: 13.770s Bun: 32.01s
2. Teste de Operações de I/O:
console.time("Execution Time");
const n = 1000000;
for (let i = BigInt(0); i < n; i++) {
console.log("Item: " + i);
}
console.timeEnd("Execution Time");
Resultados:
Node.js: 17.787s Bun: 5.27s
3. Teste de Alocação de Memória:
console.time("Memory Allocation Execution Time");
const n = 1000;
for (let i = 0; i < n; i++) {
let arr = new Array(100000).fill(0);
}
console.timeEnd("Memory Allocation Execution Time");
Resultados:
Node.js: 2.162s Bun: 1.78s
4. Teste de Manipulação de Strings:
console.time("String Manipulation Execution Time");
let result = "";
const baseString = "abcdefghijklmnopqrstuvwxyz";
const n = 100000;
for (let i = 0; i < n; i++) {
result += baseString;
}
console.timeEnd("String Manipulation Execution Time");
Resultados:
Node.js: 9.487ms Bun: 4.12ms
5. Teste de Manipulação de Arrays:
console.time("Array Operations Execution Time");
const n = 100000;
let arr = [];
for (let i = 0; i < n; i++) {
arr.push(i);
}
for (let i = 0; i < n; i++) {
let item = arr[i];
}
for (let i = 0; i < n; i++) {
arr.pop();
}
console.timeEnd("Array Operations Execution Time");
Resultados:
Node.js: Média de 8.347ms Bun: Média de 7.91ms
6. Teste de Operações Matemáticas Básicas:
console.time("Basic Math Operations Execution Time");
let result = 0;
const n = 1000000;
for (let i = 1; i <= n; i++) {
result += i;
result -= i;
result *= i;
result /= i;
}
console.timeEnd("Basic Math Operations Execution Time");
Resultados:
Node.js: Média de 11.115ms Bun: Média de 15.423ms
Parece que o bun se destaca em operações de I/O, agora o Node.js tem uma vantagem em operações aritméticas, especialmente com BigInt
Só de curiosidade, refiz esses testes usando o Benchmark.js. Só adicionei mais um caso, de Fibonacci sem BigInt
, pois vi que deu diferença. Segue o código:
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
suite
.add('Fibonacci BigInt', function () {
const n = 1000000n;
let a = BigInt(0), b = BigInt(1);
for (let i = BigInt(0); i < n; i++) {
[a, b] = [b, a + b];
}
})
.add('Fibonacci sem BigInt', function () {
// tive que diminuir n para não estourar o valor máximo de Number
const n = 1000;
let a = 0, b = 1;
for (let i = 0; i < n; i++) {
[a, b] = [b, a + b];
}
})
.add('console.log no loop', function () {
const n = 1000000;
for (let i = BigInt(0); i < n; i++) {
console.log("Item: " + i);
}
})
.add('Alocação de memória', function () {
const n = 1000;
for (let i = 0; i < n; i++) {
let arr = new Array(100000).fill(0);
}
})
.add('Manipulação de strings', function () {
let result = "";
const baseString = "abcdefghijklmnopqrstuvwxyz";
const n = 100000;
for (let i = 0; i < n; i++) {
result += baseString;
}
})
.add('Manipulação de arrays', function () {
const n = 100000;
let arr = [];
for (let i = 0; i < n; i++) {
arr.push(i);
}
for (let i = 0; i < n; i++) {
let item = arr[i];
}
for (let i = 0; i < n; i++) {
arr.pop();
}
})
.add('Operações matemáticas', function () {
let result = 0;
const n = 1000000;
for (let i = 1; i <= n; i++) {
result += i;
result -= i;
result *= i;
result /= i;
}
})
.on('cycle', function (event) {
console.log(String(event.target));
})
.run({
'async': true
});
Os resultados estão abaixo (os valores são de operações por segundo, ou seja, quanto mais, melhor).
Linux (Ubuntu 22.04.3, processador 11th Gen Intel® Core™ i5-1145G7 2.60GHz, 8 núcleos):
Teste | Node | Bun |
---|---|---|
Fibonacci BigInt | 0,07 | 0,07 |
Fibonacci sem BigInt | 224154 | 3507428 (sim, mais de 3 milhões) |
console.log no loop | 0,14 | 0,31 |
Alocação de memória | 2,51 | 2,54 |
Manipulação de strings | 2260 | 1024 |
Manipulação de arrays | 649 | 1882 |
Operações matemáticas | 198 | 222 |
Mac (2012, processador 2.6 GHz Quad-Core Intel Core i7):
Teste | Node | Bun |
---|---|---|
Fibonacci BigInt | 0,12 | 0,03 |
Fibonacci sem BigInt | 136482 | 1547414 |
console.log no loop | 0,08 | 0,18 |
Alocação de memória | 1,49 | 2,7 |
Manipulação de strings | 1483 | 1033 |
Manipulação de arrays | 453 | 1374 |
Operações matemáticas | 122 | 118 |
Ou seja, o Node em geral se sai pior no console.log
dentro de um loop (pelos motivos já citados em vários comentários). O cálculo com BigInt
faz muita diferença no Mac (o Bun se sai pior), mas no Linux dá empate técnico. Em compensação, sem BigInt
o Bun ganha por uma diferença enorme. E nas outras operações ora um, ora outro se sai melhor, com variados graus de vantagem.
wow! muito massa quebrar em 6 tipos de op. ficou muito bom ver a diferença!
IMPORTANTE: console.log
nem sempre vai ser I/O, no NodeJS de fato ele vai virar um process.stdout.write()
e olhando pro codigo fonte do bun:
but it's important that console.log() is fast.
No bun o console.log
vai virar um synchronous printf vs. no NodeJS que se vai ser um asynchronous com stdout