☕ Um Café no Bellacosa Mainframe
Gostou do conteúdo? Ajude a manter o café quente, o COBOL compilando e o mainframe acordado. 😄
☕ Pague um café ao Bellacosa

Translate

domingo, 4 de novembro de 2012

💀 AINZ OOAL GOWN E A GRANDE TUMBA DA LATÊNCIA — QUANDO O PROGRAMADOR COBOL DESCOBRIU QUE O PROGRAMA DE 4 MILISSEGUNDOS PODIA DEMORAR 3 SEGUNDOS

 

Bellacosa Mainframe e a latencia

☕ Um Café no Bellacosa Mainframe

💀 AINZ OOAL GOWN E A GRANDE TUMBA DA LATÊNCIA — QUANDO O PROGRAMADOR COBOL DESCOBRIU QUE O PROGRAMA DE 4 MILISSEGUNDOS PODIA DEMORAR 3 SEGUNDOS

Latência, throughput, cache, Db2, MQ, CICS, WLM, filas, locks, CDN, sharding, paralelismo, p99, backpressure, retries, observabilidade — e o dia em que Ainz descobriu que o verdadeiro Floor Guardian do datacenter era um WAIT.



🎬 PRÓLOGO — BEM-VINDO À GRANDE TUMBA DE NAZARICK

O jovem programador COBOL entrou na sala de operações carregando uma notícia terrível.

— Lorde Ainz! Temos um incidente!

Ainz Ooal Gown permaneceu imóvel em seu trono.

Por dentro, entretanto, provavelmente estava acontecendo algo bem diferente.

"Incidente? Será que esperam que eu saiba alguma coisa sobre performance? Demiurge certamente já entendeu tudo. Preciso apenas parecer que isso fazia parte do meu plano."

— Continue.

— A transação está demorando três segundos!

Albedo arregalou os olhos.

Demiurge ajustou os óculos.

Shalltear sugeriu eliminar fisicamente o servidor.

Cocytus considerou a proposta tecnicamente interessante.

Ainz levantou uma das mãos.

— Quanto tempo de CPU o programa COBOL consumiu?

Silêncio.

O programador consultou o monitor.

RESPONSE TIME : 3.017 segundos
CPU TIME      : 0.004 segundos

Ainz continuou imóvel.

— Então por que você está tentando otimizar o COBOL?

E naquele momento nasceu uma das perguntas mais importantes de performance engineering:

Se o programa consumiu quatro milissegundos de CPU, onde foram parar os outros 3.013 milissegundos?

Bem-vindo à dungeon da latência.

E cuidado.

O primeiro monstro quase nunca está onde você pensa.



🧙 CAPÍTULO 1 — O QUE DIABOS É LATÊNCIA?

Antes de Redis, CDN, paralelismo, MQ, sharding ou qualquer feitiço de décimo nível, precisamos entender o problema.

Latência é o tempo decorrido entre iniciar uma operação e observar seu resultado.

Imagine uma transação CICS extremamente simples.

O usuário pressiona ENTER às:

10:15:00.000

e recebe a resposta às:

10:15:00.850

Temos aproximadamente:

850 ms

de tempo de resposta.

Mas isso não significa que o processador trabalhou durante 850 milissegundos.

A transação pode ter feito algo assim:

Receber requisição          10 ms
Fila                        30 ms
COBOL CPU                    4 ms
Db2                         70 ms
MQ                          40 ms
API externa                650 ms
Preparar resposta           20 ms
Rede                        26 ms
--------------------------------
TOTAL                      850 ms

Olhe novamente para o COBOL.

4 ms

Agora olhe para a API externa.

650 ms

Se você tornar o COBOL 50% mais rápido, economizará dois milissegundos.

O usuário passará de:

850 ms

para aproximadamente:

848 ms

Parabéns.

Você passou três semanas refatorando um programa crítico para ninguém perceber diferença alguma.

Ainz provavelmente chamaria isso de:

Greater Optimization of the Wrong Thing.



