Alguém está errado na Internet novamente - no Node Weekly de ontem, havia um link para uma postagem na qual o autor está tentando medir e comparar o desempenho da API de fluxo no Node.js. A tristeza causa como o autor trabalha com fluxos e que conclusões ele tenta tirar com base nisso:
... isso funcionou muito bem em arquivos menores, mas quando cheguei ao arquivo maior, ocorreu o mesmo erro. Embora o Node.js estivesse transmitindo as entradas e saídas, ele ainda tentou manter o arquivo inteiro na memória enquanto executava as operações
Vamos tentar descobrir o que há de errado com as conclusões e o código do autor.
Do meu ponto de vista, o problema é que o autor do artigo não sabe como usar o Stream'ami e esse é um problema que você precisa encontrar com frequência. Este fenômeno, na minha opinião, tem três razões:
- A história complexa da API de fluxo do Node.js. - a dor e o sofrimento descritos aqui
- Não é a API mais intuitiva se você tentar usá-la sem invólucros
- Documentação bastante estranha que apresenta fluxos como algo muito complexo e de baixo nível
Em conjunto, isso leva ao fato de que os desenvolvedores geralmente não sabem como e não querem usar a API de Stream.
O que há de errado com o código do autor ?
Para começar, repita a tarefa aqui (o original em inglês e um link para o arquivo podem ser encontrados na postagem):
Há um certo arquivo de 2,5 GB com linhas no formato:
C00084871|N|M3|P|201703099050762757|15|IND|COLLINS, DARREN ROBERT|SOUTHLAKE|TX|760928782|CELANESE|VPCHOP&TECH|02282017|153||PR2552193345215|1151824||P/R DEDUCTION ($76.92 BI-WEEKLY)|4030920171380058715
Você precisa analisá-lo e descobrir as seguintes informações:
- O número de linhas no arquivo
- Nomes nas 432ª e 43243ª linhas (aqui a verdade surge a questão de como contar, de 0 ou 1?)
- O nome mais comum e quantas vezes ocorre
- O número de parcelas para cada mês
Qual é o problema? - O autor diz honestamente que carrega o arquivo inteiro na memória e, por causa disso, o Node "trava" e o autor nos fornece um fato interessante.
Curiosidade: o Node.js pode armazenar apenas 1,67 GB de memória por vez
O autor faz uma conclusão estranha desse fato: são os Streams que carregam o arquivo inteiro na memória e ele não escreveu o código errado.
Vamos refutar a tese: " Embora o Node.js estivesse transmitindo as entradas e saídas, ele ainda tenta armazenar o arquivo inteiro ", escrevendo um pequeno programa que contará o número de linhas em um arquivo de qualquer tamanho:
const { Writable } = require('stream') const fs = require('fs') const split = require('split') let counter = 0 const linecounter = new Writable({ write(chunk, encoding, callback) { counter = counter + 1 callback() }, writev(chunks, callback) { counter = counter + chunks.length callback() } }) fs.createReadStream('itcont.txt') .pipe(split()) .pipe(linecounter) linecounter.on('finish', function() { console.log(counter) })
Nota : o código foi intencionalmente escrito da maneira mais simples possível. Variáveis globais são ruins!
O que você deve prestar atenção:
- split - npm um pacote que recebe um fluxo de linhas na "entrada" - retorna um fluxo de conjuntos de linhas para a "saída" com uma quebra de linha separada. Provavelmente feito como uma implementação do fluxo de transformação. Nós canalizamos nele nosso ReadStream com um arquivo e ...
- linecounter - Implementação do WritableStream. Nele, implementamos dois métodos: para processar uma peça (chunk) e várias. A "linha" nesta situação é a linha de código. Inverter - adicione o número desejado ao contador. É importante entender que nessa situação não carregaremos o arquivo inteiro na memória, e a API dividirá tudo para nós em "partes" mais convenientes para o processamento
- 'finish' - eventos que “acontecem” quando os dados que chegam ao nosso ReadableStream “terminam”. Quando isso acontece, prometemos dados do contador
Bem, vamos testar nossa criação em um arquivo grande:
> node linecounter.js 13903993
Como você pode ver, tudo funciona. Pelo que podemos concluir que a API Stream faz um excelente trabalho com arquivos de qualquer tamanho e a declaração do autor da postagem, para dizer o mínimo, não é verdadeira. Aproximadamente da mesma maneira, podemos calcular qualquer outro valor necessário no problema.
Diga:
- Você está interessado em ler como resolver o problema completamente e como colocar o código resultante em um formulário conveniente para manutenção?
- Você usa a API do Stream e quais dificuldades você encontrou?