Cross Runtime Benchmark Library — Node.js Edition¶
Biblioteca de Benchmarking de Alta Precisão para aplicações Node.js
Solução profissional para medição de performance com rigor estatístico, isolamento metodológico e reprodutibilidade científica.
1. Visão Geral¶
A Cross Runtime Benchmark Library é uma solução completa para benchmarking de aplicações Node.js, projetada para produzir resultados estatisticamente confiáveis e reproduzíveis.
Características Principais¶
| Característica | Descrição |
|---|---|
| Warmup Adaptativo | Detecção automática de estabilidade via CV% (Coeficiente de Variação) |
| Isolamento por Processo | Forking via child_process.fork() para eliminação de estado acumulado |
| Timer de Alta Precisão | process.hrtime.bigint() com resolução de nanosegundos |
| Prevenção de DCE | Blackhole pattern para evitar Dead Code Elimination pelo V8 |
| Detecção de Outliers | Métodos IQR, MAD e Z-Score para filtragem estatística |
| Intervalos de Confiança | Cálculo de IC 95% via distribuição t-Student |
| GC Forçado | Integração com --expose-gc para limpeza controlada de heap |
| Saída Padronizada | JSON compatível com Java e C# para análise cross-platform |
Público-Alvo¶
- Equipes de engenharia de performance
- Desenvolvedores de bibliotecas críticas
- Pesquisadores em otimização de software
- Times de QA com foco em regressão de performance
2. Arquitetura¶

Componentes Principais¶
| Componente | Módulo | Responsabilidade |
|---|---|---|
BenchmarkRunner |
core |
Orquestração do pipeline de execução |
ProcessBenchmarkRunner |
core |
Execução com isolamento por processo |
WarmupManager |
warmup |
Gerenciamento de aquecimento adaptativo |
StatisticalAnalysis |
statistics |
Cálculos estatísticos descritivos |
AdvancedStatistics |
statistics |
Testes de significância e comparação |
HardwareCountersCollector |
metrics |
Coleta de contadores (fallback V8) |
JsonReporter |
reporters |
Exportação em formato JSON |
Blackhole |
utils |
Prevenção de Dead Code Elimination |
3. Fluxo de Execução¶

