Performance | Node.js
- Performance | Node.js
Melhorar a performance no Node.js utilizando a API de Performance
O primeiro passo para melhorar a performance de uma aplicação é entender onde estão os gargalos. A API de Performance do Node.js, através do módulo perf_hooks, permite medir o tempo de execução com alta precisão, algo que não pode ser feito com precisão usando a classe Date.
Exemplo básico de medição de tempo com perf_hooks:
const {performance} = require('node:perf_hooks');
let start = performance.now();
for (let i = 0; i < 10000; i++) {}
let end = performance.now();
console.log(end - start); // Medição mais precisa em milissegundos
A API permite marcar eventos com precisão e medir o tempo entre eles:
Marcar eventos com performance.mark:
performance.mark("loop_start");
for (let i = 0; i < 10000; i++) {}
performance.mark("loop_end");
console.log(performance.measure("loop_time", "loop_start", "loop_end"));
O uso dessas marcações pode ser útil para monitorar operações como consultas a banco de dados ou ordenações:
Exemplo de medição de operações de consulta e ordenação:
async function main(){
const querySize = 10;
performance.mark("db_query_start");
const data = fetchData(querySize);
performance.mark("db_query_end");
performance.mark("sort_start");
const sorted = sortData(data);
performance.mark("sort_end");
console.log(performance.measure("db_time", "db_query_start", "db_query_end"));
console.log(performance.measure("sort_time", "sort_start", "sort_end"));
}
Os resultados das medições podem ser exportados para ferramentas como Prometheus para monitoramento externo. Além disso, é importante limpar as marcações após seu uso:
performance.clearMarks("mark_name");
performance.clearMeasures("measure_name");
Utilizando threads para processamento pesado:
Para evitar que tarefas pesadas congelem a interface do usuário, podemos utilizar workers para processar em segundo plano:
const { Worker, isMainThread, parentPort, workerData } = require("node:worker_threads");
async function main() {
const data = await fetchData(10);
let sorted = await new Promise((resolve, reject) => {
const worker = new Worker(__filename, { workerData: data });
worker.on("message", resolve);
worker.on("error", reject);
worker.on("exit", (code) => {
if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
});
});
}
function worker() {
const data = workerData;
sortData(data);
parentPort.postMessage(data);
}
if (isMainThread) {
main().then(() => { console.log("done"); });
} else {
worker();
}
Dicas finais para otimização:
- Meça antes de otimizar: use a API de Performance para identificar os gargalos reais.
- Reduza dependências: elimine pacotes não utilizados e faça carregamento preguiçoso de módulos.
- Cache e índices: use cache com cautela e crie índices nos campos consultados frequentemente no banco de dados.
Esse resumo contém as explicações principais e o código necessário para entender e aplicar a API de Performance do Node.js para otimização de aplicativos.