⚔️ CAPÍTULO 2 — CPU TIME NÃO É RESPONSE TIME

Essa distinção precisa entrar na cabeça de todo programador iniciante.

CPU time é o tempo durante o qual o processador efetivamente executa instruções relacionadas ao trabalho.

Elapsed time é o tempo de relógio transcorrido.

Response time representa, em linhas gerais, quanto tempo o consumidor espera pela resposta.

Eles não são necessariamente iguais.

Imagine:

EXEC SQL
   SELECT NOME,
          SALDO
     INTO :WS-NOME,
          :WS-SALDO
     FROM CLIENTE
    WHERE CONTA = :WS-CONTA
END-EXEC.

Seu programa chega ao SELECT.

Nesse instante, ele talvez precise esperar.

Pode haver I/O.

Pode haver contenção.

Pode haver lock.

Pode haver recursos indisponíveis.

O programa não está necessariamente queimando CPU durante toda essa espera.

É como Cocytus chegar diante de uma porta fechada.

Ele continua sendo extremamente poderoso.

Mas não está avançando.

Essa é uma maneira excelente de pensar sobre performance:

Um sistema lento nem sempre está trabalhando demais. Muitas vezes está esperando demais.



🏰 CAPÍTULO 3 — LATÊNCIA NÃO É THROUGHPUT

Outro erro clássico é tratar velocidade individual e capacidade total como se fossem a mesma coisa.

Imagine um restaurante.

Um prato leva cinco minutos para ser preparado.

Isso é parecido com latência.

A cozinha consegue produzir 300 pratos por hora.

Isso é parecido com throughput.

Em sistemas:

Latência:
80 ms por transação

Throughput:
5.000 transações por segundo

São métricas diferentes.

Podemos ter uma aplicação com excelente throughput e algumas requisições terrivelmente lentas.

Também podemos construir um sistema no qual cada transação individual seja rápida, mas que entre em colapso quando milhares chegam simultaneamente.

E existe ainda uma terceira dimensão:

utilização dos recursos.

CPU, memória, canais, discos, conexões, threads, tasks, regiões, filas e demais recursos têm limites.

Por isso uma análise séria não pergunta apenas:

"Quanto demora?"

Ela pergunta:

"Quanto demora, sob qual carga, consumindo quais recursos e esperando por quê?"

Agora estamos começando a fazer engenharia.



📊 CAPÍTULO 4 — A MÉDIA É UM MIMIC DISFARÇADO DE BAÚ

Imagine dez transações:

10 ms
11 ms
10 ms
12 ms
11 ms
10 ms
12 ms
11 ms
10 ms
3000 ms

Se você olhar apenas uma média agregada, pode perder a informação mais importante:

alguém esperou três segundos.

Por isso aparecem métricas como:

p50
p90
p95
p99
p99.9

O p50 é aproximadamente a mediana.

O p99 significa que 99% das observações ficaram naquele valor ou abaixo dele, enquanto aproximadamente 1% ficou acima.

Imagine:

p50 = 70 ms
p95 = 180 ms
p99 = 1.800 ms

A maioria das pessoas recebe uma experiência excelente.

Mas aproximadamente uma em cada cem requisições entra na Grande Tumba de Nazarick e não encontra a saída tão cedo.

Isso é tail latency.

E sistemas distribuídos tornam o fenômeno ainda mais perigoso.

Se uma transação depende de dez serviços, existem dez oportunidades para alguma coisa atrasar.

                    ┌── Serviço A
                    ├── Serviço B
Usuário → API ──────┼── Serviço C
                    ├── Serviço D
                    └── Serviço E

Se você precisa esperar todos terminarem, o componente mais lento pode determinar boa parte da experiência.

O aventureiro mais rápido do grupo não importa muito quando todos precisam esperar o anão chegar.


🧊 CAPÍTULO 5 — CACHE: O FEITIÇO QUE EVITA REPETIR TRABALHO

Caching é uma das técnicas mais antigas e poderosas da computação.