4. Instalação¶
npm¶
yarn¶
Build Local¶
git clone https://github.com/eduardocvalente/lib-cross-runtime-bench-node-ifg.git
cd lib-cross-runtime-bench-node
npm install
5. Exemplos de Uso¶
5.1 Benchmark Simples¶
const { Benchmark } = require('lib-cross-runtime-bench-node');
async function main() {
// Benchmark com configuração padrão
const result = await Benchmark.run('My Function', () => {
let sum = 0;
for (let i = 0; i < 1000; i++) {
sum += i;
}
return sum;
});
console.log(`Mean: ${(result.statistics.mean / 1_000_000).toFixed(3)} ms (CV: ${(result.statistics.coefficientOfVariation * 100).toFixed(2)}%)`);
}
main();
5.2 Benchmark com Configuração Personalizada¶
const { Benchmark, BenchmarkConfig } = require('lib-cross-runtime-bench-node');
async function main() {
// Configuração de alta precisão
const config = BenchmarkConfig.builder()
.withIterations(200)
.withWarmupIterations(50)
.withForceGC(true)
.withAdaptiveWarmup(true)
.withWarmupStabilityThreshold(0.03) // 3% CV
.withMaxWarmupIterations(500)
.withOutlierDetection('MAD')
.withOutlierThreshold(3.5)
.build();
const result = await Benchmark.run('Configured Test', () => {
return performExpensiveOperation();
}, config);
// Exportar para JSON
const { JsonReporter } = require('lib-cross-runtime-bench-node');
await JsonReporter.report(result, 'benchmark_result.json');
}
main();
5.3 Benchmark com Forking (Isolamento por Processo)¶
const { Benchmark, BenchmarkConfig } = require('lib-cross-runtime-bench-node');
async function main() {
const config = BenchmarkConfig.builder()
.withProcessIsolation(true)
.withForksCount(5)
.withIterations(50)
.build();
const result = await Benchmark.run('Isolated Test', () => {
// Cada fork executa em processo Node.js separado
// Estado V8, heap, GC completamente isolados
return myFunction();
}, config);
console.log(`Result from ${result.forks} forks: ${(result.statistics.mean / 1e6).toFixed(3)} ms`);
}
main();
5.4 Comparação de Algoritmos¶
const { Benchmark, ConsoleReporter } = require('lib-cross-runtime-bench-node');
async function main() {
const comparison = await Benchmark.compare([
{ name: 'Algorithm A', fn: () => algorithmA(data) },
{ name: 'Algorithm B', fn: () => algorithmB(data) },
{ name: 'Algorithm C', fn: () => algorithmC(data) },
]);
ConsoleReporter.reportComparison(comparison);
// Output: "Algorithm B is 15.3% faster (p < 0.001, Cohen's d = 1.2 [Large])"
}
main();
5.5 Prevenção de DCE com Blackhole¶
const { Benchmark, Blackhole } = require('lib-cross-runtime-bench-node');
async function main() {
const blackhole = new Blackhole();
await Benchmark.run('Blackhole Test', () => {
// Sem Blackhole: V8 TurboFan pode eliminar código
const result = expensiveComputation();
// Com Blackhole: força execução do código
blackhole.consume(result);
});
}
main();
5.6 Exportação de Múltiplos Resultados¶
const { Benchmark, JsonReporter } = require('lib-cross-runtime-bench-node');
async function main() {
const result1 = await Benchmark.run('Test A', fnA);
const result2 = await Benchmark.run('Test B', fnB);
const result3 = await Benchmark.run('Test C', fnC);
await JsonReporter.reportMultiple([result1, result2, result3], 'output/results.json');
}
main();
6. Configuração¶
6.1 Presets Disponíveis¶
| Preset | Warmup | Medição | Forks | Outliers | Uso |
|---|---|---|---|---|---|
DEFAULT |
20 iter | 100 iter | 1 | IQR | 90% dos casos |
FAST |
5 iter | 20 iter | 1 | None | Dev/debug rápido |
HIGH_PRECISION |
Adaptativo | 500 iter | 3 | MAD | Decisões críticas |
6.2 Parâmetros de Configuração¶
| Parâmetro | Tipo | Default | Descrição |
|---|---|---|---|
iterations |
number | 100 | Iterações de medição |
warmupIterations |
number | 20 | Iterações de warmup fixo |
forceGC |
boolean | true | Forçar GC antes de medir (--expose-gc) |
adaptiveWarmup |
boolean | false | Usar warmup adaptativo baseado em CV% |
warmupStabilityThreshold |
number | 0.05 | CV% alvo para estabilização (5%) |
maxWarmupIterations |
number | 100 | Máximo de iterações de warmup |
outlierDetection |
string | 'IQR' |
Método: IQR, MAD, ZScore, Grubbs, None |
outlierThreshold |
number | 1.5 | Threshold para detecção de outliers |
processIsolation |
boolean | false | Executar em processos separados |
forksCount |
number | 1 | Número de forks |
7. Técnicas de Isolamento¶
7.1 Warmup Adaptativo¶
Algoritmo:
1. Executar função
2. A cada 5 iterações: calcular CV% das últimas N medições
3. Se CV% < target por 3 verificações consecutivas → parar
4. Senão: continuar até maxWarmupIterations
Por que é importante: - V8 TurboFan compilation ocorre nas primeiras execuções (10-100x mais lento) - Caches de CPU (L1/L2/L3) precisam ser aquecidos - Inline caches (ICs) do V8 precisam de histórico de tipos
7.2 Forking por Processo¶
Ver Fase 1 em
imagens/pipeline.pngpara o diagrama de isolamento por processo.
Benefícios: - Heap V8 limpo (sem fragmentação acumulada) - JIT TurboFan fresco (sem perfis de tipos enviesados) - GC state resetado - Variação reduzida em 30-50%
7.3 GC Forçado¶
// Requer execução com: node --expose-gc script.js
if (typeof global.gc === 'function') {
global.gc();
}
Benefícios: - Elimina objetos órfãos do warmup - Heap em estado conhecido antes de medir - Reduz interferência de GC durante medição
7.4 Prevenção de DCE (Blackhole)¶
// Problema: V8 TurboFan pode eliminar código "morto"
const result = compute(); // Pode ser eliminado!
// Solução: Blackhole
blackhole.consume(result); // Força execução via globalThis sink
8. Métricas Coletadas¶
8.1 Timing¶
| Métrica | Unidade | Descrição |
|---|---|---|
mean |
nanosegundos | Média aritmética |
median |
nanosegundos | Valor central (resistente a outliers) |
stdDev |
nanosegundos | Desvio padrão |
min |
nanosegundos | Valor mínimo |
max |
nanosegundos | Valor máximo |
8.2 Memória (V8)¶
| Métrica | Unidade | Descrição |
|---|---|---|
heapUsed |
bytes | Heap ocupado (process.memoryUsage().heapUsed) |
heapTotal |
bytes | Heap total alocado |
rss |
bytes | Resident Set Size total do processo |
external |
bytes | Memória de objetos nativos referenciados pelo V8 |
8.3 CPU¶
| Métrica | Unidade | Descrição |
|---|---|---|
userMs |
milissegundos | Tempo em user mode (process.cpuUsage().user) |
systemMs |
milissegundos | Tempo em kernel mode (process.cpuUsage().system) |
totalMs |
milissegundos | Tempo total de CPU |
8.4 Sistema¶
| Métrica | Descrição |
|---|---|
nodeVersion |
Versão do Node.js (process.version) |
platform |
Sistema operacional (os.platform()) |
cpuCount |
Número de CPUs lógicas (os.cpus().length) |
totalMemory |
Memória total do sistema (os.totalmem()) |
loadAvg |
Carga média do sistema (os.loadavg()) |
9. Análise Estatística¶
9.1 Estatísticas Descritivas¶
| Estatística | Fórmula | Interpretação |
|---|---|---|
| Mean (μ) | Σx / n | Centro da distribuição |
| Median | valor central | Resistente a outliers |
| StdDev (σ) | √(Σ(x-μ)²/(n-1)) | Dispersão |
| CV% | (σ/μ) × 100 | Confiabilidade relativa |
| IQR | Q3 - Q1 | Dispersão robusta |
9.2 Intervalo de Confiança 95%¶
IC = μ ± (t × SEM)
onde:
SEM = σ / √n (Erro Padrão da Média)
t = valor t-Student (depende de n-1 graus de liberdade)
9.3 Detecção de Outliers¶
| Método | Fórmula | Uso |
|---|---|---|
| IQR | Outlier se x < Q1-1.5×IQR ou x > Q3+1.5×IQR | Padrão, robusto |
| MAD | Outlier se |x - median| > 3 × MAD | Distribuições enviesadas |
| Z-Score | Outlier se |ModZ| > 3.5 | Distribuições normais |
| Grubbs | Teste estatístico formal | Detecção rigorosa |
9.4 Teste de Significância (Welch t-test)¶
const { AdvancedStatistics } = require('lib-cross-runtime-bench-node');
const comparison = AdvancedStatistics.compareBenchmarks(
resultA.measurements, resultB.measurements,
'Algorithm A', 'Algorithm B'
);
// Interpretação:
// p < 0.05: Diferença significativa (95% confiança)
// p < 0.01: Diferença muito significativa (99% confiança)
// Cohen's d: Tamanho do efeito (0.2=small, 0.5=medium, 0.8=large)
console.log(comparison.summary);
10. Formato de Saída¶
10.1 JSON Schema¶
{
"export_date": "2026-02-17T12:34:56Z",
"benchmark_name": "sort_algorithm_benchmark",
"metrics": {
"timing": {
"mean_ns": 12345678.9,
"median_ns": 12200000,
"stddev_ns": 500000,
"min_ns": 11500000,
"max_ns": 13500000,
"sample_count": 100,
"cv_percent": 4.05
},
"throughput": {
"ops_per_second": 81.0
},
"memory": {
"heap_bytes": 33554432,
"total_bytes": 301989888
},
"cpu": {
"user_time_ms": 120.5,
"system_time_ms": 5.2,
"cpu_usage_percent": 12.34
},
"hardware_counters": {
"cycles": 0,
"instructions": 0,
"instructions_per_cycle": 0,
"is_available": false
}
},
"environment": {
"os": "Windows 11",
"runtime": "Node.js v20.11.0",
"cpu_model": "Intel Core i7-9700K",
"processor_count": 8
}
}
10.2 Compatibilidade Cross-Platform¶
O schema JSON é 100% compatível com as implementações Java e C#, permitindo: - Comparação de resultados entre runtimes - Análise unificada em ferramentas de BI - Integração com pipelines CI/CD multi-linguagem
11. Integração CI/CD¶
11.1 GitHub Actions¶
name: Performance Regression
on: [push, pull_request]
jobs:
benchmark:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm install
- name: Run Benchmarks
run: node --expose-gc examples/SimpleExample.js
- name: Check Regression
run: |
# Comparar com baseline
python scripts/check_regression.py \
--baseline baseline.json \
--current result.json \
--threshold 5
11.2 Armazenamento de Baselines¶
const { Benchmark, JsonReporter, AdvancedStatistics } = require('lib-cross-runtime-bench-node');
const fs = require('fs');
// Salvar baseline
const result = await Benchmark.run('My Benchmark', myFn);
await JsonReporter.report(result, 'baselines/v2.0.0_baseline.json');
// Comparar com baseline
const baseline = JSON.parse(fs.readFileSync('baselines/v2.0.0_baseline.json'));
const comparison = AdvancedStatistics.compareBenchmarks(
baseline.measurements, result.measurements
);
if (comparison.statisticalTest.isSignificant && comparison.percentChange > 5.0) {
throw new Error(`Regression detected: ${comparison.summary}`);
}
11.3 Execução Recomendada¶
# Habilitar GC manual para métricas precisas
node --expose-gc examples/SimpleExample.js
# Exemplos disponíveis
node --expose-gc examples/SimpleExample.js # Uso básico
node --expose-gc examples/ConfiguredExample.js # Configuração avançada
node --expose-gc examples/IsolatedExample.js # Isolamento de processo
node --expose-gc examples/CompareExample.js # Comparação de algoritmos
node --expose-gc examples/SortingBenchmark.js # Benchmark de ordenação
12. Referências¶
Literatura Acadêmica¶
- Georges, A., Buytaert, D., & Eeckhout, L. (2007). Statistically Rigorous Java Performance Evaluation. OOPSLA.
- Mytkowicz, T., et al. (2009). Producing Wrong Data Without Doing Anything Obviously Wrong!. ASPLOS.
- Kalibera, T., & Jones, R. (2013). Rigorous Benchmarking in Reasonable Time. ISMM.
Bibliotecas de Referência¶
- Benchmark.js — JavaScript benchmarking
- JMH — Java Microbenchmark Harness
- BenchmarkDotNet — .NET benchmarking
Recursos Adicionais¶
- imagens/architecture.png — Arquitetura em camadas
- imagens/pipeline.png — Pipeline de execução
- BENCHMARK_NOTES.md — Notas de implementação
- examples/ — Exemplos de uso
Estrutura do Projeto¶
src/
├── Benchmark.js # API pública principal
├── index.js # Exportações do módulo
├── config/
│ └── BenchmarkConfig.js # Configuração com builder pattern
├── core/
│ ├── BenchmarkRunner.js # Engine principal de execução
│ └── ProcessBenchmarkRunner.js # Execução com child_process.fork()
├── warmup/
│ └── WarmupManager.js # Warmup adaptativo (CV%)
├── statistics/
│ ├── StatisticalAnalysis.js # Estatísticas descritivas + outliers
│ └── AdvancedStatistics.js # Welch t-test, Cohen's d
├── metrics/
│ ├── CpuMetricsCollector.js # process.cpuUsage()
│ ├── MemoryMetricsCollector.js # process.memoryUsage() + V8
│ ├── SystemMetricsCollector.js # os.cpus(), os.totalmem()
│ └── HardwareCountersCollector.js # Fallback gracioso
├── utils/
│ ├── HighPrecisionTimer.js # process.hrtime.bigint()
│ └── Blackhole.js # Prevenção de DCE
├── reporters/
│ ├── JsonReporter.js # Exportação JSON compatível
│ └── ConsoleReporter.js # Saída formatada no terminal
└── Models/
└── BenchmarkResult.js # Modelo de resultado
Compatibilidade¶
- Node.js: >= 22.0.0
- Flags recomendadas:
--expose-gcpara GC forçado - Formato: JSON schema compatível com Java e C#
Licença¶
MIT License — Copyright (c) 2026 Eduardo Costa Valente
Cross Runtime Benchmark Library — Medição de performance com rigor científico.