Primeiro aniversário do “Tudo em AdvPL”

Em 21 de Novembro de 2015, o Blog “Tudo em AdvPL” completou um ano de existência, contados do primeiro “post”. Eu sou apaixonado por tecnologia e programação desde que eu entendi o conceito da palavra (e do “Byte”), e eu gostaria de compartilhar isso com o mundo, onde existem mais pessoas que, em diferentes graus e intensidades, também têm afinidade com este mundo mágico da Tecnologia da Informação. Depois de acompanhar de perto a evolução da Internet nos últimos 20 anos, decidi que estava mais que na hora de arregaçar as mangas e fazer algo a respeito.

Hoje só tenho a agradecer a vocês, leitores e visitantes do “Tudo em AdvPL”, que buscam por mais informações e conhecimentos, que comentam um post com elogios, dúvidas ou sugestões de abordagem de outros assuntos, e que compartilham com seus amigos nas redes sociais o conteúdo aqui disponível 😉

Mais uma vez, obrigado pela audiência, e desejo a todos TERABYTES de SUCESSO 😀

“Toda a grande caminhada começa com um pequeno passo” — BUDA

filme-06-020

“Viagem ao Oiapoque (2006), BR-156” – foto por Júlio Wittwer.

Anúncios

Acelerando o AdvPL – Lendo arquivos TXT (ERRATA)

Pessoal,

No post “Acelerando o AdvPL – Lendo arquivos TXT”, foi corrigido um erro que causava um mau comportamento da rotina,  fazendo a leitura de linhas “inconsistentes”. Na chamada da função RAT(), o primeiro parâmetro deve ser a string a ser procurada, e o segundo parâmetro deve ser a string onde a primeira deve ser procurada. A passagem de parâmetros estava ao contrário, fazendo com que a quebra de linha no final de um bloco lido fosse identificada erroneamente, fazendo a rotina retornar linhas com quebras inexistentes. O código-fonte do post original já foi corrigido, segue abaixo o detalhe da correção.

Antes da correção (fonte incorreto)

// Determina a ultima quebra
nRPos := Rat(cBuffer,::cFSep)

Após a correção, o código deve ficar assim:

// Determina a ultima quebra
nRPos := Rat(::cFSep,cBuffer)

Estava trabalhando em um próximo post sobre escalabilidade e performance, e aproveitei a classe para ilustrar um processamento. Quando executei a rotina, percebi que as quebras de linha estavam inconsistentes, pois foram retornadas mais linhas do que eu havia inserido.

Introdução a Informática – Parte 03

Introdução

No post anterior, vimos as etapas que acontecem quando ligamos o equipamento, e de bandeja alguma coisa bem ‘por cima’ sobre dados e programas. Agora vamos descer um pouco mais dentro dos Bytes, abordar o conceito de Dados e Programas, e aproveitar o gancho para ver ‘por cima’ o que é um sistema de arquivos, mais especificamente o sistema de arquivos em árvore, usado pelo MS-DOS e pelo Windows.

Lembrando do Byte

“Note que um byte nada tem de especial, é apenas um número binário de oito algarismos. Sua importância na informática deriva apenas do fato do código ASCII haver adotado números de oito bits, além de razões meramente construtivas ou operacionais. Por exemplo: os códigos enviados a impressoras para controlar a impressão têm oito bits, os valores trocados via Modem entre computadores também, assim como diversas outras operações elementares de intercâmbio de informações. Além disso, memórias costumam ser organizadas de tal forma que as operações de leitura e escrita são feitas com quantidades de um byte ou de um múltiplo de bytes (oito, dezesseis, trinta e dois, sessenta e quatro ou cento e vinte e oito bits – o que corresponde a um, dois, quatro, oito e dezesseis bytes, respectivamente).” (Wikipedia, BYTE)

Logo, o que está gravado em qualquer arquivo armazenado no disco de um computador ? R: Bytes. E na memória RAM ? R: Bytes. E num pen-drive ? Mais Bytes. Legal, tudo são Bytes, ou sequências numéricas de octetos. Mas, no computador eu tenho arquivos de texto, imagens, áudio, vídeo … tudo são bytes ? R: SIM.

Existem editores de texto e ferramentas de disco que permitem abrir um arquivo qualquer, em qualquer formato, e ler todos os bytes do arquivo, e mostrar na tela o conteúdo do arquivo representados em bytes. Normalmente estes programas mostram o valor de cada byte em uma base numérica conhecida por HEXADECIMAL. No sistema decimal, usamos 10 algarismos diferentes para representar um número, de “0” a “9”. No sistema binário, usamos apenas 2: “0” e “1”. No sistema Hexadecimal, usamos 16 ( HEXA + DECIMAL = 6 + 10 ), usando os algarismos de “0” a “9” e as letras de “A” a “F”.

Partindo da base binária, precisamos de uma sequência de 4 BITS para representar 16 valores diferentes, certo ? Usando Hexadecimal, com apenas um símbolo, de “0” a “F”, conseguimos representar 16 valores diferentes. Vejamos abaixo como podemos representar os 256 valores diferentes de um Byte usando cada um dos sistemas ( DEC = Decimal, HEX = Hexadecimal, BIN = Binário ):