O conceito é simples:

se obter alguma coisa é caro e provavelmente precisaremos dela novamente, podemos guardar uma cópia em um lugar mais rápido.

Isso aparece em todos os níveis da arquitetura.

CPU possui caches.

Sistemas operacionais fazem caching.

Browsers possuem cache.

Bancos mantêm páginas em memória.

CDNs fazem caching.

Aplicações podem utilizar produtos como Redis e Memcached.

No universo Db2, a própria existência de buffer pools já deveria fazer o mainframer perceber que o conceito está longe de ser novidade.

Em vez de:

Aplicação
   ↓
Banco
   ↓
Storage
   ↓
Página
   ↓
Dado

podemos conseguir:

Aplicação
   ↓
Banco
   ↓
Memória
   ↓
Dado

Maravilhoso.

Até alguém alterar o dado original.

Agora aparece um dos problemas clássicos da ciência da computação:

invalidação de cache.

Imagine:

Db2:
SALDO = 1.000

Cache:
SALDO = 800

Você ganhou performance.

E talvez tenha criado um incidente bancário.

Portanto, cache envolve decisões sobre validade, consistência, TTL, invalidação, eviction, cache hit, cache miss e natureza do dado.

Guardar uma imagem desatualizada por vinte segundos pode ser irrelevante.

Guardar um saldo financeiro incorreto pode ser catastrófico.

Ainz chama Demiurge.

Demiurge responde:

— Tudo ocorreu exatamente como o senhor previu.

Ainz pensa:

"Eu definitivamente não previ o cache stale."


⚖️ CAPÍTULO 6 — LOAD BALANCING: MAIS SERVIDORES NÃO CONSERTAM SQL RUIM

Load balancing distribui trabalho.

Imagine:

                 ┌── Server A
Cliente → LB ────┼── Server B
                 ├── Server C
                 └── Server D

Se um servidor está recebendo carga demais, distribuir requisições pode reduzir filas, melhorar disponibilidade e aumentar capacidade.

Mas existe uma pegadinha deliciosa.

Suponha que todos executem esta operação:

consulta horrorosa = 4 segundos

Adicionar servidores produz:

Server A = lento
Server B = lento
Server C = lento
Server D = lento

Você criou um cluster de lentidão.

Load balancing combate certos tipos de gargalo.

Não transforma código ineficiente em código eficiente.

Essa distinção vale ouro:

Escalar um problema pode apenas produzir mais instâncias do problema.


📬 CAPÍTULO 7 — PROCESSAMENTO ASSÍNCRONO: O MAINFRAME JÁ CONHECIA ESSE FEITIÇO

Um jovem desenvolvedor cloud anuncia:

— Mestre Ainz! Descobrimos processamento assíncrono!

Um programador mainframe de 1987 levanta a sobrancelha.

— Fila?

— Sim.

— Mensagem?

— Sim.

— Produtor e consumidor desacoplados?

— Sim.

— Próximo assunto.

Processamento assíncrono remove determinadas tarefas do caminho crítico da resposta.

Imagine uma compra.

No modelo totalmente síncrono:

Compra
  ↓
Pagamento
  ↓
Estoque
  ↓
Nota
  ↓
E-mail
  ↓
Analytics
  ↓
Resposta

O cliente precisa esperar tudo.

Mas será realmente necessário esperar o envio do e-mail?

Talvez possamos fazer:

Compra
  ↓
Processamento essencial
  ↓
MQ ─────→ e-mail
  ├──────→ analytics
  └──────→ processamento posterior
  ↓
Resposta

A percepção de latência diminui.

Mas existe uma frase que merece ser gravada na parede:

Assíncrono não significa que o trabalho desapareceu. Significa que alguém deixou de esperar por ele.

E o preço aparece em outra parte.

Agora precisamos pensar em mensagens duplicadas, retries, ordenação, idempotência, dead-letter queues, monitoramento, backpressure e consistência eventual.

Nada é grátis em Nazarick.

Nem MQ.


