🚀 Oferta especial: 60% OFF no CrazyStack - Últimas vagas!Garantir vaga →
MÓDULO 1 - AULA 3

Processamento Sob Demanda

Por que arrays são inimigos da memória. Linha de produção vs piscina de dados

🎯 O grande problema dos arrays

"Tá, mas para que você retornaria mais de um valor de uma função em JavaScript? Por que não só retornar um array com todos os itens dentro?" Essa é a dúvida que todo desenvolvedor tem. A resposta está na memória e performance.

🏊 Piscina vs Torneira: A analogia perfeita

❌ Problema: Arrays são "piscinas"

Quando você usa arrays para processar dados grandes, é como encher uma piscina inteira para tomar um gole d'água. Você carrega TUDO na memória antes de usar qualquer coisa, desperdiçando recursos massivamente.

array-problem.js
// ❌ PROBLEMA: "Piscina de dados" - Enche tudo na memória
function processAllUsers() {
  console.log('🏊 Criando "piscina" de 1 milhão de usuários...');
  
  const users = []; // 🏊 A "piscina" que vai crescer absurdamente
  
  // Simula buscar 1 milhão de usuários do banco
  for (let i = 0; i < 1000000; i++) {
    users.push({
      id: i,
      name: `User ${i}`,
      email: `user${i}@email.com`,
      profile: {
        bio: 'Bio muito longa aqui'.repeat(100), // 🔥 Dados pesados
        preferences: Array(50).fill('config'),
        history: Array(100).fill('action')
      }
    });
  }
  
  console.log('💾 Memória usada: ~2GB'); // 🔥 ABSURDO!
  console.log(`📊 Total de usuários: ${users.length}`);
  
  return users; // Retorna piscina inteira
}

// 🎯 USO: Só quero 5 usuários específicos
const allUsers = processAllUsers(); // 😱 Carregou 1 milhão
const firstFive = allUsers.slice(0, 5); // 🤦 Só usou 5!

console.log('Resultado:', firstFive.map(u => u.name));

// 💀 RESULTADO: 
// - 2GB de RAM desperdiçados
// - Tempo de carregamento absurdo  
// - Aplicação pode travar
// - Para usar 5, carregou 1 milhão!

💧 A torneira inteligente

✅ Solução: Generators são "torneiras"

Generators funcionam como uma torneira inteligente: só produzem dados quando você realmente precisa. Cada yield é uma "gota" que sai sob demanda, economizando memória e tempo.

generator-solution.js
// ✅ SOLUÇÃO: "Torneira de dados" - Produz sob demanda
function* processUsersStream() {
  console.log('💧 Iniciando "torneira" de usuários...');
  
  // Simula processamento em lotes pequenos
  for (let batch = 0; batch < 10000; batch++) { // 10k lotes de 100
    console.log(`🔄 Processando lote ${batch + 1}...`);
    
    // Processa 100 usuários por vez (batch processing)
    for (let i = 0; i < 100; i++) {
      const userId = batch * 100 + i;
      
      // 💧 UMA "gota" por vez - só quando pedido
      yield {
        id: userId,
        name: `User ${userId}`,
        email: `user${userId}@email.com`,
        profile: {
          bio: 'Bio muito longa aqui'.repeat(100),
          preferences: Array(50).fill('config'),
          history: Array(100).fill('action')
        }
      };
    }
    
    // 🎯 AQUI: Poderia pausar, fazer rate limiting, buscar próximo batch do banco
    // await new Promise(resolve => setTimeout(resolve, 100)); // Pausa entre lotes
  }
  
  console.log('🏁 Torneira terminada!');
}

// 🎯 USO INTELIGENTE: Só consome o que precisa
let count = 0;
for (const user of processUsersStream()) {
  console.log(`📦 Recebido: ${user.name}`);
  count++;
  
  if (count >= 5) {
    console.log('✂️ Parando a torneira - já tenho o suficiente!');
    break; // 🛑 Para a "torneira"
  }
}

// 💡 RESULTADO INCRÍVEL:
// - ~5KB de RAM (vs 2GB do array)
// - Parou instantaneamente
// - Processou apenas 5 usuários
// - Aplicação não travou!

console.log('📊 Memória economizada: 99.75%!');

🏭 Linha de produção: Eficiência real

🎯 Analogia Industrial

Pense numa fábrica moderna: ela não produz milhões de carros para depois vender. Ela produz conforme o pedido chega. Generators fazem isso com dados: processam conforme a demanda.