DEC HEX BIN DEC HEX BIN DEC HEX BIN DEC HEX BIN
------------------------------------------------------------------------------
000 00 00000000 064 40 01000000 128 80 00000010 192 C0 11000000
001 01 00000001 065 41 01000001 129 81 00000011 193 C1 11000001
002 02 00000010 066 42 01000010 130 82 00000100 194 C2 11000010
003 03 00000011 067 43 01000011 131 83 00000101 195 C3 11000011
004 04 00000100 068 44 01000100 132 84 00000110 196 C4 11000100
005 05 00000101 069 45 01000101 133 85 00000111 197 C5 11000101
006 06 00000110 070 46 01000110 134 86 00001000 198 C6 11000110
007 07 00000111 071 47 01000111 135 87 00001001 199 C7 11000111
008 08 00001000 072 48 01001000 136 88 00001010 200 C8 11001000
009 09 00001001 073 49 01001001 137 89 00001011 201 C9 11001001
010 0A 00001010 074 4A 01001010 138 8A 00001100 202 CA 11001010
011 0B 00001011 075 4B 01001011 139 8B 00001101 203 CB 11001011
012 0C 00001100 076 4C 01001100 140 8C 00001110 204 CC 11001100
013 0D 00001101 077 4D 01001101 141 8D 00001111 205 CD 11001101
014 0E 00001110 078 4E 01001110 142 8E 00010000 206 CE 11001110
015 0F 00001111 079 4F 01001111 143 8F 00010001 207 CF 11001111
016 10 00010000 080 50 01010000 144 90 00010010 208 D0 11010000
017 11 00010001 081 51 01010001 145 91 00010011 209 D1 11010001
018 12 00010010 082 52 01010010 146 92 00010100 210 D2 11010010
019 13 00010011 083 53 01010011 147 93 00010101 211 D3 11010011
020 14 00010100 084 54 01010100 148 94 00010110 212 D4 11010100
021 15 00010101 085 55 01010101 149 95 00010111 213 D5 11010101
022 16 00010110 086 56 01010110 150 96 00011000 214 D6 11010110
023 17 00010111 087 57 01010111 151 97 00011001 215 D7 11010111
024 18 00011000 088 58 01011000 152 98 00011010 216 D8 11011000
025 19 00011001 089 59 01011001 153 99 00011011 217 D9 11011001
026 1A 00011010 090 5A 01011010 154 9A 00011100 218 DA 11011010
027 1B 00011011 091 5B 01011011 155 9B 00011101 219 DB 11011011
028 1C 00011100 092 5C 01011100 156 9C 00011110 220 DC 11011100
029 1D 00011101 093 5D 01011101 157 9D 00011111 221 DD 11011101
030 1E 00011110 094 5E 01011110 158 9E 00100000 222 DE 11011110
031 1F 00011111 095 5F 01011111 159 9F 00100001 223 DF 11011111
032 20 00100000 096 60 01100000 160 A0 00100010 224 E0 11100000
033 21 00100001 097 61 01100001 161 A1 00100011 225 E1 11100001
034 22 00100010 098 62 01100010 162 A2 00100100 226 E2 11100010
035 23 00100011 099 63 01100011 163 A3 00100101 227 E3 11100011
036 24 00100100 100 64 01100100 164 A4 00100110 228 E4 11100100
037 25 00100101 101 65 01100101 165 A5 00100111 229 E5 11100101
038 26 00100110 102 66 01100110 166 A6 00101000 230 E6 11100110
039 27 00100111 103 67 01100111 167 A7 00101001 231 E7 11100111
040 28 00101000 104 68 01101000 168 A8 00101010 232 E8 11101000
041 29 00101001 105 69 01101001 169 A9 00101011 233 E9 11101001
042 2A 00101010 106 6A 01101010 170 AA 00101100 234 EA 11101010
043 2B 00101011 107 6B 01101011 171 AB 00101101 235 EB 11101011
044 2C 00101100 108 6C 01101100 172 AC 00101110 236 EC 11101100
045 2D 00101101 109 6D 01101101 173 AD 00101111 237 ED 11101101
046 2E 00101110 110 6E 01101110 174 AE 00110000 238 EE 11101110
047 2F 00101111 111 6F 01101111 175 AF 00110001 239 EF 11101111
048 30 00110000 112 70 01110000 176 B0 00110010 240 F0 11110000
049 31 00110001 113 71 01110001 177 B1 00110011 241 F1 11110001
050 32 00110010 114 72 01110010 178 B2 00110100 242 F2 11110010
051 33 00110011 115 73 01110011 179 B3 00110101 243 F3 11110011
052 34 00110100 116 74 01110100 180 B4 00110110 244 F4 11110100
053 35 00110101 117 75 01110101 181 B5 00110111 245 F5 11110101
054 36 00110110 118 76 01110110 182 B6 00111000 246 F6 11110110
055 37 00110111 119 77 01110111 183 B7 00111001 247 F7 11110111
056 38 00111000 120 78 01111000 184 B8 00111010 248 F8 11111000
057 39 00111001 121 79 01111001 185 B9 00111011 249 F9 11111001
058 3A 00111010 122 7A 01111010 186 BA 00111100 250 FA 11111010
059 3B 00111011 123 7B 01111011 187 BB 00111101 251 FB 11111011
060 3C 00111100 124 7C 01111100 188 BC 00111110 252 FC 11111100
061 3D 00111101 125 7D 01111101 189 BD 00111111 253 FD 11111101
062 3E 00111110 126 7E 01111110 190 BE 01000000 254 FE 11111110
063 3F 00111111 127 7F 01111111 191 BF 01000001 255 FF 11111111
------------------------------------------------------------------------------

TABELA ASCII

Mas, se dentro de um arquivo qualquer, eu tenho apenas Bytes, como é que eu vou trocar informações ? No final, tudo são números, certo ? R: Sim. Na prática sim. O que nós podemos fazer é dar significado aos números, e definir uma forma de interpretação diferente para os números. O padrão mais conhecido na informática para representação e trocas de informações baseadas em TEXTO para computadores é a famosa TABELA ASCII.

“ASCII (do inglês American Standard Code for Information Interchange; “Código Padrão Americano para o Intercâmbio de Informação“) é um código binário (cadeias de bits: 0s e 1s) que codifica um conjunto de 128 sinais: 95 sinais gráficos (letras do alfabeto latino, sinais de pontuação e sinais matemáticos) e 33 sinais de controle. […] A codificação ASCII é usada para representar textos em computadores, equipamentos de comunicação, entre outros dispositivos que trabalham com texto. Desenvolvida a partir de 1960, grande parte das codificações de caracteres modernas a herdaram como base.” ( Wikipedia, ASCII)

Não vou replicar a tabela ASCII dentro deste post, dêem uma olhada nela no link da Wikipedia “https://pt.wikipedia.org/wiki/ASCII“. Quando abrimos um arquivo que contém apenas TEXTO (normalmente identificados pela extensão “.txt”), quando encontramos um byte com valor decimal “32”, ele significa um espaço em branco, “65” representa a letra “A” (“a” maiúscula do alfabeto), e uma sequência de bytes “13” e “10” representa uma quebra de linha.

Arquivos e Extensões

Um arquivo nada mais é do que uma sequência finita/limitada de Bytes. Qualquer programa é capaz de abrir um arquivo e ler seus bytes, mas para dar significado a esta informação, é necessário saber o que estes bytes representam. Quando o sistema de arquivos do MS-DOS foi concebido, foi definido que um “arquivo” possui um nome, que o diferencia dos demais, e uma extensão, normalmente separada do nome por um “.” ponto decimal, onde a extensão indica o tipo do conteúdo do arquivo.

Vejam abaixo algumas extensões e seus usos mais comuns, para os ambientes MS-DOS e Windows:

  • .INI Arquivo texto de configuração ou inicialização de algum aplicativo ou sistema.
  • .BAT Arquivo texto que contém uma sequencia de comandos do sistema operacional.
  • .EXE Arquivo binário que contém os códigos de um programa que pode ser executado pelo sistema operacional.
  • .JPG Arquivo de imagem no formato JPEG (Joint Photographic Experts Group).
  • .BMP Arquivo de imagem no fotmato BITMAP.
  • .PNG Arquivo de imagem no formato Portable Network Grafics.
  • .TXT Arquivo texto de uso geral.
  • .DLL Arquivo binário de link dinâmico, contém funções que podem ser carregadas e usadas por um ou mais programas.
  • .DOC Documento do MS-Word ou outro editor de textos.
  • .XLS Arquivo de Planilha Eletrônica do MS-Excel.
  • .PPT Arquivo de apresentação do MS-PowerPoint.
  • .ZIP Arquivo compactado no padrão ZIP, armazena um ou mais arquivos.
  • .RAR Arquivo compactado no padrão proprietário RAR, criado pelo russo Eugene Roshal (RAR = Roshal ARquive).
  • .XML Arquivo texto que contém dados estruturados usando XML (eXtended Markup Language).
  • .XSD Arquivo texto que contém uma regra de validação ou modelo de troca de dados em XML.
  • .DBF Arquivo de dados, normalmente nos formatos DBASE III e posteriores.
  • .CDX Arquivo de índice de dados, normalmente relacionado a dados em arquivo DBF.
  • .DTC Arquivo de dados no formato c-Tree, usados no AdvPL

Para mais extensões e seus usos mais comuns, consulte “https://pt.wikipedia.org/wiki/Extens%C3%B5es_de_ficheiros“.

Sistema de Arquivos e Diretórios (ou Pastas) no Windows

O sistema de arquivos do Windows herdou a estrutura organizacional e princípios do sistema de arquivos do MS-DOS. Cada unidade de disco instalada na máquina recebe uma letra maiúscula do alfabeto como identificador de unidade, seguido do símbolo “:” (dois pontos). As duas primeiras unidades de disco do computador, antes de existir disco rígido, eram as unidades “A” e “B”. Por isso que, até hoje, quando você abre o Prompt de Comando do sistema operacional no Windows, ou o Windows Explorer, a sua unidade de disco rígido é mostrada como “C:”, e as demais partições de disco e outras unidades (CD-ROM, Pen-Drive,etc) seguem em sequência.