🗄️ CAPÍTULO 8 — DB2: ANTES DE COMPRAR CPU, OLHE PARA O ACCESS PATH

Imagine:

SELECT *
  FROM TRANSACOES
 WHERE CLIENTE = :WS-CLIENTE;

Parece inocente.

Agora descubra que TRANSACOES contém centenas de milhões de linhas.

A pergunta deixa de ser:

"O SQL está correto?"

e passa a ser:

"Como o Db2 encontrará essas linhas?"

Entram em cena índices, estatísticas, cardinalidade, access paths, joins, sorts, buffer pools e quantidade de dados movimentados.

Outra dica importantíssima:

SELECT *

pode buscar muito mais informação do que a aplicação necessita.

Se você precisa apenas:

CLIENTE
SALDO
STATUS

por que transportar outras dezenas de colunas?

Entretanto, índices também possuem custo.

Eles precisam ocupar espaço e ser mantidos conforme os dados mudam.

Então:

mais índice ≠ automaticamente melhor

O objetivo é oferecer bons caminhos para o workload real.

Performance não é colecionar índices como Ainz coleciona itens mágicos.


🧩 CAPÍTULO 9 — SHARDING: MAGIA DE ALTO NÍVEL, NÃO FEITIÇO DE APRENDIZ

Sharding divide um grande conjunto de dados em partes.

Por exemplo:

A–F → SHARD A
G–M → SHARD B
N–S → SHARD C
T–Z → SHARD D

Isso pode permitir distribuir armazenamento e processamento.

Excelente.

Até aparecer:

SELECT ...

que precisa consultar todos os shards.

Agora existem múltiplas máquinas, redes, falhas, coordenação e resultados para combinar.

Também podemos criar um hot shard.

Imagine que a divisão seja feita por região e 70% das transações estejam concentradas em uma única região.

Três shards tomam café.

Um pega fogo.

Sharding resolve determinados problemas gigantescos de escala, mas aumenta a complexidade.

Por isso não deveria ser a primeira reação diante de:

"Minha consulta está lenta."

Talvez esteja faltando simplesmente um índice adequado.

Não invoque magia de décimo nível para matar um Goblin.


🌎 CAPÍTULO 10 — CDN E A VELOCIDADE DA LUZ

Existe um adversário que nem COBOL, Java, Rust, Go ou magia de Nazarick derrotam:

a física.

Se o usuário está no Brasil e cada operação precisa conversar repetidamente com um servidor do outro lado do planeta, existe distância envolvida.

CDNs aproximam conteúdo do consumidor.

                 ┌── Edge Brasil
                 ├── Edge Europa
Origin → CDN ────┼── Edge EUA
                 └── Edge Ásia

Imagens, CSS, JavaScript, vídeos e outros objetos podem ser fornecidos a partir de pontos mais próximos.

É uma ideia brilhantemente simples:

A requisição mais rápida através de um oceano pode ser aquela que não precisa atravessar o oceano.


🌐 CAPÍTULO 11 — CADA NETWORK HOP É UMA PORTA DA DUNGEON

Observe uma arquitetura moderna:

Browser
   ↓
CDN
   ↓
WAF
   ↓
Load Balancer
   ↓
API Gateway
   ↓
Microservice A
   ↓
Microservice B
   ↓
Microservice C
   ↓
Database

Cada caixinha parece elegante em um PowerPoint.

Mas cada seta pode envolver rede, autenticação, serialização, TLS, filas, logging, tracing, processamento e possíveis retries.

Arquitetura possui custo.

Microsserviços podem oferecer excelentes vantagens organizacionais e técnicas, mas dividir um processo local em várias chamadas remotas não reduz automaticamente latência.

Uma chamada de função dentro do mesmo processo e uma requisição atravessando a rede são criaturas completamente diferentes.

Esse é um ponto que o veterano de mainframe costuma entender intuitivamente:

movimentar dados custa.


🔮 CAPÍTULO 12 — PREFETCH: ALBEDO TENTA ADIVINHAR O QUE AINZ PEDIRÁ

