Perfilamento de código TypeScript: encontrando gargalos na prática

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Perfilamento de código TypeScript: encontrando gargalos na prática



Quando seu projeto TypeScript começa a ficar lento e os usuários reclamam de atrasos, chega a hora do perfilamento. Perfilamento não é apenas "ver o que está lento", mas uma abordagem sistemática para identificar gargalos no desempenho do código. Neste artigo, vamos explorar métodos práticos de perfilamento de código TypeScript com exemplos reais e ferramentas.



Por que perfilhar código TypeScript?



TypeScript é compilado para JavaScript, e todos os problemas de desempenho inerentes ao JS são transferidos para o TS. No entanto, o TypeScript adiciona suas próprias nuances: tipagem, decoradores, genéricos podem criar custos indiretos inesperados. O perfilamento ajuda a responder perguntas como:

  • Qual função está demorando mais para executar?
  • Onde está ocorrendo um vazamento de memória?
  • Por que a animação está travando em 60fps?
  • Qual algoritmo precisa de otimização?


Ferramentas para perfilamento TypeScript



Chrome DevTools (para código de navegador)

A ferramenta mais poderosa para frontend. Abra a aba Performance, clique em Record, execute a ação e pare a gravação. Você verá um flamegraph — uma visualização das chamadas de função e seu tempo de execução.



// Exemplo de código lento para perfilamentofunction heavyCalculation(iterations: number): number {    let result = 0;    for (let i = 0; i < iterations; i++) {        result += Math.sqrt(i) * Math.sin(i);    }    return result;}

// Execute no console do navegador e depois perfilheheavyCalculation(1000000);


Node.js — perfilador integrado

Para código de servidor, use a flag --inspect e o Chrome DevTools, ou o --prof integrado para gerar logs.



// server.tsimport express from 'express';

const app = express();

app.get('/heavy', (req, res) => { const data = processData(10000); res.json({ result: data });});

function processData(size: number): number[] { const arr: number[] = []; for (let i = 0; i < size; i++) { arr.push(i * Math.random()); } return arr.sort((a, b) => a - b);}

app.listen(3000);// Execução: node --prof dist/server.js


Benchmark.js para medições precisas

Quando precisar comparar duas implementações, use a biblioteca benchmark.



import Benchmark from 'benchmark';

const suite = new Benchmark.Suite();

// Versão lentafunction slowSearch(arr: number[], target: number): boolean { for (let i = 0; i < arr.length; i++) { if (arr[i] === target) return true; } return false;}

// Versão rápida com Setfunction fastSearch(arr: number[], target: number): boolean { const set = new Set(arr); return set.has(target);}

const testArray = Array.from({ length: 10000 }, (_, i) => i);

suite .add('slowSearch', () => slowSearch(testArray, 9999)) .add('fastSearch', () => fastSearch(testArray, 9999)) .on('cycle', (event: any) => console.log(String(event.target))) .on('complete', function(this: any) { console.log('Fastest is ' + this.filter('fastest').map('name')); }) .run({ async: true });


Exemplos práticos de localização de gargalos



Exemplo 1: Vazamento de memória através de closures

Um problema típico em aplicações React — closures que mantêm referências a objetos grandes.



// Código problemáticofunction createHeavyComponent() {    const hugeData = new Array(1000000).fill('data');        return {        getData: () => hugeData, // closure mantém hugeData        updateData: (newData: string) => {            // mutação, mas a referência permanece            hugeData.push(newData);        }    };}

const component = createHeavyComponent();// hugeData não será coletado pelo GC enquanto component existir


<

Blogs

Book Recommendations