A estrutura de arquivos do Windows é baseada em pastas — ou diretórios, como uma árvore. O primeiro diretório da árvore, ou “raiz”, e representado pela barra inversa “\”. A partir de qualquer diretório, você pode ter um ou mais arquivos, e um ou mais diretórios. Vamos entender que um diretório é um espaço nomeado dentro da estrutura que permite você guardar mais arquivos e outros diretórios. Dentro de qualquer pasta, você não pode ter mais de um arquivo ou pasta com o mesmo nome e extensão. Porém você pode ter arquivos com mesmo nome e extensão em pastas diferentes.

O Windows criou uma padronização, que apresentou pequenas mudanças ao longo das últimas 7 ou 8 versões, mas a base é a mesma. A partir da pasta Raiz da unidade de disco rígido (C:\) existe uma pasta chamada “Arquivos de Programas”, onde dentro dela existem pastas para as aplicações e programas instalados no equipamento, uma pasta “Usuários”, para registrar as informações de perfil e dados de aplicativos de cada usuário do equipamento, e a pasta “Windows”, que armazena um enorme grupo de outras pastas, que contém todos os programas, extensões, drivers e demais arquivos do Sistema Operacional.

Cada arquivo de cada pasta do computador pode ser endereçada ou identificada por um identificador de caminho completo (Full Path), composto pela unidade de disco, estrutura de pastas, e o nome do arquivo. Por exemplo, o arquivo nomeado “mstsc.exe” (Remote Desktop Connection Client), que fica na pasta “System32”, que fica na pasta “Windows” a partir do Drive “C:”, pode ser endereçado como “c:\Windows\System32\mstsc.exe”.

O sistema de arquivos de forma geral permite bem mais recursos e operações, e outras formas de endereçamento determinadas por cada sistema operacional. No Linux, por exemplo, o sistema de arquivos foi herdado dos sistema Unix, onde qualquer dispositivo pode ser endereçado como um arquivo. Não há “letras” de unidade de disco, existem “devices” nomeados, utilizando prefixos específicos para acessar cada tipo de dispositivo, e outros recursos como links dinâmicos para arquivos e pastas, que recentemente também foram implementados no Windows.

Dentro do arquivo

Mesmo que todos os arquivos do disco contenham “Bytes” dentro, arquivos que contenham por exemplo uma imagem ou fotografia, possuem uma regra de armazenamento e interpretação destes bytes. Por exemplo, vamos pegar um formato de imagem mais “antigo”, como o BITMAP (Ou Mapa de Bits), usado no Windows e no (extinto) OS\2.