Prefetching significa antecipar uma necessidade.

Se o usuário pediu A e existe grande probabilidade de pedir B em seguida, podemos carregar B antecipadamente.

Quando acertamos:

Usuário pede B
      ↓
B já está disponível

Excelente experiência.

Quando erramos, consumimos recursos buscando algo que ninguém queria.

Portanto prefetch troca:

possível desperdício agora

por

possível redução de espera depois.

É essencialmente uma aposta baseada em padrões de acesso.

Com modelos preditivos, essa decisão pode ficar ainda mais sofisticada.

Mas previsão continua sendo previsão.

Até Demiurge pode errar.

Embora jamais admita isso diante de Ainz.


⚔️ CAPÍTULO 13 — PARALELISMO: QUATRO FLOOR GUARDIANS TRABALHANDO AO MESMO TEMPO

Temos quatro tarefas independentes:

A = 100 ms
B = 100 ms
C = 100 ms
D = 100 ms

Sequencialmente:

A → B → C → D

≈ 400 ms

Se puderem executar simultaneamente:

 ┌── A
 ├── B
 ├── C
 └── D

≈ 100 ms + overhead

Parece fantástico.

Mas suponha que todos precisem do mesmo recurso exclusivo.

A ─┐
B ─┼──→ LOCK
C ─┤
D ─┘

Agora temos contenção.

Adicionar concorrência pode aumentar filas.

Existe um limite a partir do qual mais trabalhadores não produzem proporcionalmente mais trabalho.

É como colocar cem cozinheiros em uma cozinha feita para cinco.

A cozinha não fica vinte vezes mais rápida.

Talvez ninguém consiga abrir a geladeira.


🔌 CAPÍTULO 14 — CONNECTION POOLING: NÃO RECONSTRUA A PONTE A CADA VIAGEM

Estabelecer conexões pode custar caro.

Imagine executar milhares de vezes:

conectar
autenticar
negociar
usar
desconectar

Se determinadas conexões puderem ser reutilizadas, um pool permite:

          ┌── conexão 1
Requests ─┼── conexão 2
          ├── conexão 3
          └── conexão 4

Mas até aqui existe equilíbrio.

Pool pequeno demais:

requisições esperando conexão

Pool exageradamente grande:

recursos desperdiçados
sobrecarga no destino
contenção

Mais uma vez:

performance engineering é engenharia de equilíbrio, não uma competição para colocar o maior número possível em uma configuração.


🚧 CAPÍTULO 15 — BACKPRESSURE: ATÉ NAZARICK TEM CAPACIDADE FINITA

Considere:

Entrada:      10.000 mensagens/s
Processamento: 6.000 mensagens/s

Sobram:

4.000 mensagens/s

A cada segundo.

Depois de um minuto, a diferença acumulada é enorme.

Se continuarmos aceitando indefinidamente:

fila aumenta
      ↓
memória aumenta
      ↓
latência aumenta
      ↓
timeouts aparecem
      ↓
clientes tentam novamente
      ↓
carga aumenta

Estamos alimentando o próprio monstro.

Backpressure é o mecanismo pelo qual uma parte do sistema sinaliza que não consegue absorver trabalho na velocidade em que ele está chegando.

É extremamente importante em sistemas assíncronos e distribuídos.

A fila não é um buraco negro de capacidade infinita.

MQ não conjura storage de outra dimensão.


💣 CAPÍTULO 16 — RETRY STORM: QUANDO A RECUPERAÇÃO VIRA O ATAQUE

Imagine 10.000 clientes chamando um serviço.

Ele começa a apresentar lentidão.

Clientes recebem timeout.

Todos pensam:

Tentar novamente!

O servidor, que já estava sofrendo, recebe outra avalanche.

Fica ainda mais lento.

Mais clientes recebem timeout.

Mais retries.

Temos:

SERVIDOR LENTO
      ↓
   TIMEOUT
      ↓
    RETRY
      ↓
 MAIS CARGA
      ↓
