Incêndio O fim das locadoras de vídeo (parte 2)

Otimização

11 de Abril de 2008 às 18:31 Thiago  | Enviar por e-mail Hits para esta publicação: 389

Eu gosto muito quando tenho a oportunidade de otimizar um programa.

Precisamos realizar testes de carga numa aplicação servidora, então fui incumbido de modificar o programa cliente de modo que ele envie uma série de requisições para o servidor o mais rápido possível.

Fiz uma implementação bem direta e o resultado: Com 100 threads rodando minha máquina “agachava” e logo logo estourava a memória. Não estava bom o bastante.

A razão disso foi que a aplicação cliente não foi projetada para ter desempenho, pois normalmente faz apenas poucas requisições e termina, então eu não me preocupei com gasto de memória ou de tempo, já que ninguém iria notar mesmo, e fiz um projeto caprichado. Até demais.

Tenho a tendência de criar classes demais, entupir o programa com diversos níveis de abstrações e utilizar todos os design patterns que eu agüentar. :) Código bonito, extremamente flexível e lento. Uma questão importante é avaliar se a abstração realmente será benéfica. Por exemplo, num dos pacotes lógicos da aplicação, relacionei as classes de tal forma que incluir uma classe nova nesse pacote seria extremamente simples, sem a pessoa precisar de nenhum conhecimento das outras camadas da aplicação. Muito legal, exceto por um detalhe: só surgirão novas classes nesse pacote de cinco em cino anos, e isso se é que vão surgir novas. Então, muito esforço por pouca coisa.

Rodei um profiler na aplicação (sempre precisamos medir para saber onde o gargalo está, não é mesmo?) o TPTP do projeto Eclipse. A instalação não é amigável, mas funcionou. O profiler mostrou que eu estava criando milhares de objetos pequeninos, o que consumia tempo e memória.

O que fiz? Eliminei as abstrações. Nada de referências, delegações e indireções. Aproveitei alguns objetos mais de uma vez. Evitei criar objetos dentro de loops. Matei umas 10 classes. O engraçado é que o código de algumas outras ficou bem mais simples e legível. É… serve para aprender que nem sempre um nível de abstração a mais torna as coisas mais compreensíveis.

Testei o código e ficou muuuuuuito mais rápido, até assustei-me! Agüentou 100 threads sem nem chegar a 100% de uso da CPU e tinha memória de sobra na minha máquina. Reduzi em 50 vezes o número de objetos que a aplicação criava.

Ainda assim, não ganha da vez, quando trabalhava no laboratório Synergia, onde consegui um ganho de performance de 32.000% em um método de exibição de relatório, hehehe! Aquela sim causou comoção! :-)

Publicação arquivada em: Sem Categoria

Enviar por e-mail | Hits para esta publicação: 390

3 Comentários Faça seu próprio

  • 1. Matheus  |  15 de Abril de 2008 às 17:16

    Não se esqueça daquela otimização do projeto da disciplina de compiladores, conseguida apenas com a escrita apropriada de equals() e hashCode() em algumas classes. :)

  • 2. Thiago  |  15 de Abril de 2008 às 17:27

    Ah, é! TInha me esquecido dessa!
    Como fazer um programa que demorava 35 horas para finalizar um processamento gastar apenas 10 minutos. :)

    O problema não era só esses métodos não. Tive que reformatar todos os dados de entrada por outra forma equivalente.
    Pena que só fiz isso no fim do prazo para entregar o trabalho… os dias que tive que deixar o computador ligado fazendo só isso foram agonizantes…

    Fica um bom aviso: se algo está demorando demais, dê uma olhada no que pode ser feito para melhorar logo de uma vez.

  • 3. heringer  |  2 de Maio de 2008 às 08:57

    Gostei demais desse post seu. Como diz um amigo meu, “na prática, a teoria é outra”. Na vida real, temos que abrir mão de algumas práticas elegantes para atender aos requisitos.

    Quando se trabalha com persistência isso fica ainda mais evidente. Usar uma camada de persistência totalmente orientada a objetos pode ser inviável em situações de estresse num banco de dados.

    Tinha um relatório no nosso sistema que levava mais de duas horas para abrir. Como ele usava os recursos “normais” do framework que abstraía a camada de persistência, havia vários “loads” implícitos de dados do banco.

    Tivemos que alterar o código todo para usar recursos menos amigáveis, mas que carregava dados do banco em uma única chamada. Resultado: o relatório com muitos dados sai agora em 4 minutos.

Deixe um Comentário

Requerido

Requerido,escondido

Linkar esta publicação  |  Assine os comentários via o RSS


Calendário

Abril 2008
S T Q Q S S D
« Fev   Mai »
 123456
78910111213
14151617181920
21222324252627
282930  

Minhas Publicações Recentes

Publicações por Mês

Estatísticas

Meta