domingo, 8 de março de 2009

Consumo de energia e otimização de código

Consumo de energia e otimização de código


Tenho ouvido falar muito sobre eficiência energética, taxa de carbono, custo de refrigeração de data centers. Isto me deixou intrigado e comecei a pensar em como a construção de aplicativos (componentes, sistemas, etc.) pode ajudar na otimização e economia de energia. Claro que este é um assunto muito vasto e poderão ser tomadas decisões distintas, dependendo de cada projeto. Teve um sistema a que tivemos acesso, e que possuía grandes problemas de performance e consequente consumo de energia. Este projeto era desenvolvido utilizando banco de dados SQL Server 2000/2005 e Visual Basic 6.0., com base nisto as soluções mostradas foram baseadas nesta aplicação e servirá apenas como um modelo para exemplificação.


Princípios para economia de energia

  • Minimizar a quantidade de dados armazenados: dado utiliza energia já que dados armazenados em aplicações de banco de dados ou sistema de arquivos necessitam de operações em disco para serem armazenadas. Então, reduzindo a quantidade de dados armazenados podemos reduzir a quantidade de energia utilizada por uma aplicação, por reduzir a quantidade de dados na infraestrutura de armazenamento.” (FRANCIS e RICHARDSON, p. 11, 2009).

  • O princípio, ainda mais importante do que o primeiro, seria “desenvolver e codificar aplicações eficientes: No passado os desenvolvedores eram forçados a codificar cuidadosamente porque os computadores eram muito lentos e códigos ineficientes faziam a aplicação inutilizável. A lei de Moore nos deu computadores poderosos com recursos de hardware com taxas mais velozes do que poderíamos consumir, resultando em aplicações que aparentemente executam corretamente e melhores do que jamais pudemos imaginar, mesmo o código sendo gastador de recursos e ineficiente. Códigos ineficientes necessitam de grandes ciclos de CPU para serem consumidos, o que consome mais energia.” (FRANCIS e RICHARDSON, p. 11, 2009).


Quanto mais o “processador estiver carregado, maior será o consumo de energia” (FRANCIS e RICHARDSON, p. 11, 2009), send assim a eficiência energética pode ser obtida através da seguinte equação:


eficiência = throughput / watt


Quando maior a quantidade de dados processados em um determinado tempo e menor o consumo de energia, maior será a eficiência energética do servidor.



Decisões e procedimentos

Otimizar sistemas em produção, sempre trazem grandes problemas e insatisfações dos clientes com relação a instabilidades no aplicativo. Visando minimizar estes problemas foram tomadas decisões que impactassem o mínimo possível no projeto, porém estas alterações deveriam gerar ganhos perceptíveis de performance, principalmente por parte dos clientes.

Com os princípios propostos, em um primeiro momento, foi realizado um mapeamento dos dados para que fossem realizadas otimizações nas bases de dados, primeiramente com a redução da quantidade de dados armazenada. É muito comum que sejam construídas tabelas com campos do tipo “int” onde poderia haver um dado do tipo “smallint”, ou dados do tipo “smallint” onde poderia haver um dado do tipo “tinyint”. Também é comum serem utilizados campos do tipo “varchar(n)” onde poderia existir um campo com valor numérico (numeric, int, smallint, tinyint), abro um parêntese para a conversão de campos “varchar” para um correspondente numérico, pois nestes casos é necessário uma análise precisa do código para evitar sérios problemas na aplicação. A otimização dos tipos do banco de dados também impactará significativamente na performance do banco de dados, já que chaves/índices/registros menores serão encontrados mais rapidamente e consumirão menos ciclos de CPU, e poderão ser encontrados mais rapidamente.

A otimização do código é um pouco mais complicada e inicialmente foram necessárias pesquisas para analisar o ambiente em que as aplicações era executada e a tecnologia empregada na sua fabricação, antes de iniciarmos as alterações. Uma coisa que, talvez não saibam, é que o Visual Basic 6.0 utiliza uma máquina virtual para a execução do aplicativo, como grande parte das linguagens que utilizam alocação dinâmica de memória, e um grande gargalo destas aplicações são a desalocação de memória (“garbage collector”), e neste caso é sempre bom ler a documentação e seguir as recomendações do fabricante. Um outro ponto a ser analisado é o tamanho total da aplicação, em alguns casos poderão ser construídos componentes “ActiveX” agrupando as funções em comum, para a redução do tamanho total do executável em memória, já que quando ocorrer a necessidade da utilização de certas funções (externas a aplicação), o sistema fará a alocação do objeto na memória e estes recursos poderão ser liberados quando não forem mais necessários.