SERVIDOR MAIS LENTO

Um DDoS praticado involuntariamente pelos próprios clientes.

Por isso encontramos técnicas como exponential backoff, jitter, timeouts, circuit breakers e rate limiting.

Não basta perguntar:

"O sistema sabe tentar novamente?"

Precisamos perguntar:

"Quando, quantas vezes e em que ritmo?"


🏦 CAPÍTULO 17 — AINZ ENTRA NO DATACENTER DO BANCO

Agora juntaremos tudo.

Imagine:

Celular
   ↓
Internet
   ↓
API Gateway
   ↓
z/OS Connect
   ↓
CICS
   ↓
COBOL
   ↓
Db2
   ↓
MQ
   ↓
Sistema externo

O usuário reclama:

"Demorou 850 ms!"

Alguém imediatamente declara:

"O mainframe está lento!"

Ainz interrompe.

— Prove.

Medimos:

Internet             80 ms
Gateway              20 ms
z/OS Connect         15 ms
CICS                  30 ms
COBOL CPU              4 ms
Db2                   55 ms
MQ                    40 ms
Sistema externo      580 ms
Retorno               26 ms
---------------------------
TOTAL                850 ms

Temos nosso suspeito principal.

Sistema externo = 580 ms

O COBOL consumiu:

4 ms

Agora surge uma conclusão maravilhosa.

O componente acusado de lentidão pode ser justamente um dos componentes mais rápidos do caminho.

Essa é a diferença entre opinião e observabilidade.


🔭 CAPÍTULO 18 — SMF, RMF E WLM: OS ORÁCULOS DE NAZARICK

O universo mainframe possui uma longa tradição de instrumentação.

Termos modernos como observability, SRE, capacity management e performance engineering possuem parentes muito antigos no datacenter.

O mainframer conhece nomes como:

SMF
RMF
WLM
CICS monitoring
Db2 accounting
MQ statistics

SMF produz registros valiosíssimos sobre atividades do sistema e subsistemas.

RMF permite observar recursos e comportamento do ambiente.

WLM trabalha com workloads, classes de serviço, objetivos e gerenciamento dos recursos conforme prioridades e metas.

CICS possui suas métricas.

Db2 possui informações de accounting e performance.

MQ possui estatísticas e accounting.

A ideia fundamental é:

MEDIR
  ↓
LOCALIZAR
  ↓
ENTENDER
  ↓
FORMULAR HIPÓTESE
  ↓
ALTERAR
  ↓
MEDIR NOVAMENTE

Perceba o último passo.

Medir novamente.

Uma alteração não é uma otimização simplesmente porque parece inteligente.

Você precisa demonstrar o resultado.


🕵️ CAPÍTULO 19 — PASSO A PASSO PARA O PROGRAMADOR COBOL INVESTIGAR LATÊNCIA

Agora nosso Padawan — perdão, aventureiro de Nazarick — recebe seu procedimento.

Primeiro estabeleça o que significa lento. "Está demorando" não é unidade de medida. Descubra o tempo esperado e o observado.

Depois determine o escopo. Uma transação está lenta? Todas? Apenas em determinado horário? Somente alguns clientes? Depois do batch noturno? Durante pico? Após determinado deploy?

Em seguida obtenha métricas de distribuição. Não viva somente da média. Procure mediana, percentis e extremos quando disponíveis.

Depois decomponha o caminho.

Usuário
 ↓
Rede
 ↓
Frontend
 ↓
API
 ↓
Gateway
 ↓
CICS
 ↓
Programa
 ↓
Db2/MQ
 ↓
Dependências

Descubra onde o tempo é consumido.

Depois separe:

EXECUÇÃO

de:

ESPERA

E classifique as esperas.

Podem envolver I/O, locks, filas, rede, conexões, recursos, serviços remotos ou dependências.

Somente então escolha a solução.

Cache se existe trabalho repetitivo evitável.

