FNSP Web Page

Ficheiros grandes no Node sem encher a memória

Este código funciona em desenvolvimento e cai em produção:

import { readFile } from 'node:fs/promises';

const conteudo = await readFile('registos.csv', 'utf8');
const linhas = conteudo.split('\n');

Com um ficheiro de teste de 2 MB, é instantâneo. Com o ficheiro real de 3 GB, o processo tenta carregar tudo para memória de uma vez — e morre, ou leva o servidor com ele.

Os streams existem para isto: processar aos bocados, com a memória a manter-se constante independentemente do tamanho.

1. Ler linha a linha

import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';

const linhas = createInterface({
  input: createReadStream('registos.csv', 'utf8'),
  crlfDelay: Infinity, // trata \r\n como uma quebra só
});

let total = 0;

for await (const linha of linhas) {
  total += Number(linha.split(',')[3] ?? 0);
}

console.log(total);

O ficheiro pode ter 3 GB: em memória está uma linha de cada vez.

2. Ligar as pontas com pipeline

Quando há transformação pelo meio — comprimir, converter, filtrar — a forma correta é o pipeline, e não encadear .pipe() à mão:

import { createReadStream, createWriteStream } from 'node:fs';
import { createGzip } from 'node:zlib';
import { pipeline } from 'node:stream/promises';

await pipeline(
  createReadStream('registos.csv'),
  createGzip(),
  createWriteStream('registos.csv.gz')
);

console.log('comprimido');

A diferença não é de estilo: o pipeline propaga os erros e fecha tudo quando um dos lados falha. Com .pipe(), um erro a meio deixa ficheiros abertos e o processo pendurado.

3. A parte que se esquece: a contrapressão

Se o destino for mais lento do que a origem — escrever num disco lento, enviar por rede — os streams travam a leitura sozinhos. É isso que impede a memória de crescer enquanto o consumidor não acompanha.

Escrever o mesmo ciclo à mão com readFile e writeFile não tem nada disto: lê tudo à velocidade máxima e acumula o que o outro lado ainda não conseguiu escrever.

Comentários

Ainda ninguém comentou este artigo.

Voltar ao blog

Gostávamos de saber quantas pessoas visitam o site, com o Google Analytics. Sem a sua autorização não corre nada. Política de Privacidade.