production-line.js
// 🏭 LINHA DE PRODUÇÃO: Processa arquivo CSV gigante
function* processCSVFile(filename) {
  console.log(`🏭 Iniciando linha de produção para ${filename}`);
  
  // Simula arquivo CSV com milhões de linhas
  const csvLines = [
    'id,nome,email,cidade,salario',
    '1,João Silva,joao@email.com,São Paulo,5000',
    '2,Maria Santos,maria@email.com,Rio de Janeiro,6000',
    '3,Pedro Costa,pedro@email.com,Belo Horizonte,4500',
    // ... imagine 2 milhões de linhas aqui
  ];
  
  for (let i = 1; i < csvLines.length; i++) { // Pula header
    const line = csvLines[i];
    
    // 🔧 ESTAÇÃO 1: Parser CSV
    const [id, nome, email, cidade, salario] = line.split(',');
    
    // 🔧 ESTAÇÃO 2: Validação
    if (!email.includes('@')) {
      console.log(`⚠️ Email inválido na linha ${i}: ${email}`);
      continue; // Pula linha inválida
    }
    
    // 🔧 ESTAÇÃO 3: Transformação
    const usuario = {
      id: parseInt(id),
      nome: nome.trim(),
      email: email.toLowerCase(),
      cidade: cidade.trim(),
      salario: parseFloat(salario),
      // Dados calculados
      salarioAnual: parseFloat(salario) * 12,
      categoria: parseFloat(salario) > 5500 ? 'senior' : 'junior',
      processadoEm: new Date().toISOString()
    };
    
    // 📤 PRODUTO FINALIZADO: Sai da linha de produção
    console.log(`✅ Produto pronto: ${usuario.nome} (${usuario.categoria})`);
    yield usuario;
    
    // 🎯 VANTAGEM: Próximo cliente pode usar este usuário
    // enquanto a linha continua produzindo os outros!
  }
  
  console.log('🏁 Linha de produção finalizada!');
}

// 👥 MÚLTIPLOS CONSUMIDORES: Podem processar em paralelo
console.log('=== CONSUMIDOR 1: Relatório de Seniors ===');
let seniorCount = 0;
for (const usuario of processCSVFile('usuarios.csv')) {
  if (usuario.categoria === 'senior') {
    console.log(`📊 Senior encontrado: ${usuario.nome} - R$${usuario.salarioAnual}/ano`);
    seniorCount++;
    
    if (seniorCount >= 3) {
      console.log('✂️ Relatório completo - 3 seniors encontrados!');
      break;
    }
  }
}

// 💡 RESULTADO FANTÁSTICO:
// - Arquivo de 2GB processado linha por linha
// - Apenas ~1KB na memória por vez
// - Parou assim que achou o que precisava
// - Não travou nem deu timeout!

📊 Performance Real: Números que impressionam

❌ Abordagem com Arrays

Memória: 2GB+ para 1M registros

Tempo inicial: 15-30 segundos

Para usar 5: Carrega 1 milhão

Travamento: UI congelada

CPU: Pico de 100%

Mobile: Crash garantido

✅ Abordagem com Generators

Memória: ~1KB constante

Tempo inicial: Instantâneo

Para usar 5: Processa apenas 5

Travamento: Zero

CPU: Baixo e estável

Mobile: Funciona perfeitamente

performance-benchmark.js
// 📊 BENCHMARK: Comparação real de performance
console.log('=== TESTE DE PERFORMANCE ===');

// ❌ TESTE 1: Array tradicional
console.time('Array Approach');
function arrayApproach() {
  const data = [];
  for (let i = 0; i < 100000; i++) { // 100k para não travar tudo
    data.push({
      id: i,
      data: 'x'.repeat(1000), // 1KB por item
      timestamp: Date.now()
    });
  }
  return data.slice(0, 10); // Usa apenas 10
}

const arrayResult = arrayApproach();
console.timeEnd('Array Approach');
console.log('Memory Array: ~100MB para usar 10 itens');

// ✅ TESTE 2: Generator approach  
console.time('Generator Approach');
function* generatorApproach() {
  for (let i = 0; i < 100000; i++) {
    yield {
      id: i,
      data: 'x'.repeat(1000), // 1KB por item
      timestamp: Date.now()
    };
  }
}

const generatorResult = [];
let count = 0;
for (const item of generatorApproach()) {
  generatorResult.push(item);
  count++;
  if (count >= 10) break;
}
console.timeEnd('Generator Approach');
console.log('Memory Generator: ~10KB para usar 10 itens');

// 📊 RESULTADO TÍPICO:
// Array Approach: 150-300ms + 100MB RAM
// Generator Approach: 1-5ms + 10KB RAM
// 
// 🏆 VENCEDOR: Generator é 60x mais rápido e 10.000x mais eficiente!

console.log('\n=== DIFERENÇA DE MEMÓRIA ===');
console.log('Array: Como comprar um supermercado para tomar um refrigerante');
console.log('Generator: Como comprar apenas o refrigerante que vai beber');

🎯 Casos de uso reais no mundo

🌍 Aplicações do Mundo Real

Empresas como Netflix, Google e Amazon usam processamento sob demanda para lidar com bilhões de dados sem quebrar. Aqui estão cenários onde generators salvam o dia.

📊 Analytics de Logs

Problema: Analisar 50GB de logs diários

Array: Impossível - estoura memória

Generator: Processa linha por linha

Resultado: Relatórios em tempo real

🛒 E-commerce Search

Problema: Buscar em 10M produtos

Array: Carrega tudo para mostrar 20

Generator: Filtra sob demanda

Resultado: Busca instantânea

📱 Social Media Feed

Problema: Scroll infinito de posts

Array: Pré-carrega milhares de posts

Generator: Carrega conforme scroll

Resultado: App fluido e rápido

💳 Financial Processing

Problema: Processar milhões de transações

Array: Risco de timeout e crash

Generator: Batch processing seguro

Resultado: Processamento 24/7

🚀 Checkpoint: Mestre da Eficiência

Piscina vs TorneiraLinha de ProduçãoPerformance 99%+Casos de Uso Reais

Agora você entende por que generators revolucionam o processamento de dados!