Async se o usuário não precisa aguardar determinada atividade.

Índice ou revisão SQL se o banco está consumindo o tempo.

Load balancing se filas e saturação justificarem distribuição.

CDN se distância e entrega de conteúdo forem relevantes.

Paralelismo se existirem operações independentes e capacidade para executá-las simultaneamente.

Pooling se criação repetitiva de conexões for significativa.

Sharding somente quando o problema realmente justificar sua enorme complexidade.

Finalmente faça uma alteração controlada e meça novamente.

Isso é engenharia.


🧪 CAPÍTULO 20 — NÃO OTIMIZE NO ESCURO

Existe uma doença antiga entre programadores:

otimização por intuição.

O desenvolvedor olha o código e decide:

"Esse PERFORM parece caro."

Talvez seja.

Mas precisamos medir.

Imagine:

PERFORM VARYING WS-I FROM 1 BY 1
        UNTIL WS-I > 100
    ADD WS-I TO WS-TOTAL
END-PERFORM

Você passa horas tentando economizar microssegundos.

Enquanto isso, logo abaixo:

EXEC CICS LINK
     PROGRAM('PGMREMOT')
     COMMAREA(WS-COMMAREA)
END-EXEC

leva centenas de milissegundos devido ao que acontece além daquela chamada.

Ou existe SQL esperando lock.

Ou MQ aguardando uma dependência.

Ou uma API cruzando continentes.

A regra de Ainz:

Não ataque o monstro antes de descobrir qual monstro está drenando seu HP.


🧠 CAPÍTULO 21 — PERFORMANCE TAMBÉM É ARQUITETURA

Há uma lição ainda maior.

Performance não começa quando alguém reclama.

Decisões arquiteturais determinam grande parte do comportamento futuro.

Se você constrói:

A → B → C → D → E → F → G

e todos são síncronos, cada dependência entra no caminho crítico.

Se algumas operações puderem ser:

A → B → C → RESPONSE
        |
        +→ MQ → D
        +→ MQ → E
        +→ MQ → F

a experiência muda.

Mas você trocou simplicidade síncrona por complexidade assíncrona.

Essa troca precisa ser consciente.

Não existe arquitetura perfeita.

Existem trade-offs.

Performance, consistência, disponibilidade, simplicidade, custo, resiliência e manutenção frequentemente puxam o projeto em direções diferentes.


🥚 EASTER EGG — O INCIDENTE DAS 03:17

Às 03:17, um alerta dispara em Nazarick.

A transação passou de:

p99 = 180 ms

para:

p99 = 4.700 ms

Shalltear quer reiniciar o CICS.

Cocytus quer aumentar CPU.

Albedo culpa o Java.

Demiurge afirma que tudo faz parte do plano de Ainz.

O jovem COBOL olha o SMF.

Depois olha o Db2.

Depois olha MQ.

Finalmente encontra:

Fila crescendo desde 03:16:47
Consumidor externo degradado
Retries aumentando

Ainz declara:

— Exatamente como imaginei.

Por dentro:

"Sasuga... programador COBOL."


☕ CAPÍTULO FINAL — O SISTEMA NÃO ESTÁ LENTO. ALGUMA COISA ESTÁ ESPERANDO.

Voltamos à primeira tela.

RESPONSE TIME : 3.017 s
CPU TIME      : 0.004 s

No começo da aventura, o jovem programador pensava:

"Preciso tornar meu COBOL mais rápido."

Agora ele pergunta:

"Onde estão os outros 3.013 segundos?"

Essa pergunta muda tudo.

Talvez estejam no Db2.

Talvez em I/O.

Talvez esperando lock.

Talvez em uma fila.

Talvez em MQ.

Talvez na rede.

Talvez numa API.

Talvez aguardando uma conexão.

Talvez exista saturação.

Talvez exista retry storm.

Talvez uma arquitetura com quinze serviços tenha transformado uma operação simples numa excursão por quinze datacenters.

E somente depois de encontrar a resposta você escolhe a ferramenta.