Na Wikipedia, acesse o link “BMP file format” (https://en.wikipedia.org/wiki/BMP_file_format), veja a seção “File Structure“. Nela é descrito como é o formato de armazenamento interno de uma imagem em um arquivo BMP. O arquivo começa a ser lido do primeiro byte, e existem sequências de bytes de tamanho fixo que indicam informações de como os demais dados estão dispostos, e a partir de um determinado ponto, os blocos de bytes possuem tamanhos variáveis, de acordo com as definições anteriormente especificadas no arquivo. Um arquivo de dados em formato DBF possui uma estrutura similar, onde no início do arquivo os primeiros blocos de bytes identificam quais as informações que estão armazenadas no arquivo.

Nível de complexidade de operações com arquivo

Agora, imagine o quão complexo seria se você tivesse que saber como as informações estão dispostas dentro do arquivo para poder acessá-las? Sim, daria um valente trabalho…. cada arquivo possui uma estrutura interna, e um erro ao ler ou gravar um dado pode corromper a informação no arquivo.

PAra tornar este processo mais fácil, as linguagens de programação que trabalham nativamente acesso a dados oferecem mecanismos de mais “alto nivel”, onde através de funções ou classes, você aciona operações como “ler um registro”, “posicionar em um registro”, “inserir um novo registro”, “alterar os dados de um registro”. Outra abordagem muito utilizada é usar um segundo software, um SGBD (Sistema Gerenciador de Banco de Dados), usando SQL (Structured Query Language), através das quais você monta sentenças praticamente “literais” e solicita ao SGDB a operação desejada, como “SELECT * FROM SA1010 WHERE A1_ATIVO = ‘S’ ORDER BY A1_NREDUZ” (Selecione todos os registros da tabela SA1010 onde o campo (coluna) A1_ATIVO seja igual a letra ‘S’ maiúscula, com o resultado ordenado pelo campo A1_NREDUZ).

Se você precisa trabalhar com um tipo de arquivo que contém imagens, e quer aplicar na imagem um efeito, como mudança de brilho ou cor, você pode escrever uma API sua, abrir o arquivo em modo ‘binário’ (lendo diretamente seu conteúdo em bytes para a memória), entender como aquele mapa de bytes representa a imagem e suas cores, e aplicar o efeito desejado recalculando as definições de cores. Ou, você pode usar um componente pronto, uma biblioteca de funções fornecida com a linguagem ou uma biblioteca de terceiros (existem bibliotecas pagas e gratuitas, com código aberto (Open Source) e código fechado, para diversas linguagens de programação. Naturalmente, vai ser bem mais fácil e rápido usar uma biblioteca pronta. Basta você pesquisar se a escolha em foco atende todas as suas necessidades e não tem alguma restrição que inviabilize seu uso no cenário onde a mesma será aplicada.

Conclusão

A introdução está ficando “longa”, mas uma vez assimilada esta base comum de conhecimento, ela serve para tudo o que foi construído sobre ela, apenas existindo algumas características e comportamentos diferenciados para algumas plataformas ou sistemas, o resto é “farinha do mesmo saco”. Quem gosta de TI, Análise de Sistemas, Engenharia de Software, Programação e ciências correlatas, precisa ter sede e vontade de aprender, e de se manter atualizado, sempre. Mesmo após tornar-se um especialista, é preciso estar de olhos e ouvidos abertos para a evolução constante em torno da área como um todo.

Novamente, agradeço a todos pela audiência, e desejo a vocês TERABYTES de sucesso 😉

Até o próximo post, pessoal 😀

Referências

BYTE. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=Byte&oldid=43771720>. Acesso em: 2 nov. 2015.

ASCII. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=ASCII&oldid=43771464>. Acesso em: 2 nov. 2015.

Extended ASCII. (2015, April 1). In Wikipedia, The Free Encyclopedia. Retrieved 03:19, November 2, 2015, from https://en.wikipedia.org/w/index.php?title=Extended_ASCII&oldid=654535698

RAR (file format). (2015, October 30). In Wikipedia, The Free Encyclopedia. Retrieved 19:19, November 14, 2015, from https://en.wikipedia.org/w/index.php?title=RAR_(file_format)&oldid=688294797

General overview of the Linux file system. In The Linux Documentation Project. Retrieved 17:27, November 14, 2015, from http://www.tldp.org/LDP/intro-linux/html/sect_03_01.html

Escalabilidade e Performance – Parelelismo – Parte 01

Introdução

Em posts anteriores sobre escalabilidade e desempenho, foram frisados vários pontos e técnicas que devem ser levadas em conta no momento de desenvolver uma aplicação partindo das premissas de escalabilidade horizontal e desempenho. Agora vamos trazer isso para um contexto real dentro do AdvPL, explorando uma análise de um cenário muito comum: Processamento de grandes quantidades de dados.

Cenário proposto

Imagine um cenário onde você precisa realizar um processamento de um arquivo TXT (ou CSV), que pode ter muitos MB … O ponto importante é que você pode receber vários arquivos em um curto espaço de tempo, e estes arquivos precisam ser processados e alimentar tabelas do sistema da forma mais rápida possível. Nesta abordagem, vamos abordar a análise de caso e os pontos importantes a considerar.

Fase 01 – Determinar origem dos arquivos

A primeira coisa a pensar é onde estarão estes arquivos. Para eles serem processados mais rapidamente, eles precisam estar pelo menos em uma pasta no RootPath do ambiente. Se estes arquivos vêm de fora do sistema, e você tem que pegá-los em algum lugar fora da sua rede, a melhor alternativa de tráfego é um FTP. O FTP é um protocolo criado especificamente para transferência de arquivos. Nada impede de você usar um webservice para transferir o arquivo em pedaços, mas isto vai trazer um custo (overhead) do HTTP e do XML-SOAP. Se os arquivos estão na própria rede interna, eles podem ser copiados via sistema de arquivos do sistema operacional mesmo, com compartilhamento de rede, numa pasta dentro do RootPath, mas isto vai ser tão rápido quanto FTP, a menos que você utilize um comando mais robusto de cópia, como o ROBOCOPY.

Fase 02 – Determinar pontos de paralelismo

Os arquivos já estão na pasta. Agora, vamos verificar se é possível aplicar algum tipo de paralelismo neste processo. Se os arquivos precisam impreterivelmente obedecer a ordem de chegada, onde cada arquivo precisa ser processado por inteiro antes do próximo arquivo iniciar o processo, uma parte boa do paralelismo já foi perdida … Se os arquivos não tem ordem de processamento, isto é, cada um pode ser processado aleatoriamente, você poderia usar múltiplos JOBS , onde cada um processaria um arquivo inteiro por vez.

Mas nem tudo está perdido … Se dentro de um grande arquivo, as linhas não tiverem ordem de processamento, isto é, cada linha é uma unidade independente de informação, e você não precisa necessariamente ter terminado de processar a linha 999 para processar a linha 1000, … ainda temos uma ótima possibilidade de paralelismo. Vamos assumir que este cenário é possível no nosso exemplo.

Certo, então para aproveitar o máximo possível de paralelismo, eu posso quebrar o arquivo em vários pedaços, e colocar um JOB para processar cada pedaço do arquivo. A pergunta a ser feita agora é: O processamento de uma determinada linha vai exigir algum recurso exclusivo durante o processamento, que também pode ser ou será efetivamente necessário para processar outra linha?

Por exemplo, de cada linha a ser processada do arquivo precisar atualizar um mesmo registro da base de dados, caso duas linhas distintas, sendo processadas pelos jobs precisem fazer um lock de alteração de um mesmo registro de uma tabela no SGBD, fatalmente um dos processos ficará esperando o outro terminar a transação e soltar o lock para conseguir fazer o seu trabalho. Isto implica em uma serialização do processamento neste ponto.

Se as chances disso ocorrer são pequenas durante o processamento, a maioria dos processos somente vai sofrer uma contenção ou serialização em pontos isolados, ainda temos muito a ganhar com processos em paralelo. Agora, se grandes blocos de registros correm o risco de colidir, mesmo assim nem tudo está perdido. No momento de quebrar o arquivo em pedaços, cada pedaço deve agrupar o máximo de linhas que utilizem o mesmo registro, para que um pedaço do arquivo evite concorrer com os demais.

Fase 03 – Quebrando o arquivo

Agora, vamos “quebrar o arquivo”. Vamos pensar bem nesta etapa, afinal existem muitas formas de fazer isso. Precisamos encontrar aquela que melhor se adequa a nossa necessidade, consumindo um mínimo de recursos possível. Se o consumo de um recurso for inevitável, precisamos encontrar a forma mais eficiente de fazê-lo.

Normalmente subimos Jobs ou Threads de processamento na mesma instância do Application Server onde estamos rodando o nosso programa. Porém, subir 2, 3 ou mais threads no mesmo Application Server, quando temos uma máquina com 8 cores HT — como um servidor Intel com processador DUAL-Quadricore HT, é mais interessante subir alguns jobs de processamento em mais de um Application Server. Isto pode exigir alguns controles adicionais, mas os resultados costumam ser muito interessantes.

O lugar onde subir estes Jobs também é importante. Na máquina onde está a unidade de disco com o ambiente do ERP, a leitura de arquivos é feita direto pelo FileSystem do Sistema Operacional, é muito mais rápido do que ler pela rede. Porém, normalmente nesta máquina utilizamos um c-Tree Server, para compartilhar os meta-dados (Dicionários, SXS) do ERP com todos os demais serviços. Colocar muito processamento nesta máquina pode usar muitos recursos dela, e prejudicar os demais processos.

A alternativa mais flexível que evita este risco, é poder subir os Jobs em qualquer um dos serviços de qualquer uma das máquinas disponíveis no parque de máquinas que rodam os Application Server’s. Para isso, fatalmente teremos que usar a rede. Porém, se usarmos ela com sabedoria, podemos minimizar impactos. Vamos partir para esta alternativa.

Fase 04 – Multiplos processos

Existem várias formas de colocarmos JOBS dedicados para realizar um trabalho em vários serviços. Podemos fazer a nossa aplicação iniciar os Jobs de processamento apenas quando necessário, usando por exemplo o RPC do AdvPL, onde no programa principal enumeramos os IPs e Portas dos Application Server’s que serão endereçados para esta atividade, e através de RPC subimos um ou mais Jobs em cada um, usando por exemplo a função StartJob(), ou podemos deixar em cada um dos serviços de processamento um ou mais jobs no ar, inicializados na subida de cada Application Server usando a seção [ONSTART] do appserver.ini, e depois fazendo RPC para cada serviço e distribuir os trabalhos usando IPC (Internal Procedure Call) do AdvPL.

Subir um pedaço grande inteiro do arquivo na memória inicialmente pode parecer uma boa alternativa, porém lembre-se que em se tratando de processos paralelos, várias juntas podem consumir muita memória, E , se muita memória é ocupada e endereçada, os processos de lidar com esta memória podem ficar mais lentos do que lidar com pedaços menores. Nas minhas experiências, buffers de 8 KB ou 16K dão conta do recado, fazendo um acesso eficiente em disco, e gerando um pedaço de dados que não vai “doer” na memória dos processos.

A parte importante aqui é: Como quebrar um arquivo grande de forma eficiente, e distribuir seus pedaços para processamento? Uma primeira idéia que me veio na cabeça foi fazer com que o programa principal de processamento abrisse a tabela e fizesse a leitura de várias linhas. Após acumular na memória um bloco de linhas, com o mínimo de processamento possível (por exemplo colocando as linhas dentro de um array), este bloco de linhas pode ser enviado por RPC para um dos slaves, e disparar um IpcGo() para uma das threads disponíveis no slave onde o RPC está conectado.

Desta forma, ao invés de mandar linha por linha em cada requisição, onde em cada uma você vai ter um pacote de rede muito pequeno, ao agrupar um número de linhas que chegasse perto de 64 KB de dados, enviar este bloco de uma vez, em um único evento de envio de rede por RPC, para o Slave “da vez”, ele receberia este pacote de uma vez só, isso aproveitaria bem melhor a banda de rede, e o processo alocado naquele Application Server que recebeu este pacote estaria dedicado a processar todas as linhas recebidas naquela solicitação.

Fase 05 – Sincronização de Processos

Parece lindo, mas ainda têm 2 problemas: Partindo de um ambiente com 4 serviços de Protheus, com 2 threads dedicadas em cada um, você teria um total de 8 threads espalhadas. Fazendo um Round-robin entre os serviços, a primeira requisição iria para a T1S1 (primeira thread do serviço 1), a próxima para T1S2, depois T1S3, T1S4, T2S1, T2S2, T2S3, T2S4, e agora as 8 threads estão ocupadas processando cada uma 64 KB de linhas.

Quando você for enviar a requisição 09, ela vai novamente para o serviço 1 … se nenhuma das threads do serviço 1 terminou de processar o pacote anterior, você gastou 64 KB da banda de rede trafegando um pacotão de coisas, para um servidor ocupado … Então você tenta enviar para o servidor 2, gasta mais banda de rede, e… nenhuma thread livre …. Mesmo que você crie uma mensagem de “consulta”, onde você não passasse os dados, apenas perguntasse se tem threads livres naquele servidor, você ficaria metralhando a rede com pacotes pequenos em todos os serviços mapeados para o processo, até que um deles iria responder “estou livre”, para você então mandar para ele mais um pacote de linhas.

Este pequeno percalço pode ser resolvido com um mecanismo chamado de “CallBack”. Nada impede que o seu Job possa fazer um RPC de volta para você, para avisar que um determinado pedaço foi processado. Com isso você pode usar o RPC com IPC em “mão dupla”, com dois pares de conexões. Quando o seu programa principal enviar as 8 requisições, ele entra em um loop de espera por uma mensagem de IPC. Cada JOB alocado precisa receber no momento da alocação um IP e porta e ambiente para conectar-se de volta, para notificar os estados de processamento. Quando um JOB terminar de processar um pacote, ele manda via RPC um sinal de IPC para avisar que ele terminou, informando “quem ele é” na mensagem. Como o seu processo principal vai estar esperando receber uma notificação via IPC, assim que ela chegar, o seu programa principal pega o próximo pacote de linhas e manda para aquela thread via RPC+IPC, pois assim que esta thread enviar a notificação de retorno, ela vai entrar em modo de espera de IPC para uma nova solicitação de processamento.

Este sincronismo também pode ser de mão única … ao invés do seu Job principal fazer um “push” das requisições de processamento, ele pode acionar uma vez os jobs dedicados para serem alocados para este processo, onde o job dedicado imediatamente faz o callback, e passa a “pedir” requisições de processamento, e notificar o programa principal pelo mesmo canal a cada pacote processado.

Existem outras formas de sincronismo, como por exemplo usar o banco de dados. O programa principal cria uma tabela para fins temporários no SGDB, e alimenta esta tabela com os pacotes a serem processados. Porém, se este mecanismo for utilizado, você acaba consumindo tempo e recursos para popular uma tabela grande no SGDB, e cada processo faz uma busca indexada na tabela por um pacote que ainda não foi processado. Ao conseguir locar o registro, o programa de processamento deve mudar o status para “em processamento” e manter o lock até o final do processo. No caso, o programa principal vai alimentando a tabela, enquanto os jobs dedicados vão pegando os registros não processados e fazendo suas tarefas. Quando o programa principal terminar de popular a tabela, ele passa a verificar quais registros ainda estão em processamento, aguardando todos ficarem prontos, e verificando se os jobs de processamento que pegaram os registros ainda estão no ar. NO final das contas, acaba sendo um mecanismo tão complexo quanto o sincronismo “online”, ainda com a desvantagem de colocar o SGDB no meio do caminho.

Fase 06 – Tratamentos de erro

Agora o bicho pega … Imaginar que tudo vai funcionar como um relógio é o mundo lindo … mas e se um job cair, e se a resposta não vir, e se todos os envios falharem, como é que o programa principal fica sabendo se aconteceu algo horrível ? Essa parte do controle é realmente um “parto” de ser feita … existem vários caminhos, mas normalmente os mais fáceis são os mais sujeitos a erros do tipo “falso-positivo” ou “falso-negativo”. Uma das formas mais interessantes de controle é ter um mecanismo confiável para saber se um determinado JOB que recebeu uma requisição ainda está no ar, e criar no programa principal um mecanismo de registro de envios, para dar baixa de cada pacote enviado conforme os eventos de retorno são recebidos, onde deve constar neste mecanismo o momento de envio, para que se um pacote começar a demorar muito, você possa consultar se o job que recebeu aquele pacote ainda está no ar — apenas está demorando um pouco mais — ou se ele saiu do ar — normalmente por erro.

Com estes processos sincronizados e as métricas definidas, o programa principal que inicia o processamento pode, após garantir que um pacote de linhas foi enviado e o job de destino “caiu” sem terminar o processo, você pode direcionar este pacote para outra thread em outro serviço, evitando assim ter que reiniciar o trabalho.

Vale lembrar que cada processo deve ter um transacionamento, que deve ser mantido aberto pelo menor tempo possível, e que os programas de processamento não vão ter “interface”, não será possível (não de maneira simples) perguntar pro operador do sistema o que fazer ou dar uma opção de múltipla escolha para um determinado tratamento dentro de uma linha em um job. Normalmente você trata no programa os cenários possíveis, e qualquer coisa que não estiver de acordo, você pode rejeitar o processamento e gerar um log do que foi recusado, para que sejam tomadas as providências quanto aquelas informações quando o processo terminar, e você puder rodar um reprocessamento apenas do que faltou, após arrumar os dados ou a condição não tratada.

Outras alternativas

Se, ao invés de usar Jobs dedicados, você subir vários jobs de acordo com a quantidade de pedaços da sua tabela, você pode subir um número de Jobs que pode gerar um colapso nos recursos do sistema, como CPU, rede, memória, disco, SGDB …. É mais saudável trabalhar com um número limitado de processos, e medir com testes se a quantidade pode ser aumentada sem comprometer a disponibilidade do resto do ambiente. Este processo é empírico, começa com um job em cada serviço, roda um processamento inteiro, verifica se algum recurso está sendo consumido excessivamente, aumenta alguns jobs, roda de novo …

Cuidados Especiais

Se você resolver subir os jobs sob demanda, usando um fator limitante, de qualquer modo você precisa de um mecanismo para saber se os jobs terminaram o que tinham que fazer, para você poder subir novos Jobs ou enviar requisições de processamento para um Job que já está livre.

É importante lembrar que, por mais abundantes que sejam os recursos, uma carga de processamento mal dimensionada pode derrubar o ambiente, gerando uma indisponibilidade geral de outros serviços. Um programa errado que começa a comer memória com farinha pode esgotar a memoria física de um equipamento, principalmente usando uma Build 64 Bits do Protheus, fazendo a máquina inteira entrar em “Swap” e paginação de memória em disco … eu já vi equipamentos literalmente entrarem em Negação de Serviço (DoS), onde não era possível sequer abrir um Terminal Services pra tentar parar os serviços.

Conclusão

Eu sei, neste post eu só “abrir o apetite”, e abri caminho para muitas reflexões importantes. No próximo post, vamos abordar cada uma destas etapas acompanhada de um exemplo prático 😉

Até o próximo post, pessoal ! Desejo a todos TERABYTES de sucesso 😀

Referências

Introdução a Informática – Parte 02

Introdução

No post anterior, foram abordados assuntos mais ligados a história do surgimento do computador e da informática. Hoje vamos entrar um pouco mais nos computadores de hoje, ver um pouco do que tem dentro, e o que acontece quando você liga o seu desktop ou laptop.

Por dentro do Microcomputador

Um micro-computador é composto basicamente pelos seguintes componentes:

.Processador: Equipamento responsável pela execução de instruções de máquina.
.Memória RAM: Conjunto de memória que mantém bytes armazenados enquanto o computador está ligado. Ao ser desligado, as informações são perdidas (Memória Volátil, não persistente). Usada pelos programas em execução do equipamento para armazenamento temporário do próprio programa e dos dados manipulados pelo programa.
.BIOS: Consiste em um programa básico de infra-estrutura do equipamento, armazenado em uma memória diferenciada na placa principal do equipamento (ROM ou FLASH), que executa um diagnostico inicial quando o computador é ligado, e permite ajustar detalhes internos de comportamentos dos componentes instalados dentro do computador. BIOS é um acrônimo para “Basic Input Output System”, ou “sistema básico de entrada e saída.
.Disco Rígido: Unidade de disco magnético, de uso interno ou externo, usado para armazenar de forma persistente programas e dados. Não é volátil, quando desligado mantém os dados armazenados por longos períodos.
.Placa-mãe ou placa principal (MotherBoard): Hardware utilizado para integrar o processador à memória RAM e a todos os demais periféricos do computador, incluindo outras placas de acesso a dispositivos que podem ser acopladas nela.
.Portas de comunicação: Serial, Paralela, SATA, USB. Usadas para acoplar no computador vários periféricos, como mouse, teclado, fone de ouvido, impressoras, Disco Rígido (ou HD) externo, Scanners, etc.
.Fonte de energia: Conversor de energia alternada (110/220V) para fornecer corrente contínua estabilizada com voltagens de -5 a +12 V para os componentes do equipamento.

Ligando um computador

Assim que o computador é ligado, o primeiro programa carregado automaticamente na memória do equipamento é o BIOS. Ao ser executado, ele faz um diagnóstico nas placa principal, verificando o que está instalado no equipamento: Quantos “pentes” de memória RAM, interfaces de Entrada e Saída, placa de vídeo, rede, portas de comunicação serial, paralela, USB, SATA, etc. Normalmente é feito um teste rápido em alguns blocos dos endereços de memória RAM, para certificar-se que ela está armazenando e recuperando dados corretamente, e se os dispositivos acoplados estão em condições operacionais.

Se um computador não tivesse nada além do BIOS, uma vez ligado o equipamento precisa de um programa para que o operador possa “operar” o equipamento. O primeiro microcomputador que eu aprendi a programar era um MSX, da Gradiente. Processador Z-80, 32 KB de RAM, sem unidade de disco. Depois do BIOS ser carregado e executado com sucesso, o próximo programa carregado era um interpretador de BASIC, que já vinha gravado na memória ROM do equipamento. Este interpretador mostrava um “Prompt” na tela, onde através dele eu poderia executar comandos do BASIC, criar programas na memória e executar estes programas. Este interpretador de comandos é que tornava o meu microcomputador “operável”. Logo, você tinha que aprender quais instruções você poderia utilizar em modo interativo, como usar esse recurso, e quais instruções você tinha disponíveis na linguagem BASIC do equipamento para fazer um programa.

Para tornar um computador “operável”, de uma forma mais flexível, foram criados por várias empresas, com diversos nomes, um conjunto de programas conhecido por “Sistema Operacional”. Como o próprio nome diz, este programa torna um computador “operável”, e através dele você pode executar outros programas, gerenciar programas e arquivos de dados armazenados no equipamento, executar programas utilitários que são distribuídos com o sistema operacional para operações simples, como criação, armazenamento e impressão de arquivos de texto, imagens, áudio, vídeo, etc.

Carga do Sistema Operacional

Após a BIOS ser executada, ela verifica em uma lista de periféricos (Disco Rígido, CD/DVD, porta USB) se existe uma instrução de carga de programa pré-definida armazenada no primeiro segmento de dados destes dispositivos. A BIOS faz esta verificação em uma ordem pré-definida, que pode ser configurada. O primeiro dispositivo acessado que tiver uma instrução de carga de programa, a BIOS executará esta carga.

Quando instalamos um sistema operacional no equipamento (hoje a maioria já vem com um S.O. pré-instalado de fábrica no Disco Rígido), o programa de carga do sistema operacional é executado, e ele é o responsável por carregar todos os demais programas internos criados pelo fabricante do sistema operacional e “drivers” (programas de acesso a dispositivos ) fornecidos pelos fabricantes dos equipamentos e periféricos conectados de alguma forma à placa principal. Esta sequência de carga constitui a carga do “Kernel” do sistema operacional. São programas gerenciadores de disco, memória, vídeo, áudio, comunicação, etc… Cada um destes programas está gravado no Disco Rígido (ou HD) do equipamento, dentro de uma pasta reservada para uso do Sistema Operacional. O sistema Operacional sabe onde eles estão, e sabe interpretar o que tem dentro de cada um.

Enquanto os programas estão sendo carregados, é mostrada normalmente uma imagem no monitor (ou vídeo) do computador, normalmente um logotipo do fabricante do Sistema Operacional sendo carregado. Quando esta carga é bem sucedida, logo em seguida são carregados e iniciados os programas internos, chamados de “serviços” do Sistema Operacional, e um programa dedicado a fornecer a interface “operacional” do sistema. No caso do Windows, é carregado automaticamente o processo chamado “Explorer”, responsável pelo DeskTop do equipamento, onde a partir dele podemos acessar todas as opções do sistema operacional e executar todos os demais programas instalados no equipamento.

Old School

Um dos primeiros sistemas operacionais que eu tomei contato foi o MSX-DOS (Sistema operacional de disco do MSX), carregado quando você iniciava o computador com uma unidade de disquete externa acoplada no equipamento. Sua interface era bem similar ao MS-DOS ( Microsoft Disk Operational System). Basicamente eram carregados apenas dois drivers ( IO.SYS e MSDOS.SYS ), e na sequência era carregado o interpretador de comandos do DOS ( Ainda hoje presente em praticamente todas as versões de Windows, acessado através do ícone “Prompt de Comando”.

Na primeira carga do interpretador de comandos, um arquivo com as configurações iniciais de carga do sistema operacional era processado. No arquivo CONFIG.SYS eram definidos os drivers de gerenciamento de memória, disco e demais dispositivos. Uma vez que tudo estava carregado, era executado um arquivo chamado AUTOEXEC.BAT, com uma lista de chamada adicionais de outros programas para definir configurações de ambiente e carregar outros dispositivos. Enfim, você tinha acesso ao Prompt de comandos, que mostrava normalmente a unidade de disco atual “C:\>”.

O interpretador de comandos possui um conjunto de comandos nativos, e o sistema operacional já vinha com alguns programas simples, como um editor de textos em formato TXT (EDIT), um programa interpretador para desenvolver usando a linguagem BASIC, algumas ferramentas de manutenção de disco (FORMAT/CHKDSK/SCANDISK/DEFRAG), comandos para criar estruturas de pastas nas unidades de disco para armazenamento de arquivos, comandos para realizar cópia, mover arquivos, apagar arquivos e pastas, etc. Estes comandos tinham que ser digitados no Prompt de comando, seguindo a sintaxe e parâmetros adequada para cada comando. Todos os demais programas que você quisesse instalar e executar no equipamento precisam ser compatíveis com aquela versão do sistema operacional.

E agora ?

Uma vez que o computador esteja ligado, e o sistema operacional esteja carregado, você pode abrir qualquer um dos programas instalados, instalar novos programas, enfim, você pode usar o computador. Para cada tarefa ou utilização do computador, você precisa usar um programa. Para criar um programa você usa um ou mais programas.

Editores de texto mais avançados, planilhas eletrônicas, aplicações de bancos de dados, ambientes de desenvolvimento para programação, jogos e afins, são programas ainda vendidos ou obtidos separadamente. No início da década de 90, as aplicações mais famosas para edição de textos, planilha eletrônica e banco de dados eram o WordStar, Lotus 123 e DBASE III, respectivamente. Hoje são os programas do Microsoft Office “Word”, “Excel” e “Access”. Todos estes novos programas são evoluções dos programas iniciais, com mais recursos, funcionalidades e integrações.

Se você quiser acessar a Internet, você precisa ter um programa chamado “Internet Browser”, que a partir de um endereço de um servidor (ou site), este programa é capaz de conectar no site, recuperar o arquivo que contém um script com a tela inicial do site, e “desenhar” este arquivo na sua tela, servindo de “interface” para você acessar os conteúdos e funcionalidades do site. Hoje os Browses mais famosos são o Google Chrome, o Internet Explorer, o Mozzila Firefox….

Se você quiser programar na linguagem Python, você precisa instalar o programa responsável por interpretar os scripts desta linguagem no seu computador. Hoje em dia basta ter uma conexão com a Internet, abrir o seu Internet Browser, acessar um mecanismo de pesquisa ( Google Search, Yahoo, Bing ) e procurar por “Python Download”, entrar no site “Phyton.org”, localizar a área de Download, escolher a versão da linguagem adequada ao seu sistema operacional, fazer o download, e instalar o aplicativo na sua máquina. Uma vez instalado, você deve aprender como a linguagem funciona, como você escreve um programa, e como você executa um programa.

Mas, antes de mais nada, eu recomendo que você aprenda o que é e como funciona o sistema operacional que você está utilizando. Para ser apenas um operador da máquina, e utilizar ela para fazer seus textos, documentos, ver fotos e filmes, acessar a Internet, você precisa pelo menos de uma noção de “como” e “onde” o seu sistema operacional guarda no disco os seus arquivos de dados, os seus programas instalados, as suas fotos, vídeos e afins, e como você faz para instalar, desinstalar e executar um ou mais programas.

Conclusão

Quando vemos um sistema computacional ‘por cima’, ele é relativamente simples. O que começa a dar volume da complexidade das operações é quantidade de recursos e etapas que uma instrução ‘simples’ faz por baixo do capô. Você não precisa ser mecânico para dirigir um carro, mas ter pelo menos uma noção de mecânica pode servir de orientação e explicar por quê determinados procedimentos não são boas práticas ao dirigir. O mesmo principio é totalmente válido ao operar um computador. Para programar a máquina, você precisa ter pelo menos um conhecimento superficial de mecânica, de como ela funciona. Isso vai fazer você conseguir aproveitar melhor os recursos do equipamento que você têm em mãos.

Fala-se sobre em “lógica de programação”, e sobre este tema pintam um monstro de 2 cabeças e vários tentáculos. Lembre-se, programar é como escovar os dentes, não passa de uma lista de tarefas. A “lógica” em si é a ordenação destas tarefas em uma sequência de operações e decisões que chegue ao resultado esperado. Depois de escrever um programa simples em qualquer linguagem e ver como ele funciona, você verá que o monstro não é tão feio quanto o que falam dele.

Curiosidades

Antes de aprender programação, eu literalmente “devorei” a coleção de revistas de eletrônica do meu pai. Chamava-se “Be-a-Bá da Eletrônica”, ele tinha a coleção completa da edição 1 a 32, que abordava em uma linguagem didática desde o que era um elétron e um fluxo de energia, até eletrônica digital e portas lógicas. Eu realmente fiquei fascinado ao saber o que era eletricidade e eletromagnetismo, e como vários tipos de materiais poderiam ser usados para gerar luz e dar movimento às coisas, apenas controlando o fluxo de elétrons entre as partes de um circuito elétrico. Quando eu aprendi a primeira linguagem de programação, eu imaginei usar este conhecimento para criar programas e ferramentas que me ajudassem a projetar circuitos eletrônicos. Porém, quando eu comecei a programar, e parei de tomar choque em capacitor carregado, parei de queimar a mão no ferro de solda ao tentar colocar um transístor em uma ponte de terminais, em “fritar” uma peça por que um fio estava errado… Chega de eletrônica, isso aqui é mais divertido.

Desejo novamente a todos TERABYTES de Sucesso 😀

Até o próximo post, pessoal 😉

Referências

SISTEMA OPERATIVO. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=Sistema_operativo&oldid=43714710>. Acesso em: 1 nov. 2015.

PREEMPTIVIDADE. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=Preemptividade&oldid=43360409>. Acesso em: 1 nov. 2015.

SISTEMA DE FICHEIROS. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=Sistema_de_ficheiros&oldid=43725348>. Acesso em: 1 nov. 2015.

Introdução a Informática – Parte 01

Introdução

“Informática é um termo usado para descrever o conjunto das ciências relacionadas ao armazenamento, transmissão e processamento de informações em meios digitais, estando incluídas neste grupo: a ciência da computação, a teoria da informação, o processo de cálculo, a análise numérica e os métodos teóricos da representação dos conhecimentos e da modelagem dos problemas. Mas também a informática pode ser entendida como ciência que estuda o conjunto de informações e conhecimentos por meios digitais.” (1)

Em dois artigos anteriores, eu postei algo sobre Programação e sobre Análise de Sistemas. Seguindo a mesma linha, de “desmistificar” a aparente complexidade deste universo, eu reparei que alguns conhecimentos que eu considero como “base” para o entendimento dos sistemas computacionais são pouco abordados, ou são vistos com uma superficialidade muito grande.

E boa parte do que temos hoje em tecnologia de sistemas e processamento de dados é uma evolução natural desta base. Logo, eu considero fundamental saber um pouco mais da origem das coisas, e da evolução histórica da computação no último século, para entender um pouco mais no que ela é baseada, e por quê (e como) ela evoluiu a saltos gigantescos desde então.

Um pouco de História

Fiz meu primeiro curso de programação com 13 anos de idade, e meu primeiro curso de nível profissional de informática com 15 anos, em uma escola de informática em Botucatu, fundada por um ex-técnico de Software da IBM e sua esposa. Antes de sentarmos na frente de um IBM-PC e ligá-lo pela primeira vez, tivemos uma semana de aula sobre “Introdução a Informática”, para que todos tenham uma noção de o que é um micro-computador, o que têm dentro, e pelo menos uma noção de como as partes internas funcionam.

Particularmente eu achei aquilo extremamente interessante, pois na semana seguinte, quando fomos para a frente dos computadores, mesmo sem ter visto um, nós sabíamos o que precisava ser feito para ligá-lo, e o que acontecia desde o momento que você apertou o botão “ON” até aparecer o “Prompt” de comando do sistema operacional ( na época, “A:\>” ).

Seguindo esta linha, estou dando inicio a uma série de Posts, com a TAG “Introdução a Informática”, onde eu vou tentar trazer esse conhecimento para vocês, com a maior riqueza de detalhes que a minha memória permite, estendendo esta abordagem até os micro-computadores dos dias de hoje. Recomendo essa literatura a todos que estão iniciando seus estudos em computação, e estendo o convite a todos que tenham alguma curiosidade sobre isso.

A necessidade é a mãe da invenção

A necessidade de mensurar coisas é tão antiga quanto a história da civilização. Uma vez que o homem aprendeu a cultivar a terra, por volta do período neolítico (8 mil A.C.). Este período é considerado um importante avanço social, econômico e político, onde o homem descobre que é muito mais vantajoso agir em grupo do que individualmente.

Com a subsistência mais fácil, não tendo que sair para caçar todos os dias, os neolíticos tinham mais tempo para interagir entre si, então desenvolveram as primeiras atividades de lazer, descobrindo a arte da cerâmica e depois como comercializá-la. O surgimento da escrita e a criação do Estado pelas primeiras da Antiguidade marcou o final da era neolítica.

Desde então, sempre existiu a necessidade de mensurar coisas. Quantidade de sementes, frutos produzidos, criação de unidades monetárias (dinheiro) para facilitar relações comerciais e afins. Embora a matemática conhecida hoje — usando algarismos indo-arábicos (1234567890), com ponto decimal e frações date de 1000 D.C., a utilização dessa representação em algarismos decimais é datada de 2 A.C.

O Ábaco, um instrumento de cálculo que data de 5500 A.C., ele é considerado como uma extensão do ato natural de contagem com os dedos. E também usa o sistema decimal (onde usamos 10 algarismos para representar um número). O Ábaco ainda é usado hoje para ensinar a crianças somar e subtrair.

Invenções mecânicas

Buscando dar mais precisão, segurança e velocidade aos processos de operações numéricas, várias invenções mecânicas foram surgindo ao longo do tempo, como a máquina de operações de Pascal (Século XVII), o Tear de cartões perfurados de Jacquard (Século XVIII), o projeto da máquina analítica de Babbage, até a máquina eletromecânica de Herman Hollerith, um equipamento que usava cartões perfurados usado para calcular o censo populacional dos EUA de 1890 em APENAS um ano — o censo da década anterior demorou 7 anos … Através de um painel de fios em seu tabulador 1906 Type I, foi possível executar diferentes trabalhos sem a necessidade de ser reconstruído. Estes foram considerados os primeiros passos em direção à programação. Em 1911, quatro corporações, incluindo a firma de Hollerith, se fundiram para formar a Computing Tabulating Recording Corporation. Sob a presidência de Thomas J. Watson, ela foi renomeada para IBM (“International Business Machines”).

O papel da eletricidade

Mesmo sendo conhecidos desde a Grécia antiga, os fenômenos magnéticos e os fenômenos elétricos somente começaram a ser estudados e explicados cientificamente a partir do século XVII. No início do século XIX, Hans Christian Ørsted obteve evidência empírica da relação entre os fenômenos magnéticos e elétricos. A partir daí, os trabalhos de físicos como André-Marie Ampère, William Sturgeon, Joseph Henry, Georg Simon Ohm, Michael Faraday foram unificados por James Clerk Maxwell em 1861 por meio de equações que descreviam ambos os fenômenos como um só: o fenômeno eletromagnético. Esta unificação foi uma das grandes descobertas da física no século XIX. Com uma teoria única e consistente, que descrevia os dois fenômenos anteriormente julgados distintos, os físicos puderam realizar vários experimentos prodigiosos e inventos úteis, como a lâmpada elétrica (Thomas Alva Edison) ou o gerador de corrente alternada (Nikola Tesla)

Entre 1930 e 1940, George Stibitz, um pesquisador da Bell Labs percebeu que os relés eletromecânicos usados em centrais telefônicas poderiam ser usados para realizar operações sequenciais, e desenvolveu os primeiros circuitos de lógica digital usando relés. Os projetos de computadores usando relês da Bell foram usados pelos EUA para fins militares, usando 1400 relês e com memória de 10 números, eles eram usados para processamento de cálculos de direcionamento de artilharia anti-aérea. Os trabalhos de George Stibitz foram baseados nos princípios de álgebra booleana, concebidos por George Boole quase um século antes, mas que até o momento não tinham aplicação prática.

Com o surgimento da válvula termo-iônica, como uma forma de modulação direta de energia, bem mais rápida que um relê, todo o conhecimento adquirido até então foi aproveitado para a evolução desta tecnologia. Porém, as válvulas queimavam com muita facilidade, e consumiam muita energia para funcionar. Mas a velocidade de chaveamento de energia era tão mais rápida que um relê, que logo surgiram os primeiros computadores usando esta tecnologia. A universidade de Iowa em 1942 montou um dos primeiros computadores valvulados, não programável, mas funcional para resolver equações de primeiro grau.

O primeiro computador totalmente eletrônico e programável foi o ENIAC (Electronic Numerical Integrator And Computer). Construído durante a segunda guerra mundial na universidade da Pensilvânia, ficou pronto em 1946. Usava mais de 17 mil válvulas, consumia 150 kW, e pesava 27 toneladas …. mas era milhares de vezes mais rápido do que qualquer computador a relê. Por exemplo, o computador Harward Mark II (1947), que usava relês de alta velocidade, operava a uma frequência de 8 Hz (ciclos por segundo). O ENIAC operava a uma frequência vertiginosa de 5 mil Hz (5 KHz), o que permitia ele calcular aproximadamente 357 multiplicações de números de 10 dígitos por segundo. Hoje, um processador de um SmartPhone ultrapassa facilmente 1 GHZ ( Um BILHÃO de ciclos por segundo).

Onde estão os “zeros” e “uns” ?

O sistema de numeração binário (base 2), usa apenas dois algarismos para representar um valor: ‘0’ ou ‘1’. Em informática, a menor unidade de armazenamento de um dado é o “bit”, que coincidentemente também armazena os valores ‘0’ ou ‘1’. Quando agrupamos 8 bits, temos um Byte ( também chamado de “octeto” de bits). Utilizando um BIT, armazenamos 2 valores diferentes (0 ou 1). Usando 2 bits, armazenamos quatro sequências de bits diferentes ( 00, 01, 10 e 11). Usando 8 Bits (um Byte) podemos armazenar 2 ^ 8 sequencias diferentes, ou seja, 256 combinações diferentes de 0 e 1 (de 00000000 a 11111111). Convertendo isso para numeração decimal (ou base 10), temos 256 valores diferentes (entre 0 e 255).

E por que eu preciso saber disso ?

Bem, meu chapa … toda a base de programação e processamento de dados são sequencias de zeros e uns. Isto somente vai ser quebrado com a computação quântica, que surgiu como teoria a alguns anos, e atualmente os estudos na área estão tornando possível a criação do Hardware para permitir este tipo de processamento. A computação quântica deve quebrar paradigmas em campos de aplicação onde as máquinas tradicionais (utilizando lógica booleana) chegaram em um limite tecnológico “físico” de desempenho. A menor unidade de informação em um computador é um Byte, que nada mais é do que um agrupamento de 8 bits. Logo, todo o armazenamento de dados e fluxo de informações entre os componentes de um computador e seus componentes auxiliares (ou periféricos) serão sequências ou blocos de zeros e uns 😉

E onde entra a tal da “programação” ?

Programar significa fornecer uma lista de instruções para realizar uma determinada tarefa. Quando você compra um produto desmontado, que vêm com um manual de instruções de montagem, ele descreve em linguagem natural a lista de passos para você montar o produto. Isto pode ser considerado um programa, que ao ser executado na ordem certa e com os materiais corretos, resulta no produto montado.

Um programa de computador é exatamente isso. Qualquer programa de computador é composto de uma sequência de instruções e dados, regidos por uma gramática e um conjunto de operações especificas, cujo objetivo final é enviar ao processador do equipamento uma sequência de códigos binários que representem a sequência de processamento a ser executada. Nesta sequência de instruções podemos interagir com os periféricos do equipamento, como a interface de vídeo, o teclado, uma impressora, uma unidade de armazenamento de dados, etc.

Conclusão

Este tópico é só para “abrir o apetite”. No próximo vamos dar uma boa olhada no que tem dentro de um computador, o que é um “Sistema Operacional”, por quê precisamos de um, e depois o que acontece quando a gente liga um equipamento.

Desejo a todos uma boa leitura, e TERABYTES de sucesso 😀

Até o próximo post, pessoal 😉

Referências

INFORMÁTICA. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=Inform%C3%A1tica&oldid=43615873>. Acesso em: 12 out. 2015.

ÁBACO. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=%C3%81baco&oldid=43500340>. Acesso em: 12 out. 2015.

ALGARISMOS INDO-ARÁBICOS. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=Algarismos_indo-ar%C3%A1bicos&oldid=43058223>. Acesso em: 12 out. 2015.

ELETROMAGNETISMO. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=Eletromagnetismo&oldid=43478266>. Acesso em: 12 out. 2015.

HERMAN HOLLERITH. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=Herman_Hollerith&oldid=42754476>. Acesso em: 12 out. 2015.

George Stibitz. (2015, August 15). In Wikipedia, The Free Encyclopedia. Retrieved 07:19, October 12, 2015, from https://en.wikipedia.org/w/index.php?title=George_Stibitz&oldid=676218293

Harvard Mark II. (2014, September 19). In Wikipedia, The Free Encyclopedia. Retrieved 07:37, October 12, 2015, from https://en.wikipedia.org/w/index.php?title=Harvard_Mark_II&oldid=626186726

ENIAC. (2015, October 12). In Wikipedia, The Free Encyclopedia. Retrieved 07:44, October 12, 2015, from https://en.wikipedia.org/w/index.php?title=ENIAC&oldid=685327153

SISTEMA DE NUMERAÇÃO BINÁRIO. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/w/index.php?title=Sistema_de_numera%C3%A7%C3%A3o_bin%C3%A1rio&oldid=43459004>. Acesso em: 12 out. 2015.

Outras referências

http://www.infoescola.com/pre-historia/periodo-neolitico/

http://www.newtoncbraga.com.br/index.php/curiosidades/4856-cur008

http://www.techtudo.com.br/artigos/noticia/2012/09/computadores-a-valvulas.html