Inspection e Autocannon | CPUProfile | Performance | Node.js
- Inspection e Autocannon | CPUProfile | Performance | Node.js
Erick Wendel - Vídeo: 🔗 Clique aqui
Neste artigo, vamos aprender como:
- Instrumentar o Node.js Inspector diretamente no código
- Gerar um arquivo
.cpuprofile - Simular carga com Autocannon
- Analisar o resultado no Discovery.js CPU Profile Viewer
Essa abordagem é ideal para:
- Profiling automatizado
- Execução em CI
- Ambientes onde o Chrome DevTools não é viável
- Reprodutibilidade de resultados
1. Visão geral da estratégia
O fluxo será:
Aplicação Node.js
├─ Inicia Inspector Session
├─ Ativa CPU Profiler
├─ Executa aplicação sob carga (Autocannon)
├─ Para o Profiler
├─ Salva arquivo .cpuprofile
└─ Analisa no Discovery.js
2. Exemplo de aplicação Node.js
2.1 Estrutura do projeto
project/
├─ index.js
└─ package.json
3. Código com inspector.Session (index.js)
Este exemplo:
- Cria um servidor HTTP
- Inicia automaticamente o CPU Profiler
- Para o profiler após um tempo
- Salva o arquivo
.cpuprofile
import http from 'node:http'
import inspector from 'node:inspector'
import fs from 'node:fs'
// -----------------------------
// CPU PROFILER SETUP
// -----------------------------
const session = new inspector.Session()
session.connect()
function post(method, params = {}) {
return new Promise((resolve, reject) => {
session.post(method, params, (err, result) => {
if (err) reject(err)
else resolve(result)
})
})
}
async function startProfiling() {
await post('Profiler.enable')
await post('Profiler.start')
console.log('CPU profiling started')
}
async function stopProfiling() {
const { profile } = await post('Profiler.stop')
fs.writeFileSync(
'cpu-profile.cpuprofile',
JSON.stringify(profile)
)
console.log('CPU profiling finished → cpu-profile.cpuprofile')
session.disconnect()
}
// -----------------------------
// APPLICATION CODE
// -----------------------------
function heavyComputation(iterations) {
let total = 0
for (let i = 0; i < iterations; i++) {
total += Math.sqrt(i * Math.random())
}
return total
}
const server = http.createServer((req, res) => {
if (req.url === '/compute') {
const result = heavyComputation(5_000_000)
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ result }))
return
}
res.writeHead(404)
res.end()
})
server.listen(3000, async () => {
console.log('Server running on http://localhost:3000')
// inicia profiling automaticamente ao subir o servidor
await startProfiling()
// para o profiling após 30 segundos
setTimeout(async () => {
await stopProfiling()
server.close()
}, 30_000)
})
4. Gerando carga com Autocannon
Em outro terminal, execute:
npx autocannon -c 50 -d 25 http://localhost:3000/compute
Recomendações:
- O tempo do Autocannon deve estar contido dentro do tempo do profiling
- Evite iniciar Autocannon antes do
Profiler.start
5. Arquivo gerado
Após a execução, você verá:
cpu-profile.cpuprofile
Esse arquivo é compatível com:
- Chrome DevTools
- VS Code
- Discovery.js CPU Profiler
6. Analisando no Discovery.js
-
Arraste o arquivo:
cpu-profile.cpuprofile -
Explore:
- Flame graph interativo
- Self time vs Total time
- Call tree
- Hot paths
7. O que analisar no Discovery.js
Pontos importantes:
- Funções com maior self time
- Call stacks profundas
- Funções chamadas excessivamente
- Código síncrono bloqueando o event loop
No exemplo, você verá algo como:
heavyComputation
└─ Math.sqrt
Confirmando o gargalo de CPU.
8. Boas práticas com inspector.Session
Controle explícito
- Inicie e pare o profiler em momentos bem definidos
- Evite perfis muito longos (10–60s é ideal)
Produção
- Nunca deixe profiling ativo permanentemente
- Use flags de ambiente:
if (process.env.ENABLE_PROFILING === 'true') {
await startProfiling()
}