CACHE
ASYNC
DB OPTIMIZATION
LOAD BALANCING
CDN
PARALLELISM
PREFETCH
POOLING
BACKPRESSURE
RATE LIMITING
SHARDING

Essa é provavelmente a maior deficiência daqueles infográficos chamados "10 maneiras de deixar qualquer sistema mais rápido".

As técnicas podem estar corretas.

O problema é imaginar que elas possam ser escolhidas antes do diagnóstico.

Um médico não olha para dez remédios e pergunta:

"Qual deles parece mais moderno?"

Primeiro investiga o paciente.

Performance engineering funciona da mesma maneira.

E existe uma conexão particularmente bonita com o universo mainframe.

Durante décadas, sistemas críticos precisaram responder perguntas como:

Quem consumiu CPU?

Quem esperou?

Quanto esperou?

Qual recurso provocou o atraso?

Qual workload deve ter prioridade?

Qual subsistema está saturado?

O problema está na aplicação ou fora dela?

É por isso que conceitos associados hoje a observabilidade, SRE e engenharia de performance soam tão familiares para quem cresceu olhando CICS, Db2, MQ, SMF, RMF e WLM.

As ferramentas evoluíram.

As arquiteturas ficaram distribuídas.

As APIs atravessaram a internet.

Os microsserviços multiplicaram os hops.

Cloud, containers e Kubernetes acrescentaram novas camadas.

Mas a pergunta fundamental continua praticamente a mesma:

ONDE FOI PARAR O TEMPO?

Ainz Ooal Gown levanta-se finalmente de seu trono.

O jovem programador aguarda sua sentença.

— Qual é a primeira regra de performance?

O aprendiz responde:

— Não otimizar antes de medir.

— E a segunda?

— Response time não é CPU time.

— E a terceira?

— Encontrar onde o sistema está esperando.

Ainz faz silêncio.

O programador continua:

— E nunca criar sharding para resolver um SELECT sem índice.

Demiurge sorri.

Albedo se emociona.

Cocytus aprova.

E, em algum lugar perdido de Nazarick, um job termina:

IEF142I BELLACOS STEP01 - STEP WAS EXECUTED
IEF373I STEP/STEP01 /START 20260926.0317
IEF374I STEP/STEP01 /STOP  20260926.0317
IEF375I JOB/BELLACOS/START 20260926.0317
IEF376I JOB/BELLACOS/STOP  20260926.0317

MAXCC=0000

Mas nosso programador já não comemora tão rapidamente.

Ele olha para o relógio.

Depois para CPU.

Depois para I/O.

Depois para as esperas.

Porque finalmente aprendeu:

MAXCC=0000 diz que o job terminou corretamente. Não diz que terminou rápido.

E essa talvez seja a melhor lição deixada pela Grande Tumba da Latência.

Sasuga, Ainz-sama.

☕ Gostou deste café?
Siga o Bellacosa Mainframe e acompanhe os próximos artigos.
SEGUIR O BLOG

Sem comentários:

Enviar um comentário

De Fã para Fã. Conteúdo não oficial produzido como homenagem, comentário, análise ou paródia. Personagens, marcas e obras eventualmente mencionados pertencem aos seus respectivos titulares.
Vagner Renato Bellacosa, IBM Champion e especialista em IBM Mainframe
IBM Z17 SYSTEM ONLINE
Sobre o autor

Vagner Renato Bellacosa

IBM Champion 2026 • Especialista em IBM Mainframe

Vagner Renato Bellacosa trabalha com IBM Mainframe desde 1988 , é IBM Champion e especialista em COBOL, CICS, Db2, z/OS e IBM Z. Compartilha experiências profissionais, conhecimento técnico, história da computação e práticas do universo mainframe para aproximar novas gerações das tecnologias que sustentam empresas, bancos e governos ao redor do mundo.

IBM Champion IBM Z COBOL CICS Db2 z/OS Mainframe desde 1988
GitHub LinkedIn
Inicializando conteúdo...