Skip to content

bmenegidio/clinic-benchmark-image-io

Repository files navigation

🚀 Clinic Benchmark - Image File I/O

Benchmark de leitura e escrita de arquivos de imagem utilizando duas abordagens diferentes com Node.js: leitura direta (buffer) e stream.

🧠 Descrição

Este projeto visa comparar o desempenho entre dois métodos de leitura e escrita de arquivos:

  • 📦 read-file.ts: usa readFile e writeFile do fs/promises, lendo e escrevendo o arquivo inteiro na memória (buffer).
  • 🌊 read-file-stream.ts: usa createReadStream e createWriteStream com pipeline para processar os arquivos por streaming.

O benchmark é realizado com a ferramenta Clinic.js.

📁 Imagens de teste

Para realizar os testes, cole uma ou mais imagens na pasta input/.

👉 Como sugestão, você pode baixar imagens grandes no site: visibleearth.nasa.gov

⚠️ Observação sobre uso do ImageMagick via spawn

Este projeto utiliza o ImageMagick através do comando spawn do Node.js para realizar operações de manipulação de imagem. Optou-se por essa abordagem para evitar o controle interno de memória que bibliotecas como Sharp possuem, permitindo um benchmark mais fiel do desempenho puro das operações de leitura e escrita via streaming.

Dessa forma, o fluxo do processo é: leitura do arquivo de imagem -> manipulação via ImageMagick executado em processo separado -> escrita do arquivo de saída.

Isso garante uma avaliação realista da performance do I/O sem interferência de otimizações internas específicas.

🛠️ Scripts disponíveis

Antes de iniciar, é necessário compilar os arquivos TypeScript:

npm run build

⚙️ Benchmark com leitura direta (buffer)

npm run start-read-file

🔁 Benchmark com leitura via stream

npm run start-read-file-stream

📦 Pré-requisitos

  • Node.js >= 20.10.0
  • npm
  • Clinic.js (instalado via dependências do projeto)

📂 Organização dos diretórios

  • input/: arquivos de entrada.
  • output/: arquivos gerados após leitura e escrita.

📊 Resultados do Benchmark

A ferramenta Clinic.js Doctor foi utilizada para medir o impacto de cada abordagem no uso de memória durante o processamento dos arquivos de imagem.

Os testes foram realizados processando:

  • 🖼️ 1 arquivo .tif (~30,5 MB)
  • 🖼️ 1 arquivo .png (~292,8 MB)

🔢 Volume total processado: ~323,3 MB

📦 Leitura e escrita com readFile / writeFile (buffer)

Leitura com Buffer

  • 🧠 355 MB de uso de memória RSS
  • Tempo de uso concentrado logo no início, com carga alta em pouco tempo

🌊 Leitura e escrita com createReadStream / createWriteStream (stream)

Leitura com Stream

  • 🧠 90 MB de uso de memória RSS (redução de ~75% em relação ao buffer)
  • Comportamento muito mais estável e previsível

🚀 Considerações de desempenho e escalabilidade

A abordagem com readFile e writeFile realiza a leitura e escrita do arquivo inteiro na memória, o que causa um alto consumo de memória RAM (como evidenciado pelo pico de 355 MB no teste com apenas dois arquivos). Esse método pode rapidamente se tornar um gargalo em aplicações que lidam com arquivos grandes ou múltiplos arquivos simultaneamente.

Por outro lado, a abordagem com createReadStream e createWriteStream utiliza streams, que carregam e processam os dados de forma incremental e contínua, sem precisar manter o arquivo inteiro na memória. Isso reduz drasticamente o uso de memória (cerca de 90 MB no mesmo cenário de teste) e torna o sistema muito mais eficiente.

As vantagens do uso de streams incluem:

  • 🔁 Melhor gerenciamento de memória, evitando sobrecarga e gargalos
  • 💸 Menor custo com infraestrutura, especialmente em servidores em nuvem com cobrança por uso de memória e CPU
  • 🧱 Maior escalabilidade, permitindo processar múltiplos arquivos em paralelo sem comprometer o desempenho do sistema
  • ⚙️ Mais estabilidade e previsibilidade, com uso consistente de recursos mesmo em cenários de carga elevada

✅ Sempre que possível, prefira streams para tarefas intensivas de I/O com arquivos, especialmente imagens, vídeos, grandes documentos ou qualquer dado binário pesado.


📄 Licença

MIT © Bruno Menegidio