O manual do MSDN faz as seguintes recomendações para otimização de código, utilizando Visual Basic 6.

  • Evite utilizar variáveis do tipo “variant”.

  • Dê preferência para utilizar variáveis do tipo “integer” e “long”.

  • Coloque os valores das propriedades mais utilizadas em uma variável.

  • Substitua chamada de procedimentos por códigos “inline”.

  • Utilize constantes sempre que possível.

  • Passe argumentos com “ByVal” ao invés de “ByRef”.

  • Utilize argumentos opcionais tipados.

  • Tire vantagens das “collections”.


Como muitos destes itens podem parecer meio vagos, mais informações sobre cada um dos itens listados pode ser obtido diretamente do site do MSDN, no endereço: http://msdn.microsoft.com/en-us/library/aa263511(VS.60).aspx#


Com estas informações em mãos, as otimizações do código foram realizadas utilizando a seguinte regra de prioridade:

  1. Funções genéricas, aquelas utilizadas por grande parte da aplicação.

  2. Módulos e funções mais utilizados pelos usuários.

  3. Módulos críticos, aqueles em que a empresa fica parada caso não funcionem (merecem atenção especial).


Ainda tinhamos algumas dúvidas com relação à alocação de memória, com relação as variáveis, por parte do VB6, neste foram construídos dois protótipos para exemplificar como a aplicação se comportava quanto a alocação de memória. Para isto foram criados dois executáveis, um deles fazia a alocação de um vetor do tipo “Long” com 1 posição e o outro utilizava um vetor com 52256000 posições (definido aleatoriamente), os valores eram apenas alocados na memória, não eram manipulados em nenhum momento, a seguir uma imagem para exemplificar o tamanho das duas aplicações.





Após a confirmação da alocação de memória, passamos a um problema sério, variáveis que eram declaradas no código e em nenhum momento eram utilizadas na aplicação, gerando um desperdício de memória e um consequente aumento no consumo de energia. Este é um processo que demandaria muito tempo para analisar todo o código, neste caso a decisão tomada, foi a construção de um aplicativo para fazer a leitura de toda a aplicação e validar as variáveis que estavam sendo utilizadas e aquelas que não eram utilizadas, como este procedimento é muito perigoso, o aplicativo apenas gerava um log indicando onde as variáveis se encontravam, arquivo e linha, permitindo que o programador a localizasse rapidamente e fizesse a correção (manualmente).

A construção deste aplicativo nos roubou uma madrugada e um dia de trabalho, não ficou otimizado, mas permitiu que realizássemos as correções rapidamente. Isto também possibilitou a descoberta de algumas falhas no código, ainda não reclamadas ou ocorridas nos clientes. Também foram realizadas algumas otimizações no banco de dados, mas não entrarei em mais detalhes, pois fogem ao escopo deste artigo.


Conclusão

Ao final das iterações, pode-se perceber uma melhora significativa na qualidade do aplicativo e na otimização da aplicação, os usuários puderam perceber uma melhora significativa na sua execução, também pudemos perceber que a utilização de boas práticas e uma codificação otimizada sempre podem evitar falhas na aplicação, além de facilitar o entendimento do código pelos membros da equipe, apesar da demostração de otimização em aplicações cliente/servidor, aplicativos que serão executados apenas no servidor merecem uma atenção especial, pois a maior parte, senão todo, o processamento do aplicativo será centralizado nele, o que poderá gerar a necessidade de um consumo extra de energia com a alocação física de mais servidores ou processadores, do que o necessário, caso a aplicação fosse construída preocupando-se com a eficiência energética.


Referências:

FRANCIS, Kevin e RICHARDSON, Peter. Green Maturity Model for Virtualization. Green Computing.

Microsoft Journal, Estados Unidos, n. 18, p. 11, 2009.


MICROSOFT. Visual Basic Concepts. Optimizing Code. Disponível na internet. http://msdn.microsoft.com/en-us/library/aa263511(VS.60).aspx# . 2009.


Um comentário:

ricbit disse...

Uai, pode linkar sim, go for it.