| Bellacosa Mainframe evoluindo o data division trabalhando com o working-storage vrs local-storage |
☕ Um Café no Bellacosa Mainframe
Working-Storage vs Local-Storage em COBOL: Muito Além do Static e Dynamic — A Engenharia Invisível que Mantém Milhões de Transações Funcionando
"Todo programador COBOL aprende cedo que existe a Working-Storage Section e a Local-Storage Section. Quase todos decoram que uma é 'estática' e a outra é 'dinâmica'. Poucos entendem que essa diferença define como um programa se comporta quando milhares de pessoas o executam simultaneamente em um IBM Z."
Existe um momento curioso na vida de todo desenvolvedor COBOL.
Logo nas primeiras aulas aparece alguém dizendo:
"Working-Storage é memória estática."
Logo depois vem outra frase:
"Local-Storage é memória dinâmica."
O aluno anota.
Decora.
Passa na prova.
Continua programando.
Anos depois ainda acredita que toda a história termina aí.
Mas não termina.
Na verdade, essa é apenas a primeira página de um assunto que influencia desempenho, escalabilidade, consumo de memória, concorrência, reentrância e até mesmo a disponibilidade dos maiores sistemas bancários do planeta.
Hoje vamos tomar um café e conversar sobre algo que acontece silenciosamente dentro do IBM Z toda vez que um programa COBOL começa a executar.
Vamos falar sobre memória.
Mas não qualquer memória.
Vamos falar da memória que ninguém vê.
Aquela que decide se um programa será elegante ou problemático.
Aquela que pode suportar dez usuários... ou cem mil.
O que realmente acontece quando um programa COBOL inicia?
Imagine que um programa COBOL seja um restaurante.
O código-fonte representa o projeto arquitetônico.
As instruções são as receitas.
Os parágrafos são os cozinheiros.
Mas falta algo essencial.
Onde ficam os ingredientes?
Eles precisam ser armazenados em algum lugar.
É exatamente esse o papel das áreas de dados.
Quando o programa é carregado, o sistema operacional reserva espaços de memória para armazenar todas as variáveis declaradas.
Essas áreas são cuidadosamente organizadas.
Algumas existirão durante toda a vida do programa.
Outras nascerão e morrerão constantemente.
É justamente aqui que entram a Working-Storage e a Local-Storage.
Working-Storage: a grande despensa do restaurante
Imagine a despensa principal de um restaurante.
Ela foi montada antes da abertura.
Os armários já estão organizados.
Os ingredientes estão separados.
Os utensílios permanecem sempre nos mesmos lugares.
Nada disso precisa ser montado toda vez que um cliente chega.
É exatamente essa a filosofia da Working-Storage.
WORKING-STORAGE SECTION.
01 WS-CLIENTE.
05 WS-NOME PIC X(40).
05 WS-CONTA PIC 9(10).
01 WS-SALDO PIC S9(11)V99 COMP-3.
01 WS-CONTADOR PIC 9(6).
Quando o programa é carregado pelo z/OS, essa área recebe memória.
A partir desse instante ela permanece disponível.
Não importa quantos PERFORM sejam executados.
Não importa quantos IF existam.
Não importa quantas SECTIONS sejam chamadas.
As variáveis continuam existindo.
O endereço de memória continua sendo o mesmo.
Isso torna o acesso extremamente rápido.
O verdadeiro significado de "estático"
Muitos iniciantes imaginam que "estático" significa "imutável".
Não.
Static não significa que o valor nunca muda.
Significa que o espaço de memória permanece o mesmo.
Observe:
MOVE 100 TO WS-TOTAL.
Depois:
ADD 50 TO WS-TOTAL.
Depois:
SUBTRACT 20 FROM WS-TOTAL.
O conteúdo mudou diversas vezes.
Mas o endereço da variável permaneceu exatamente igual.
É como uma gaveta.
Você pode trocar o que está dentro dela.
Mas continua sendo a mesma gaveta.
O custo invisível da criação de memória
Toda vez que um sistema precisa criar memória, ele realiza diversas operações internas.
Ele precisa:
localizar espaço livre;
reservar esse espaço;
inicializar a região;
atualizar tabelas internas;
controlar proteção;
posteriormente liberar aquela memória.
Tudo isso consome CPU.
A Working-Storage evita esse trabalho.
Ela nasce uma vez.
E permanece viva.
Por isso é extremamente eficiente para dados permanentes durante a execução.
Onde ela é usada?
Praticamente em todos os programas Batch.
Imagine um processamento de folha de pagamento.
Durante horas o programa percorre milhões de registros.
Ele precisa manter:
total de salários;
quantidade de funcionários;
número do lote;
estatísticas;
indicadores;
buffers de leitura;
tabelas carregadas em memória.
Nenhum desses dados precisa ser recriado continuamente.
Logo, Working-Storage é perfeita.
Agora imagine outro cenário...
Você desenvolveu um programa chamado CALCULA-IMPOSTO.
Ele é chamado por:
Internet Banking;
Aplicativo Mobile;
Caixa eletrônico;
Central de Atendimento;
PIX;
TED;
DOC;
Sistema interno do banco.
Milhares de chamadas por segundo.
Todos executando exatamente o mesmo programa.
Agora surge uma pergunta interessante.
Como impedir que um cliente altere os dados do outro?
Bem-vindo ao mundo da Local-Storage
É aqui que entra a Local-Storage Section.
LOCAL-STORAGE SECTION.
01 LS-TOTAL-IMPOSTO PIC S9(9)V99.
Essa variável possui um comportamento completamente diferente.
Ela não existe durante toda a vida do programa.
Ela nasce.
É utilizada.
E desaparece.
Cada nova ativação do programa recebe uma nova cópia.
Não existe compartilhamento.
É como um bloco de anotações entregue individualmente para cada cliente que entra no restaurante.
Quando o cliente vai embora...
O bloco é descartado.
O próximo recebe outro completamente limpo.
A diferença parece pequena...
...mas muda tudo.
Imagine três clientes acessando simultaneamente um sistema bancário.
Cliente A:
Saldo:
R$ 5.000
Cliente B:
Saldo:
R$ 18.000
Cliente C:
Saldo:
R$ 730
Se todos utilizassem exatamente a mesma variável para armazenar o saldo temporário...
Teríamos um desastre.
Enquanto um cliente calcula juros...
Outro altera o saldo.
Enquanto outro faz um PIX...
A variável já contém informações diferentes.
Resultado?
Corrupção de memória.
Valores inconsistentes.
Falhas imprevisíveis.
Esse tipo de problema recebe até um nome em computação:
Race Condition.
O IBM Z foi construído para evitar exatamente isso
O mainframe nasceu para executar milhares de tarefas simultaneamente.
Ele não foi criado pensando em um único usuário.
Foi projetado para atender cidades inteiras.
Bancos.
Companhias aéreas.
Seguradoras.
Governos.
Empresas de cartão.
Operadoras de saúde.
Enquanto você lê este artigo, existem programas COBOL sendo executados milhares de vezes por segundo.
Muitas vezes o mesmo módulo está atendendo centenas de usuários ao mesmo tempo.
Como isso é possível?
Porque o código é compartilhado.
Mas os dados não.
Código compartilhado
Imagine um livro.
Mil pessoas podem ler exatamente o mesmo livro.
O livro não muda.
Agora imagine que todas escrevessem anotações na mesma página.
Seria um caos.
É exatamente essa diferença.
O código pode ser compartilhado.
Os dados precisam ser privados.
Reentrância: um conceito muito maior que Local-Storage
Aqui chegamos a uma palavra que todo programador COBOL deveria conhecer.
Reentrant.
Um programa reentrante pode ser executado simultaneamente por inúmeras tarefas.
Existe apenas uma cópia do código.
Mas cada execução possui sua própria área de dados.
Isso reduz consumo de memória.
Melhora desempenho.
Aumenta escalabilidade.
Permite milhares de transações concorrentes.
Em ambientes CICS, isso é praticamente obrigatório.
O compilador RENT
Quem já compilou programas Enterprise COBOL provavelmente encontrou a opção:
RENT
Muitos imaginam que ela apenas altera um parâmetro de compilação.
Na verdade, ela muda toda a filosofia de utilização da memória.
O compilador passa a gerar código preparado para múltiplas execuções concorrentes.
Isso exige disciplina.
Variáveis compartilhadas precisam ser evitadas.
Dados específicos da execução devem permanecer em áreas privadas.
É justamente aqui que Local-Storage ganha enorme importância.
Batch e CICS não vivem exatamente no mesmo mundo
Essa é outra confusão comum.
No processamento Batch, normalmente existe apenas uma instância daquele programa executando.
Logo, Working-Storage atende perfeitamente.
Já no CICS...
Milhares de usuários podem chamar o mesmo programa.
Ao mesmo tempo.
Nesse ambiente, utilizar inadequadamente áreas compartilhadas pode gerar problemas extremamente difíceis de reproduzir.
Aquele famoso erro que "acontece uma vez por semana" muitas vezes nasce justamente da utilização incorreta da memória.
Um exemplo simples
Imagine este contador.
WORKING-STORAGE SECTION.
01 WS-CONTADOR PIC 9(5).
Cada chamada faz:
ADD 1 TO WS-CONTADOR.
Em Batch isso pode funcionar exatamente como esperado.
Agora imagine centenas de transações simultâneas.
Quem garante qual usuário alterou o contador primeiro?
Quem garante que nenhuma atualização será perdida?
É exatamente por isso que programas transacionais precisam ser cuidadosamente projetados.
Local-Storage também tem custo
É tentador imaginar que basta substituir tudo por Local-Storage.
Não é tão simples.
Toda criação de memória possui custo.
A cada ativação do programa, o sistema precisa:
reservar memória;
inicializar valores;
preparar a área;
liberar recursos posteriormente.
Esse trabalho é pequeno.
Mas quando falamos em milhões de chamadas por dia...
Pequenos custos tornam-se grandes números.
É por isso que engenharia de software nunca trabalha com respostas absolutas.
Tudo depende do contexto.
E o VALUE?
Outro detalhe frequentemente ignorado.
Observe:
01 WS-TOTAL PIC 9 VALUE 5.
O valor inicial é definido quando a área é inicializada.
Depois disso, o programa pode alterá-lo quantas vezes desejar.
Já na Local-Storage:
01 LS-TOTAL PIC 9 VALUE 5.
Cada nova ativação recebe novamente o valor cinco.
Parece um detalhe.
Mas em subprogramas reutilizados milhares de vezes isso muda completamente o comportamento da aplicação.
CALL e Subprogramas
Imagine um módulo de cálculo.
CALCULA-JUROS
Ele é chamado por dezenas de sistemas.
Se utilizar apenas Working-Storage para dados temporários, o comportamento dependerá da forma como o ambiente gerencia essa área e do modelo de execução adotado.
Se utilizar Local-Storage para as variáveis temporárias, cada ativação começa com uma área própria e limpa, reduzindo o risco de interferência entre execuções.
Por isso, muitos subprogramas modernos utilizam Local-Storage para cálculos intermediários e Working-Storage apenas para estruturas que realmente precisam existir durante toda a ativação do programa.
A analogia do hotel
Imagine um hotel.
A Working-Storage é o prédio.
Sempre está lá.
As paredes continuam no mesmo lugar.
Os corredores não mudam.
Agora pense nos quartos.
Cada hóspede recebe um quarto limpo.
Quando vai embora...
Outro hóspede ocupa o mesmo espaço.
Não leva a bagagem do anterior.
A Local-Storage funciona exatamente assim.
Cada execução recebe seu próprio "quarto".
E quando falamos de desempenho?
Uma das maiores virtudes do IBM Z sempre foi a eficiência.
O sistema operacional conhece profundamente como seus programas utilizam memória.
O compilador Enterprise COBOL também foi otimizado durante décadas para produzir código extremamente eficiente.
Por isso, a escolha entre Working-Storage e Local-Storage não deve ser feita por hábito, mas por necessidade.
Variáveis permanentes?
Working-Storage.
Dados temporários exclusivos de uma ativação?
Local-Storage.
Subprogramas reentrantes?
Planejamento cuidadoso das áreas de dados.
O erro mais comum dos iniciantes
Existe uma pergunta que aparece frequentemente em cursos.
"Professor, então devo usar Local-Storage em tudo?"
A resposta é simples.
Não.
Assim como não existe um único tipo de dataset para todas as situações, não existe uma única área de memória adequada para todos os cenários.
A escolha depende do ambiente de execução, do tipo de aplicação, da necessidade de concorrência, do ciclo de vida dos dados e dos requisitos de desempenho.
Conhecer essas diferenças é o que separa quem apenas escreve código de quem projeta soluções robustas para ambientes corporativos.
O verdadeiro aprendizado
Aprender COBOL não é decorar sintaxes.
Não é memorizar comandos.
Não é saber onde fica a vírgula do PIC.
Programar COBOL é entender como o sistema operacional conversa com o compilador.
Como o compilador organiza a memória.
Como o programa compartilha recursos.
Como milhares de usuários podem executar exatamente o mesmo módulo sem que um interfira na execução do outro.
Quando compreendemos a diferença entre Working-Storage e Local-Storage, deixamos de enxergar apenas duas seções da Data Division.
Passamos a enxergar a arquitetura invisível que sustenta aplicações responsáveis por movimentar trilhões de dólares diariamente.
Na próxima vez que declarar uma variável em seu programa COBOL, lembre-se: você não está apenas escolhendo onde armazenar um número ou um texto. Está tomando uma decisão de arquitetura que pode impactar desempenho, escalabilidade, reentrância e confiabilidade de todo o sistema.
E é justamente esse tipo de detalhe, aparentemente simples, que transforma um programador COBOL em um verdadeiro engenheiro de software para IBM Z.
Porque, no fim das contas, a excelência no mainframe não nasce das grandes decisões. Ela é construída por milhares de pequenas escolhas corretas, feitas todos os dias, muitas delas invisíveis para quem apenas olha o código.
Sem comentários:
Enviar um comentário