Otimização “madura”

October 23, 2007

Aconselho a leitura do artigo Mature Optimization, escrito por Mick West.

Ele aborda uma questão interessante: otimização no inicio do projeto é sempre ruim?

Citando Donald Knuth:

We should forget about small efficiencies, say about 97% of the time. Premature optimization is the root of all evil – Knuth, Literate Programming, 1992, p28.
O autor tenta mostrar que, as vezes, otimizações no final do projeto podem ser problemáticas:
Towards the end of the project we profile the code, and find that 20% of our CPU time is taken up by a function [...] then we fix it. Then we tackle our next function on the profiler’s list; maybe one that takes 10% of the CPU time. We fix that[..] Our game now runs 30% faster[...] However, if after that the code is still too slow, you will now find it is not because of a few weighty functions, but rather a general problem with all of the code. The code is just generally inefficient. By ignoring optimization until the end of the project you have ended up with “sick code” that contains multiple inefficiencies too deeply ingrained within the fabric of the code to be removed in a timely manner.
A idéia do texto é mostrar que existem duas categorias de otimizações a serem consideradas. A primeira, considerada precoce e ruin, é aquela que é feita sem um real entendimento da necessidade dela e sobretudo do efeito final. As vezes, gastamos um grande tempo otimizando uma função cara que, no final das contas, será chamada apenas uma ou duas vezes durante a execução do programa sem afetar na performance geral.

A segunda categoria é chamada pelo autor de otimização madura. Ela cuida de problemas bem conhecidos em certos domínios de software, que são recorrentes e sobretudo previsíveis em vários projetos. Em geral, são otimizações estruturais que envolvem decisões de arquitetura e que dificilmente podem ser corrigidas ao final do projeto. O autor cita vários exemplos aplicados ao desenvolvimento de jogos, onde performance é crítica. Um exemplo bom é a questão de alocação de memória: é muito mais eficiente utilizar um sistema de pool de objetos do que ficar executando alocação repetitiva e constante na pilha.

No domínio de software que eu tenho trabalhado, o grande gargalo pode ser a quantidade de dados gravados. Uma simples listagem pode ser um pesadelo caso não seja feita seguindo certas regras simples: usar paginação na base de dados (e nunca na camada de aplicação), tentar filtrar ao máximo os dados extraídos da tabela (extrair apenas o necessário para exibição, evitandoo aumento desnecessário da quantidade de dados). Pode parecer bobo, mas outro dia me deparei com uma listagem simples que demorava em torno de 15 minutos pra rodar…

O problema acima não se encaixa tão bem no quesito “decisão estrutural”, porque ao final do código é relativamente simples mudar sem grande impacto no sistema. É apenas chato ter que passar por todas as queries, reescrever e retestar tudo. Sem contar que em geral o problema irá aparecer apenas depois do sistema ter sido instalado no cliente, ou estar em produção (afinal, ele está diretamente ligado à quantidade de dados da base). Mas com certeza é o tipo de problemas que pode ser facilmente mapeado no inicio do projeto e que não impacta em nada no desenvolvimento, se bem organizado.

tags: ,
posted in Desenvolvimento, Design by Miguel Galves

Follow comments via the RSS Feed | Leave a comment | Trackback URL

View Comments to "Otimização “madura”"

  1. wrote:

    Otimização “madura” « Log4Dev

    Será realmente que TODA otimização feita no início de um projeto de software é ruim e pode ser prejudicial? Miguel Galves discute este aspecto e tenta mostrar que em alguns casos, não só não é prejudicial como é necessária.

  2. wrote:

    1st – Make it work. 2nd – Make it simple. 3rd – Make it fast.

    A maior parte das vezes que tive problemas com performance foram por violação ao item 2 :)

    Concordo que não se pode deixar a performance completamente de lado. Mas a única maneira de evitar “achismos” nessa parte é medir. Sem medição, pensar em perfomance (antes ou depois) e completamente pointless.

  3. wrote:

    Corrigindo meu reply (Miguel, pode apagar o primeiro se quiser):

    Ronie, eu assino embaixo, sem medição otimizar é um tiro no escuro mesmo.

    Aumentar a performance de um trecho de código geralmente implica em aumentar sua complexidade e diminuir sua legibilidade (mas nem sempre), para não falar do tempo que se perde, então é algo que deve ser feito apenas com a certeza de sua necessidade.

    Agora eu confesso que tiro o corpo fora da discussão quando se fala de desenvolvimento de jogos por exemplo, não tenho experiência nesta área para dar meus pitacos, agora no mundo de aplicações corporativas o conselho do Knuth é lei.

  4. wrote:

    Corrigindo meu reply (Miguel, pode apagar o último se quiser):

    Ronie, eu assino embaixo, sem medição otimizar é um tiro no escuro mesmo.

    Aumentar a performance de um trecho de código geralmente implica em aumentar sua complexidade e diminuir sua legibilidade (mas nem sempre), para não falar do tempo que se perde, então é algo que deve ser feito apenas com a certeza de sua necessidade.

    Agora eu confesso que tiro o corpo fora da discussão quando se fala de desenvolvimento de jogos por exemplo, não tenho experiência nesta área para dar meus pitacos, agora no mundo de aplicações corporativas o conselho do Knuth é lei.

  5. wrote:

    Nunca fui adepto de otimização prematura e sempre a favor do preceito “do the simplest thing that could possibly work”, ou seja, primeiramente, criar a base de código funcional e posteriormente refatorá-lo.

    Refactoring não somente em deixar o modelo implementado mais legível como também realizar algumas otimizações no código (partindo-se do fato de que já se foi levantando através de ferramentas adequadas quais os possíveis bottlenecks existentes e os pontos a serem atacados já foram demarcados).

    No início do projeto ainda se tem dúvidas a respeito do negócio ao qual o software vai atender, algo que vai se tornando maduro com o desenvolvimento do projeto. Portanto, é muito difícil prematuramente elocubrar todos os possíveis problemas de performance e necessidades de otimização que o software vai enfrentar durante seu desenvolvimento.

    Isso não tira o fato de que a arquitetura concebida para suportar o desenvolvimento das funcionalidades do sistema não deva ser flexível o suficiente para permitir tais otimizações durante o desenrolar do projeto. Afinal, ela deve ser robusta, manutenível e flexível para permitir a implementação de novas features e também a fácil correção de problemas, como os de necessidade de otimização citados aqui. Logo, a arquitetura deve ser orientada aos requisitos funcionais mas dar o devido suporte aos requisitos não-funcionais.

  6. wrote:

    Pelos comentarios, parece até que eu fiz a apologia da otimização prematura. Não fiz. Considero prejudicial. Mas concordo com o autor do texto quando ele diz que existem problemas que podem muito bem serem vislumbrados ANTES, com uma boa análise. Talvez sejam poucos. Mas notem que até o Knuth dá abertura pra isso falando que 97% dos problemas nao tem que ser otimizados prematuramente. Restam 3%…..

  7. wrote:

    Se restam só 3% então meu palpite é que estão todos na área de programação de jogos ;-)

    Agora sério, Knuth só não falou 100% para ser mais humilde.

  8. wrote:

    Logo, a arquitetura deve ser orientada aos requisitos funcionais mas dar o devido suporte aos requisitos não-funcionais.

    Falou bonito hein Rafael, hehe.

Leave Your Comment

blog comments powered by Disqus

Switch to our mobile site

 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org