A micro-otimização é importante na codificação?


178

Recentemente, fiz uma pergunta no Stack Overflow para descobrir por que o isset () era mais rápido que o strlen () no PHP . Isso levantou questões sobre a importância do código legível e se vale a pena considerar as melhorias no desempenho de microssegundos no código.

Meu pai é um programador aposentado e eu mostrei as respostas. Ele estava absolutamente certo de que, se um codificador não considera o desempenho em seu código, mesmo no nível micro, ele não é um bom programador.

Não tenho tanta certeza - talvez o aumento no poder da computação signifique que não precisamos mais considerar esse tipo de aprimoramento de micro-desempenho? Talvez esse tipo de consideração seja das pessoas que escrevem o código de idioma real? (do PHP no caso acima).

Os fatores ambientais podem ser importantes - a Internet consome 10% da energia do mundo. Eu me pergunto como são desperdiçados alguns microssegundos de código quando replicados trilhões de vezes em milhões de sites?

Eu gostaria de saber respostas de preferência com base em fatos sobre programação.

A micro-otimização é importante na codificação?

Meu resumo pessoal de 25 respostas, obrigado a todos.

Às vezes, precisamos nos preocupar realmente com micro-otimizações, mas apenas em circunstâncias muito raras. Confiabilidade e legibilidade são muito mais importantes na maioria dos casos. No entanto, considerar a micro-otimização de tempos em tempos não faz mal. Um entendimento básico pode nos ajudar a não fazer más escolhas óbvias ao codificar como

if (expensiveFunction() || counter < X)

Deveria estar

if (counter < X || expensiveFunction())

( Exemplo de @ zidarsk8 ) Essa poderia ser uma função barata e, portanto, alterar o código seria uma micro otimização. Mas, com um entendimento básico, você não precisaria, porque escreveria corretamente em primeiro lugar.


123
O conselho do seu pai está desatualizado . Eu não perguntaria o quanto isso melhora o desempenho. Eu perguntaria onde está o gargalo. Não importa se você melhora o desempenho de uma seção de código, se isso não faz diferença geral, seu link mais lento determinará a velocidade. No PHP, isso está gravando na rede (a menos que você possa provar o IE de outra forma); que se traduz em escrever um código mais legível é mais importante.
Martin York

61
Se a palavra-chave é considerada, ele não está errado. Você tem que ter alguma pista sobre isso.
JeffO 8/08

37
Fico triste porque a famosa citação Premature Optimization ainda não foi mencionada: "Os programadores perdem muito tempo pensando ou se preocupando com a velocidade de partes não críticas de seus programas, e essas tentativas de eficiência têm um forte impacto negativo. impacto quando a depuração e a manutenção são consideradas. Devemos esquecer as pequenas eficiências, digamos cerca de 97% das vezes: a otimização prematura é a raiz de todo mal . No entanto, não devemos desperdiçar nossas oportunidades nesses 3% críticos ".
Tamara Wijsman

13
Você pode fornecer uma fonte de "10% da energia do mundo"?
Michael Easter

17
coder does not consider performance in their code even at the micro level, they are not good programmersé muito diferente de otimizar. É apenas uma boa codificação.
Woliveirajr

Respostas:


90

Eu concordo e discordo de seu pai. O desempenho deve ser pensado cedo, mas a micro-otimização só deve ser pensada cedo se você realmente souber que uma porcentagem alta de tempo será gasta em pequenas seções de código ligadas à CPU.

O problema da micro-otimização é que isso geralmente é feito sem ter qualquer conceito de como os programas realmente passam mais tempo do que o necessário.

Esse conhecimento vem da experiência de ajustar o desempenho, como neste exemplo , no qual um programa aparentemente simples, sem ineficiências óbvias, é realizado através de uma série de etapas de diagnóstico e aceleração, até que seja 43 vezes mais rápido do que no início.

O que mostra é que você não pode realmente adivinhar ou intuir onde estarão os problemas. Se você realizar um diagnóstico, que no meu caso é uma pausa aleatória , as linhas de código responsáveis ​​por uma fração significativa do tempo são expostas preferencialmente. Se você olhar para eles, poderá encontrar um código substituto e, assim, reduzir o tempo total em aproximadamente essa fração.

Outras coisas que você não corrigiu ainda levam tanto tempo quanto antes, mas, como o tempo total foi reduzido, essas coisas agora ficam com uma fração maior; portanto, se você fizer tudo de novo, essa fração também poderá ser eliminada. Se você continuar fazendo isso em várias iterações, é assim que você pode obter acelerações maciças , sem necessariamente ter feito qualquer micro-otimização .

Após esse tipo de experiência, ao abordar novos problemas de programação, você começa a reconhecer as abordagens de design que inicialmente levam a essas ineficiências. Na minha experiência, isso provém do excesso de design da estrutura de dados, da estrutura de dados não normalizada, da dependência massiva de notificações, desse tipo de coisa.


120

Micro-otimização é importante apenas se os números dizem que é.

Os requisitos contra os quais você está desenvolvendo devem ter alguma especificação de dados de desempenho, se o desempenho for um problema para o cliente ou usuário. Ao desenvolver software, você deve testar o desempenho do seu sistema em relação a esses requisitos. Se você não estiver atendendo aos requisitos de desempenho, precisará criar um perfil de sua base de códigos e otimizar conforme necessário para atingir os requisitos de desempenho. Quando você estiver com o desempenho mínimo exigido, não há necessidade de diminuir o desempenho do sistema, especialmente se você comprometer mais a legibilidade e a manutenção do código (na minha experiência, o código altamente otimizado é menos legível e sustentável, mas nem sempre). Se você pode obter ganhos adicionais de desempenho sem degradar os outros atributos de qualidade do sistema,

No entanto, há casos em que o desempenho é da maior importância. Estou pensando principalmente em sistemas em tempo real e sistemas embarcados. Em sistemas em tempo real, alterar a ordem das operações pode ter um efeito enorme no cumprimento dos prazos rígidos necessários para a operação adequada, talvez até influenciando os resultados dos cálculos. Em sistemas embarcados, você normalmente possui memória, potência da CPU e energia limitadas (como na energia da bateria), portanto, é necessário reduzir o tamanho dos binários e o número de cálculos para maximizar a vida do sistema.


Por outro lado, se houver um problema entre o uso de uma função mais lenta e mais rápida, não há razão para usar a função mais lenta - como aqui no caso do isset.
Mavrik

7
@Mavrik Isso é verdade. Se você tiver duas funções, X e Y, e Y for mais rápido que X (pelo menos para suas condições particulares), não há razão para não usar Y, se o código ainda estiver legível e com manutenção. Mas se você não conhece Y e precisa refatorar o código para usar Y em vez de X, e o desempenho (desse segmento de código) não é um problema, não há razão para fazer essa alteração. Trata-se de compensações - desempenho, tempo, custo, esforço, legibilidade / manutenção e assim por diante.
Thomas Owens

2
Eu concordo plenamente, eu só queria fazer esse ponto quando se trata de micro-otimização - se não lhe custa nada em termos de legibilidade / tempo, faça-o. Caso contrário, não.
Mavrik

O código altamente otimizado com +1 é menos legível e de manutenção ... mas nem sempre.
Boz

Mais casos em que o desempenho é importante: (1) jogos; (2) grandes quantidades de dados; (3) site de alto tráfego; (4) capacidade de resposta de uma interface do usuário altamente complexa; (5) serviço que deveria ser executado em segundo plano como verificação de vírus; (6) finanças; (7) smartphone; e assim por diante. Dificilmente se limita a casos esotéricos como RTS e sistemas embarcados.
Rex Kerr #

103

Sempre que alguém pergunta sobre otimização , lembro-me da citação de Michael A. Jackson

A primeira regra de otimização de programa: não faça isso.

A Segunda Regra da Otimização de Programas (somente para especialistas!): Não faça isso ainda .

Citação da Wikipedia corrigida para inglês britânico. * 8 ')

Implícito na segunda regra é criar um perfil do seu código e gastar apenas tempo otimizando coisas que farão a diferença.

Ao programar em montagem, a afirmação de seu pai estava correta. Mas isso é muito mais próximo do metal do que a maioria das pessoas programa atualmente. Hoje, mesmo a tentativa de otimizar a si mesmo (sem criação de perfil) pode resultar em uma execução mais lenta do código do que se você tivesse feito algo da maneira mais comum, pois é mais provável que a maneira comum seja otimizada pelos compiladores JIT modernos .

Mesmo em C, você precisa ser muito bom em otimização para saber mais sobre como otimizar uma seção de código do que o compilador.

Se você não está familiarizado com muito do que Ulrich Drepper fala em seu excelente artigo O que todo programador deve saber sobre memória , provavelmente está perdendo, mesmo tentando otimizar a si mesmo. Porém, ao contrário do título dos trabalhos (que na verdade é uma homenagem à igualmente fantástica O que todo cientista da computação deve saber sobre aritmética de ponto flutuante ) não ter esse nível de entendimento não o impede necessariamente de ser um bom programador, apenas um tipo diferente de programador.

isset()vs. strlen()em PHP

Eu não sei PHP, então realmente não é óbvio o que isset()se deve fazer. Posso inferir isso a partir do contexto, mas isso significa que será igualmente obscuro para programadores PHP iniciantes e pode até fazer com que programadores mais experientes dêem uma olhada dupla. Esse é o tipo de uso idiomático de uma linguagem que pode tornar a manutenção um pesadelo.

Não apenas isso, mas não há garantia de que isset()sempre será mais eficiente, apenas porque é mais eficiente agora. Uma otimização agora pode não ser uma otimização no próximo ano ou em 10 anos. CPUs, sistemas, compiladores melhoram e mudam com o tempo. Se o desempenho do PHP strlen()for um problema, o PHP poderá ser modificado no futuro, então todas as otimizações isset () podem precisar ser removidas para otimizar o código mais uma vez.

Toda otimização tem o potencial de se tornar uma anti-otimização futura ; portanto, deve ser considerado um possível odor de código, a ser mantido no mínimo.

Um exemplo da experiência pessoal

Como exemplo dessa anti-otimização , uma vez eu tive que higienizar uma enorme base de código cheia de código do formulário, if x==0 z=0 else z=x*yporque alguém assumiu que um ponto flutuante multiplicado sempre seria mais caro que um ramo. Na arquitetura de destino original, essa otimização fez o código executar uma ordem de magnitude mais rápido, mas os tempos mudam.

Quando tentamos usar esse código em uma CPU mais moderna, com alto fluxo de pipeline, o desempenho foi horrivelmente ruim - cada uma dessas instruções causa uma descarga de pipeline. Simplificar todas essas linhas de código para que z=x*yo programa execute uma ordem de magnitude mais rapidamente na nova arquitetura, restaurando o desempenho perdido pela anti-otimização .

Os problemas que normalmente temos que otimizar para hoje são muito diferentes daqueles que tivemos que otimizar há 20 ou 10 anos atrás.

Então nos preocupamos em fazer o máximo de trabalho por ciclo de clock, agora é mais provável que nos preocupemos com liberações de pipeline, previsões incorretas de ramificações e falhas de cache no nível da CPU, mas os bloqueios e a comunicação entre processos estão se tornando muito mais significativos à medida que avançamos para o multi- arquiteturas de processo e multiprocessador. O artigo de Drepper pode realmente ajudar a entender muitas dessas questões.


3
Descarga de fluxo e cache do pipeline é o que você deseja evitar: D Eles têm custos horríveis. mas apenas em partes do código que os excutam muitas, muitas, muitas e muitas vezes.
Deadalnix

7
Uma coisa que eu acrescentaria é que os compiladores percorreram um longo caminho e otimizarão muitas coisas para você. AFAIK, eles otimizam melhor o código limpo e legível do que as coisas complicadas.
Becuzz

3
+1 por fornecer um exemplo real de uma micro-otimização que desperdiçou tempo - e por revelar que Michael Jackson era um programador.
Boz

1
+1 Para o exemplo. Ilustra perfeitamente por que você deve deixar transformações triviais no compilador.
Aug2

1
@Rex Kerr> no exemplo, o custo vem da ramificação, que causa a descarga do pipeline da CPU. A multiplicação de ponto flutuante também é cara. O que é mais caro depende muito do FPU e do comprimento do pipeline da CPU executando o código. Eu não ficaria surpreso que esse código tenha sido executado mais rapidamente na CPU mais antiga, com pipeline mais curto e FPU menos eficiente do que a CPU atual.
deadalnix

84
  1. Escreva um código limpo, conciso, simples e auto-explicativo.
  2. Faça testes de desempenho para identificar gargalos.
  3. Otimize seções críticas.

Como regra geral: 95% do seu código é executado 5% do tempo. Não há sentido em otimizar antes de criar um perfil / comparar o seu código e ver quais são os 5% que são executados 95% das vezes.

Todo idiota pode fazer micro-otimização e qualquer compilador / tempo de execução decente fará isso por você.
A otimização do bom código é trivial. Escrever código otimizado e tentar torná-lo bom depois disso é tedioso na melhor das hipóteses e insustentável na pior.

Se você se preocupa seriamente com desempenho, não use PHP para código crítico de desempenho. Encontre os gargalos e reescreva-os com extensões C. Mesmo otimizar seu código PHP além do ponto ofuscante, você não terá tanta velocidade.

Pessoalmente, gostei muito da micro-otimização quando comecei a programar. Porque é óbvio. Porque recompensa você rapidamente. Porque você não precisa tomar decisões importantes. É o meio perfeito de procrastinação. Permite fugir das partes realmente importantes do desenvolvimento de software: o design de sistemas escaláveis, flexíveis, extensíveis e robustos.


2
A melhor resposta para mim foi encontrada, notavelmente, no Bugzilla Developer's Guide: "Se você está tentando ser inteligente, em vez de ser legível, talvez esteja tentando tornar as coisas" mais rápidas? ". Se sim, lembre-se : não resolva um problema antes de saber que ele existe.Se você não sabe (por testes reais e detalhados) que seu código é lento, não se preocupe em torná-lo "mais rápido". Isso não se limita apenas a otimização - muitos programadores estão constantemente resolvendo problemas que ninguém jamais experimentou. Não faça isso. " bugzilla.org/docs/developer.html#general
Marco

7
Eu geralmente concordo - exceto por uma linha, eu afirmo que "todo idiota pensa que pode otimizar micro" ...;) #
Nim

@Nim: Point taken;)
back2dos

26

Eu concordaria com seu pai: "Se um codificador não considera o desempenho em seu código, mesmo no nível micro, ele não é um bom programador". A chave é "considerar o desempenho". Isso não é equivalente a "fazer micro-otimizações a cada passo".

Concordo com a maioria dos outros comentários - o que costumava tornar os programas C mais rápidos hoje em dia - mas há outras coisas sérias a serem consideradas: Devo usar C ou C ++? Classes com operadores sobrecarregados simples podem prejudicar o desempenho se você as usar muito. Isso importa? Depende da sua aplicação, mas se você nem considerar, você não é um bom programador. Algumas pessoas podem considerá-lo por cerca de 2 milissegundos e descartá-lo, mas acho que muitos literalmente nem o consideram.

A realidade é que, com a otimização, o código pode ficar mais difícil de ler. O código levará mais tempo para escrever. O código estará entre um pouco mais rápido e uma ordem de magnitude mais rápida (isso é raro). Seus clientes provavelmente não saberão a diferença.

Outra realidade é que as pessoas gostam de reutilizar código, e onde ele acaba pode ser bem diferente do que quando você o escreveu. De repente, as pessoas podem se importar.

Como exemplo, digamos que você escreveu algo como Angry Birds em um PC ou em um console de jogos. Você desconsiderou a otimização em seu sistema de física e em seu sistema gráfico - porque os núcleos duplos de 2,5 GHz são basicamente o mínimo hoje em dia, e seu jogo funciona suficientemente bem. Em seguida, os telefones inteligentes aparecem e você deseja portá-lo. Oh caramba, um núcleo ARM de 600 MHz ?

Pense em um site - algo reunido em um fim de semana como Hot or Not . Você usa qualquer banco de dados útil, escreve tudo com o desenvolvimento rápido em mente, iniciando enviando um URL para seus amigos. Três meses depois, seu servidor está morrendo de sobrecarga e não há nada que você possa fazer para aumentar a escala. Isso acontece o tempo todo. Os maiores sites têm contas de energia medidas em centenas de quilowatts ou mesmo megawatts. Pense nisso: existem megawatts a serem salvos por meio da otimização de código.

Como seu pai disse, você deve pelo menos considerar . A maioria das pessoas nem sabe quanto desempenho está em cima da mesa e o encobre com uma rápida piada sobre "otimização prematura" e "não faça". Estes não são bons programadores.

Esta não é uma opinião popular sobre esses sites. Tchau, pontos de reputação ....


3
Claro, você deve considerá-lo (na parte de trás da sua cabeça) e tipicamente rejeitá-lo, a menos que se mostre que vale a pena. Você precisa considerar que as otimizações geralmente diminuem a legibilidade do código e podem aumentar o tempo necessário para codificar e manter um fator de 10 ou mais. Se o programa não consome muita CPU, geralmente não é necessário. Reconheça que seu compilador geralmente é muito melhor em otimização do que você e que muitas de suas otimizações realmente prejudicam o desempenho. Se não vale a pena testar suas otimizações e perfil, não vale a pena otimizar.
precisa saber é o seguinte

3
Seu exemplo do Angry Birds mostra exatamente por que você não deve otimizar prematuramente. Ao migrar do desktop para o console e para o (s) dispositivo (s) móvel (s), você está lidando com (pelo menos) três tipos muito diferentes de hardware e otimização para um pode prejudicar, em vez de ajudar o outro. Pior ainda, otimizar tornará o código mais difícil de entender e, portanto, mais difícil de portar. Claro, escolha algoritmos eficientes desde o início, mas salve a micro-otimização para a fase de ajuste de desempenho quando dados reais indicarem onde está o problema em cada plataforma.
Caleb

@Caleb: O exemplo do Angry Birds ilustra por que não otimizar para um hardware específico. Também ilustra como você pode criar um aplicativo inteiro sem se preocupar em fazer otimizações mais gerais do "nível C" e depois se queimar. Na verdade, não queimado, mas tendo problemas para ir além da sua intenção original.
phkahler

25

Vamos primeiro considerar o seu caso: PHP

  • Não acho que o PHP seja um tipo de linguagem (por causa de sua natureza e seu principal domínio de aplicação) que você precisa se preocupar com essas "micro-otimizações". O código PHP é otimizado principalmente com o cache do opcode.
  • Os programas escritos em PHP não têm limite de CPU, são principalmente de E / S , portanto, essas otimizações não valerão o seu tempo.
  • Qualquer coisa que você DEVE otimizar provavelmente deve ser inserida em uma extensão C e carregada dinamicamente no tempo de execução do PHP
  • Então, como você pode ver, não temos incentivo para otimizar nosso código em PHP - por outro lado, se você gastar esse tempo para tornar o código PHP mais legível e sustentável -, isso pagará mais dividendos.

Em geral,

Eu não gastaria muito tempo "TOOOOO" otimizando meu código em uma linguagem dinâmica como Python ou Ruby - porque eles NÃO foram projetados para tarefas de processamento de números intensivos da CPU. Eles resolvem diferentes classes de problemas em que modelar uma situação do mundo real de maneira elaborada (que é fácil de ler e manter) - que é chamada de expressividade - é mais importante que a velocidade. Se a velocidade fosse a principal preocupação, eles não seriam dinâmicos em primeiro lugar.

Para programas compilados (C ++, Java), a otimização é mais crucial. Mas também é preciso primeiro examinar a natureza / domínio / objetivo do programa que você está escrevendo. Você também deve ponderar cuidadosamente o tempo para otimizar com os ganhos dessa otimização. Se você precisar de mais otimização, considere dar um passo para baixo - e codifique essas partes do seu código no assembler.

Portanto, para responder à sua pergunta original - "A micro-otimização é importante ao codificar?" - a resposta é - DEPENDE -

  • Que tipo de coisa você está fazendo: domínio de aplicativo, complexidade?
  • As melhorias de velocidade em microssegundos REALMENTE são importantes para o seu programa?
  • Que tipo de otimização será mais lucrativa? Pode não ser sempre a otimização do código, mas algo externo.
  • Quanta "bondade" (em termos de velocidade) você está colhendo no tempo em que investe na otimização micro?
  • É possível obter velocidades melhores de outras maneiras - alterando o hardware, a RAM e o processador, executando o código paralelamente ou em um sistema distribuído?

Além de consumir muito tempo, a micro-otimização (otimização de código) também "distorce" a legibilidade natural do seu código, tornando-o pesado em manutenção. Sempre considere o último recurso - tente sempre otimizar todo o aplicativo adotando hardware e arquitetura melhores do que otimizar arquivos de código individuais.


18

Parece haver muitas respostas que dizem que a micro otimização é

tudo sobre tradeoffs - desempenho, tempo, custo, esforço, legibilidade / manutenção e assim por diante.

Mas bem, eu sei que existem algumas otimizações em que não há impacto na legibilidade, e eu apenas gosto de fazer isso por diversão. Vi em algumas de minhas tarefas escolares (todas baseadas na velocidade) que sempre é bom considerar a micro otimização ao escrever declarações condicionais como:

if (counter < X && shouldDoThis()) // shouldDoThis() is an expensive function

é sempre melhor do que

if (shouldDoThis() && counter < X ) 

Existem algumas maneiras de "acelerar" seu código dessa maneira e a diferença geralmente é insignificante (nem sempre), mas me sinto melhor se escrever dessa maneira.

Não sei se alguém considera isso como uma otimização, mas acho que um programador deve saber e considerar essas coisas ao escrever seu código.


2
Pode não ser importante para este caso em particular . No entanto, acho que é muito importante poder reconhecer otimizações como essas para que, quando isso for importante, você não precise gastar tempo desnecessário criando perfis e otimizando após o fato.
tskuzzy

4
Este é um exemplo muito perigoso . Uma otimização nunca deve mudar o comportamento . Mesmo sugerindo que isso cheap() && expensive()é uma otimização, expensive () && cheap()convida as pessoas a substituírem cegamente uma pela outra, sem levar em consideração a significativa mudança semântica que ela cria (em idiomas onde &&é o operador de curto-circuito).
Mark Booth

5
Se as funções não tiverem efeitos colaterais, elas são equivalentes e uma é mais rápida. Se eles tiverem efeitos colaterais, não se deve escrever o código dessa maneira em primeiro lugar. Eu diria até que este é um procedimento que deve ser feito por hábito - a menos que realmente mude o comportamento.
phkahler

3
@ MarkBooth Eu tenho que concordar com a phkahler aqui, nenhuma dessas funções deve ter efeitos colaterais! A ordem dos condionos em uma declaração if não deve afetar o resultado do programa. Meu exemplo seria melhor escrito como if (x<100 && isPrime(x)), apenas para deixar mais claro.
Zidarsk8

1
@ zidarsk8 - Se uma otimização muda algo diferente da velocidade de execução , não é uma otimização . Como programadores, geralmente precisamos ser pragmáticos , e às vezes isso significa que não podemos garantir que todas as funções usadas com um operador de curto-circuito sejam puras - especialmente quando nosso código chama bibliotecas de terceiros sobre as quais não temos controle. Nessa situação, você deve ter cuidado para que programadores inexperientes não sejam incentivados a introduzir bugs em nome da otimização .
21412 Mark Booth

11

No início de minha carreira, declarações abrangentes como "não otimizar micro" levaram a muita confusão. Tudo é circunstancial; portanto, a razão pela qual as pessoas dizem "melhor prática" em vez de "fazer isso".

A "melhor prática" é a melhor opção, considerando todas as circunstâncias. Por exemplo, LINQ e Entity Framework devem ser usados ​​no lugar de SQL embutido. Na minha empresa, estamos no SQL Server 2000 . O SQL Server 2000 não oferece suporte ao Entity Framework. As melhores práticas exigem:

  • Vendendo meu chefe com a idéia de comprar uma nova versão do SQL Server, o que significa vários milhares de dólares.
  • Venda de desenvolvedores com a idéia de aprender novas tecnologias.

Sei por experiência própria que isso não vai acontecer. Então, eu poderia sair, insistir sem fim ou não seguir as melhores práticas.

Há considerações políticas, técnicas e monetárias por trás das decisões que afetam o resultado geral. Lembre-se desse fato ao tomar uma decisão e escolha suas batalhas com sabedoria.

" Para tudo, há uma estação, um tempo para todas as atividades sob o céu " .


1
BTW, você pode usar o Dapper como uma alternativa de micro-ORM para SQL embutido.
Dan

2
LINQ and Entity Framework should be used in lieu of inline SQL- Até que você realmente precise do SQL embutido para otimizar alguma coisa; o SQL que a EF produz nem sempre é ideal.
Robert Harvey

1
fwiw, se seu chefe está preocupado com os custos de licenciamento do SQL 2k8 (ou o que quer que seja que esteja atual), você deve salientar que ele tem idade suficiente para entrar no EOL muito em breve (se ainda não estiver)
warren

@warren - Algumas empresas não levam essas coisas em consideração. Para alguns, se ainda "funcionar", eles não serão atualizados. Por trabalho, quero dizer que o servidor ainda roda. Já vemos falta de apoio da EF. Isso simplesmente não é suficiente para convencê-los a gastar algum dinheiro.
precisa saber é o seguinte

1
Para que você saiba, você pode usar o EF com o SQL 2000. O designer não funciona, mas a estrutura real da entidade suporta o SQL 2000. Para contornar a limitação do designer, você pode criar um banco de dados local no sql 2008 express com o mesmo esquema como o banco de dados sql 2000, aponte o designer para isso para gerar todas as classes, vá para o arquivo .edmx e altere a versão do banco de dados de destino para 2000 e aponte a cadeia de conexão para o banco de dados do sql server 2000. Não é a melhor solução, mas se você não pode atualizar, ele funciona.
Neil

8

Isso é sempre uma troca.

Primeiro, a indústria de computadores trata de dinheiro no final. O que você precisa fazer como desenvolvedor é gerar valor para o cliente para obter dinheiro (isso é uma simplificação excessiva, mas o ponto principal está aqui).

O tempo do desenvolvedor custa dinheiro. A energia da máquina também custa dinheiro. Normalmente, esse segundo custo é bem menor que o primeiro. Portanto, é importante ter um código legível e código de manutenção, para que o desenvolvedor possa passar a maior parte do tempo agregando valor.

A micro-otimização pode, em alguns casos, ser importante. Mas eles geralmente envolvem código menos legível ou código menos extensível (esse não é o caso do seu exemplo vinculado, mas, em geral, é). Isso vai custar em algum momento do desenvolvedor. Desta vez, sendo mais caro que a energia da máquina, isso é um desperdício.

Segundo, a micro-otimização em um grande projeto pode tornar cada vez mais difícil manter / evoluir. O problema disso é que, ao evoluir, pode ser impossível fazer outra otimização. Com um aplicativo em evolução, você normalmente acaba com uma solução mais lenta do que você teria sem fazer essas otimizações.

Terceiro, a otimização é muitas vezes irrelevante, pois a complexidade do algoritmo geralmente supera qualquer micro-otimização que você poderia ter feito se o conjunto de dados crescer. Infelizmente, como a micro-otimização torna seu código mais difícil de manter / evoluir, essa otimização pode ser mais difícil de fazer.

Em algum momento, o valor está nessa otimização (pense em programas críticos de latência, como em videogames ou no piloto automático de uma aeronave). Mas isso tem que ser demonstrado. Normalmente, seu programa passa a maior parte do tempo em uma parte limitada do código. Seja qual for a micro-otimização que você faz, você nunca terá seus programas com valor mais rápido sem identificar o gargalo e trabalhar nessa parte.

Ao fazer sua pergunta, você mostrou que não comparou o problema em um programa real. Nesse caso, você poderia fazer o truque e perceber se era mais rápido ou não. Então você estava perguntando isso antes de ter qualquer problema. É aqui que está o problema. Você estava lidando com o problema de otimização da maneira errada.

Como a manutenção e a evolução são geralmente mais valiosas que a micro-otimização, certifique-se de ter a interface certa antes de fazer qualquer. Então, se partes do seu programa são abstratas o suficiente uma para a outra, você pode otimizar uma micro sem estragar tudo. Isso requer que sua interface esteja em execução por tempo suficiente para ser confiável.


"Sempre existe uma troca". É verdade que reduzir uma variável aumentará a outra, se o programa estiver na curva de troca . Na minha experiência, a maioria dos programas não está nem perto da curva de troca e tem muito espaço para as duas variáveis ​​serem reduzidas.
Mike Dunlavey

A manutenção e a evolução +1 são mais valiosas que a micro otimização. Embora eu tenha certeza de que a indústria de computadores é mais do que apenas dinheiro? Por exemplo, código aberto, educação, inovação, governança, comunidade etc. Tenho certeza de que o dinheiro pode ser encontrado na raiz, mas isso é verdade para a maioria das coisas.
Boz

@Boz kay> Isso é parcialmente verdade. Primeiro, porque seu chefe e cliente geralmente não sabem nada sobre isso e se preocupam com dinheiro. Se você deseja promover algumas ferramentas de código aberto, precisa dizer a elas como isso melhorará a marca da empresa ou como reduzirá os custos de desenvolvimento. Além disso, tornar os desenvolvedores felizes é uma maneira de obter bons desenvolvedores em sua empresa. Um bom desenvolvedor ganha dinheiro (principalmente lance qualidade e inovação). No final, o dinheiro é a chave. E eu estou escrevendo isso no meu computador linux, criando um ótimo suporte para software livre. O mesmo vale para a educação.
Deadalnix

8

O desempenho é um recurso

O artigo de Jeff Atwood é excelente para criar um site de alto desempenho e a importância de fazê-lo ...

Dito isto, não se concentre na micro-otimização até que você precise. Há uma otimização mais econômica que você pode executar. Concentre-se na arquitetura, não no código. A maioria dos sites que vi com desempenho lento apresentava problemas de alto nível (camada desnecessária de serviços da web, design de banco de dados ruim, arquiteturas excessivamente complicadas) que não apenas afetavam adversamente o desempenho, mas estavam profundamente arraigados e difíceis de corrigir.

Ao criar um site, o código do lado do cliente e a lógica do banco de dados têm muito mais probabilidade de causar problemas de desempenho do que o código do lado do servidor. Como qualquer outra coisa, se você tiver problemas de desempenho, saberá ainda melhor o perfil do seu código e poderá encontrá-los logo no início.


7

O tempo do desenvolvedor custa mais que o tempo do computador. Geralmente, é isso que você deseja otimizar. Mas:

  • Há uma diferença entre micro-otimização e complexidade algorítmica. Gaste tempo suficiente para ter certeza de que está usando o algoritmo certo .
  • Verifique se você está fazendo a pergunta certa, select (select count(*) from foo) >= 1não é a mesma coisa que select exists(select 1 from foo).
  • alguns idiomas de idioma são populares simplesmente porque são mais rápidos. Não há problema em usá-los, pois a maioria dos usuários fluentes do idioma os conhece. (seu exemplo é um bom exemplo).

7

O que você deseja otimizar?

  • Desempenho de software?
  • Confiabilidade?
  • Produtividade do programador?
  • Satisfação do cliente?
  • Eficiência energética?
  • Manutenção?
  • Tempo para o mercado?
  • Custo?

"Otimizar" nem sempre significa fazer com que o código seja executado o mais rápido possível. Há momentos em que é importante encontrar a maneira mais rápida de fazer algo, mas isso não é tão comum na maioria dos códigos. Se os usuários não perceberem a diferença entre 50 e 100 microssegundos, não há efetivamente nenhuma diferença entre os dois no código que será executado apenas ocasionalmente. Aqui está um exemplo:

Se você precisar atualizar continuamente uma exibição da duração da entrada do usuário e da quantidade de tempo que leva para uma das duas rotinas para determinar que a duração é muito menor que o tempo entre dois pressionamentos de tecla consecutivos, realmente não importa qual rotina você usa. Por outro lado, se você precisar determinar o tamanho de um bilhão de strings, provavelmente desejará prestar muita atenção às diferenças de desempenho entre diferentes rotinas. No primeiro caso, você pode preferir escrever um código fácil de entender e verificar; no segundo caso, você pode estar disposto a trocar legibilidade por velocidade.

De qualquer forma, se você deseja otimizar seu código, analise seu código antes e depois das alterações que você fizer. Hoje em dia, os programas são complicados o suficiente para que seja difícil dizer onde estão os gargalos; a criação de perfil ajuda a otimizar o código certo e depois mostra que as otimizações que você fez realmente funcionaram.

Você não disse quando seu pai se aposentou ou que tipo de programação ele fez, mas a reação dele não é surpreendente. Historicamente, memória, armazenamento secundário e tempo de computação eram todos caros e, às vezes, muito caros. Hoje em dia, todas essas coisas se tornaram muito baratas em comparação ao tempo do programador. Ao mesmo tempo, processadores e compiladores tornaram-se capazes de otimizar o código de maneiras que os programadores nunca poderiam corresponder. Os dias em que os programadores usam pequenos truques para incluir algumas instruções da máquina aqui e ali desaparecem.


1
+1 Sem mencionar que nos últimos anos, os dispositivos móveis tornaram-se novamente altamente dependentes da otimização de código. Alguém que não escreve código otimizado ou pelo menos considera que pode ter dificuldade em fazer com que o aplicativo intensivo de CPU seja executado sem problemas em um dispositivo móvel.
Styler

+1 é muito parecido com a sua lista de possíveis otimizações. Ele usou assembly / fortran
Boz

@ Style: não demoraria muito até que os dispositivos móveis tivessem CPU quad core com GBs de memória, já possuímos smartphones dual core.
Lie Ryan

@Lie Ryan: Sim isso é verdade, mas como a maioria dos pioneiros tiveram que viajar em barcos de madeira;)
Styler

7

Não é importante otimizar ao escrever o código. A otimização deve ser feita com a ajuda de um criador de perfil, otimizando o código onde for importante.

NO ENTANTO , um programador deve tentar evitar coisas obviamente estúpidas enquanto escreve o código.

Por exemplo, não faça operações caras repetidas dentro de um loop. Armazene o valor em uma variável fora do loop e use-o. Não faça coisas como comparações de strings ou regex repetidamente em uma função frequentemente chamada, quando você puder subir um nível, fazer a comparação e transformá-la em um número inteiro, uma referência de função ou uma classe derivada.

Essas coisas são fáceis para um programador experiente lembrar e quase sempre melhoram a qualidade do código.


Percebi que precisava ser mais claro na edição da minha pergunta, estava dizendo a mesma coisa - atualizei-a.
Boz

7

Ao decidir o que otimizar, lembre-se sempre da lei de Amdahl . Veja o link para matemática precisa; a declaração concisa a lembrar é:

Se uma parte do seu programa responder por 10% do tempo de execução, e você a otimizar para executar duas vezes mais rápido, o programa como um todo acelerará apenas 5%.

É por isso que as pessoas sempre dizem que não vale a pena otimizar partes do seu programa que não ocupam mais do que alguns por cento do tempo de execução total. Mas esse é apenas um caso especial de um princípio mais geral. A lei da Amdahl diz que, se você precisar executar o programa inteiro duas vezes mais rápido, precisará acelerar cada peça em média 50%. Ele informa que, se você precisar processar vinte gigabytes de dados, existem apenas duas maneiras de fazê-lo ir mais rápido do que o tempo necessário para ler vinte gigabytes do disco: obtenha um disco mais rápido ou reduza os dados.

Então, o que a lei de Amdahl diz sobre micro-otimizações? Diz que talvez valham a pena se aplicar de maneira geral. Se você pode economizar um por cento do tempo de execução de todas as funções do seu programa, parabéns! Você acelerou o programa em um por cento. Valeu a pena fazer isso? Bem, como um compilador, eu ficaria encantado em encontrar uma otimização que fizesse isso, mas se você estiver fazendo isso manualmente, diria que procure algo maior.


1
+1 para a cotação da Amdahl, mas não concordo com "para fazer com que o programa inteiro seja executado duas vezes mais rápido, você precisa acelerar cada peça". Eu diria que você não acelera nenhuma "peça". Em vez disso, você encontra trabalho desnecessário e o elimina. Especialmente chamadas de função, se o programa for maior que um brinquedo. Muito do pensamento comum sobre desempenho parece ignorar completamente a importância de encontrar ramificações desnecessárias inteiras da árvore de chamadas (que podem ser instruções únicas) e eliminá-las.
precisa saber é o seguinte

O diabo está na palavra "média" lá. É matematicamente o caso de que para acelerar um programa em 50%, cada peça deve ser acelerada em 50%, em média . Agora, se você pode dividir o programa em um trabalho que consome 75% do tempo de execução e outro que consome 25% e acelerar o primeiro em 3x, isso lhe dará 50% no total, apesar de não ter feito nada no último trabalho. Mas o caso muito mais comum é que existem dezenas de "trabalhos", cada um com menos de 5% do tempo de execução - e então você precisa acelerar ou se livrar de muitos deles.
zwol 9/08/11

Eu acho que há um caso ainda mais comum. Há um "trabalho" que leva 50% do tempo, mas você realmente não precisa dele ; portanto, remova-o completamente, reduzindo o tempo total nessa quantidade e repita. Eu sei que isso é difícil de aceitar - que os programas podem estar gastando grandes frações de tempo fazendo coisas que (em retrospectiva) são totalmente desnecessárias. Mas aqui está o meu exemplo canônico .
Mike Dunlavey

6

Depende do estágio de desenvolvimento em que você está, ao começar a escrever algo inicialmente, as micro-otimizações não devem ser levadas em consideração, pois você obterá mais ganhos de desempenho usando bons algoritmos do que as micro otimizações. Além disso, considere o que você está desenvolvendo, pois os aplicativos sensíveis ao tempo terão mais benefícios das considerações de micro otimização do que os aplicativos comerciais genéricos.

Se você estiver testando e ampliando o software, as micro-otimizações provavelmente o prejudicarão, pois tendem a dificultar a leitura do código e até a introduzir seu próprio conjunto exclusivo de bugs que precisam ser corrigidos, juntamente com qualquer outra coisa que precise ser corrigida.

Se você está realmente recebendo reclamações dos usuários sobre código lento, vale a pena considerar, mas apenas se tudo o mais tiver sido resolvido, a saber:

  • O código está bem escrito?
  • O aplicativo pode acessar seus dados sem problemas?
  • Um algoritmo melhor pode ser usado?

Se todas essas perguntas tiverem sido respondidas e você ainda estiver com problemas de desempenho, talvez seja hora de começar a usar micro-otimizações no código, mas é provável que outras alterações (ou seja, melhor código, melhor algoritmo, etc.) irão lhe render mais um ganho de desempenho do que uma micro-otimização.


5

A velocidade de execução é um dos muitos fatores que contribuem para a qualidade de um programa. Muitas vezes, a velocidade tem uma correlação inversa com a legibilidade / manutenção. Em quase todos os casos, o código deve ser legível por humanos, para que possa ser mantido. O único momento em que a legibilidade pode ser comprometida é quando a velocidade é um requisito essencial. O requisito de tornar o código mais rápido do que a capacidade de legibilidade / capacidade de manutenção total quase nunca é aplicável, mas há certos casos em que isso ocorre. O principal a lembrar é que o código micro-otimizado geralmente é código hacky; portanto, a menos que haja um requisito definido em algum lugar, é quase sempre a maneira errada de resolver o problema. Por exemplo, o usuário quase nunca notará a diferença entre os tempos de execução de 0,5 segundo e 1 segundo nas operações CRUD, portanto, você não precisa entrar em um assembly-interop-hackfest para chegar a 0,5 segundos. Sim, eu poderia pilotar um helicóptero para trabalhar e seria 10 vezes mais rápido, mas não o faço pelo preço e pelo fato de o helicóptero ser muito mais difícil de pilotar.Quando você otimiza o código desnecessariamente, é exatamente isso que você está fazendo: adicionando complexidade e custo desnecessários para alcançar uma meta supérflua.


5

A micro otimização é importante quando você atinge uma restrição. O que lhe interessa pode ser a memória, a taxa de transferência, a latência ou o consumo de energia. Observe que essas são características no nível do sistema; você não precisa (e não pode) otimizar todas as funções de todas as maneiras.

É mais provável que os sistemas embarcados precisem de micro-otimização porque as restrições são atingidas com mais facilidade. No entanto, até mesmo a micro-otimização apenas leva você até agora; você não pode otimizar sua maneira de sair de um design ruim. O ponto sobre o bom design em um sistema é que você pode raciocinar sobre o sistema como um todo. Os componentes que precisam de micro otimização devem ser perfeitamente expostos e otimizados de uma maneira que não comprometa o design do sistema.

Observe que os pequenos sistemas "incorporados" hoje em dia podem estar bem próximos dos Vaxen ou PDP-11 do passado, portanto esses problemas costumavam ser mais comuns. Em um sistema moderno de uso geral que executa computação comercial geral moderna, a micro-otimização é rara. Provavelmente, isso é parte do motivo pelo qual seu pai assume a posição que ele faz.

No entanto, não importa se você está lidando com nanossegundos, milissegundos, segundos ou horas; os problemas são os mesmos. Eles precisam ser avaliados no contexto do sistema e no que você está tentando alcançar.

Este é um exemplo de uma pergunta recente que respondi no Stack Overflow para um caso em que a micro-otimização era necessária: codificadores de vídeo de código aberto para um sistema incorporado .


4

O maior problema com a micro-otimização é que ele leva a escrever um código mais difícil de manter.

Outro problema é que, dependendo da configuração do computador, às vezes sua micro-otimização pode ter um desempenho pior do que sem a 'otimização'.

Fazer muitas micro-otimizações consumirá muito tempo lutando contra algo que realmente não importa.

Uma abordagem melhor é tornar um código mais limpo, mais fácil de manter e, se você tiver problemas de desempenho, execute um perfil para descobrir o que realmente está tornando seu código lento. E sabendo exatamente o que é realmente ruim, você pode corrigi-lo.

Não estou dizendo que não fazer micro-otimizações é desculpa para escrever código estúpido.


4

Se você começar a se preocupar com milissegundos, considere desistir do PHP e usar C ou Assembly. Não que eu queira fazer isso, não faz sentido discutir esses números e usar uma linguagem de script. Seu código interage com esse comando com frequência?

Os fatores ambientais estão fora de questão aqui, esses servidores são executados 24 horas por dia, sete dias por semana, e se eles realmente processam algo, isso só importa se for realmente uma tarefa em execução por um período muito longo.

Provavelmente, a luz do seu escritório e a energia que nossos computadores usaram enquanto todos digitamos perguntas e respostas, gastaram muito mais energia do que qualquer tipo de micro otimização que você possa aplicar razoavelmente aos seus aplicativos economiza.


+1 apagando a luz ou não respondendo perguntas.
Boz

4

Você deve escolher o melhor algoritmo simples para a tarefa. O motivo de ser simples é manter o código legível. O motivo pelo qual ele precisa ser o melhor é evitar começar com características de tempo de execução ruins. Não escolha cegamente o BubbleSort quando souber que terá grandes conjuntos de dados. É bom, no entanto, para o tipo ocasional de 10 elementos.

ENTÃO, se os números de criação de perfil mostrarem que sua escolha do melhor algoritmo simples não foi boa o suficiente, você poderá iniciar a otimização (que geralmente é o custo da legibilidade).


O BubbleSort pode realmente ser melhor do que o quicksort ou mescla quando seus dados são quase classificados com apenas alguns elementos dispersos que não estão muito longe do destino final. Porém, para todas as outras tarefas, você deve usar a função de classificação interna que sua linguagem de programação fornece para você; é a maneira mais simples de começar (e a função de classificação interna na maioria dos idiomas tem bom desempenho). CONSELHOS RUIM:, start out with bad runtime characteristicnão comece deliberadamente com uma característica de tempo de execução ruim.
Lie Ryan

@ Lie, se você SABE que seus dados estão quase ordenados e, portanto, pode usar bolhasort, você não está exatamente escolhendo cegamente seu algoritmo ... Também obrigado por apontar o erro de digitação.

4

Eu já disse isso antes e vou dizer aqui: "A otimização prematura é a raiz de todo mal" . Essa deve ser uma das regras no centro da mente de qualquer programador.

O código pode, até certo ponto, sempre ser mais rápido do que atualmente. A menos que você esteja montando manualmente a embalagem com um chip em mente, sempre há algo a ser ganho com a otimização. No entanto, a menos que você queira montar uma embalagem manual para tudo o que faz, deve haver uma meta quantitativa que, quando você se encontra, você diz "basta" e para de otimizar, mesmo que ainda exista um olhar ofuscante por desempenho. você na cara.

Um código bonito, elegante e extremamente eficiente é inútil se não funcionar (e por "trabalho" quero dizer produzir a saída esperada, considerando todas as entradas esperadas). Portanto, produzir código que funcione SEMPRE deve ser a primeira prioridade. Depois que funciona, você avalia o desempenho e, se estiver faltando, procura maneiras de melhorá-lo, até o ponto em que é bom o suficiente.

Há algumas coisas que você precisa decidir antecipadamente que afetarão o desempenho; decisões muito básicas, como qual idioma / tempo de execução você usará para implementar esta solução. Muitos deles impactarão o desempenho em muitas ordens de magnitude mais do que chamar um método contra outro. Honestamente, o PHP, como linguagem de script, já é um problema de desempenho, mas como poucos sites com script são criados de baixo para cima em C / C ++, é comparável a outras tecnologias que você provavelmente escolheria (Java Servlets, ASP.NET etc).

Depois disso, o tamanho da mensagem de E / S é o seu próximo maior desempenho. A otimização do que você lê e grava no disco rígido, portas seriais, canais de rede etc. geralmente melhorará o tempo de execução do programa em muitas ordens de magnitude, mesmo que os algoritmos por trás das operações de E / S sejam eficientes. Depois disso, reduza a complexidade Big-O do próprio algoritmo e, se for absolutamente necessário, você pode "otimizar" escolhendo opções de método mais baratas e tomando outras decisões esotéricas em níveis baixos.


2
+1 Produzir código que funcione SEMPRE deve ser a primeira prioridade.
Boz

2
@ Keith, na verdade Knuth disse primeiro, e ele disse um pouco mais do que isso.

"Faça funcionar, depois faça o trabalho o mais rápido que precisar", Anon.
John Saunders

1
Na verdade, a religião é a raiz de todo mal, mas eu discordo.
Thomas Eding

4

Você menciona que seu pai é um programador aposentado. Os programadores que trabalhavam no mundo do mainframe precisavam se preocupar muito com o desempenho. Lembro-me de estudar uma atividade da Marinha dos EUA em que seu mainframe estava restrito por hardware a 64 KB de memória por usuário. Nesse mundo da programação, você tem que procurar cada pouquinho que puder.

As coisas estão muito diferentes agora e a maioria dos programadores não precisa se preocupar tanto com micro-otimizações. No entanto, os programadores de sistemas embarcados ainda o fazem e as pessoas do banco de dados ainda precisam usar código otimizado.


3

O código deve ser escrito para ser absolutamente claro sobre o que ele faz. Então, se e somente se estiver muito lento, volte e acelere. O código sempre pode ser alterado para ser mais rápido mais tarde, se puder ser entendido - mas boa sorte mudando para ficar claro se for rápido.


3

É importante se:

1) A vida de alguém depende do seu código. Uma função que leva 25ms para ser executada no monitor de freqüência cardíaca de alguém é provavelmente uma má ideia.

Pessoalmente, adoto uma abordagem em duas frentes - existem micro-otimizações que você pode fazer que não afetam a legibilidade - obviamente você deseja usá-las. Mas se isso afeta a legibilidade, espere - você não obterá muitos benefícios e poderá levar mais tempo para depurar a longo prazo.


2
Apenas alguns pontos menores no seu exemplo: Uma função em um monitor de freqüência cardíaca que leva 25ms não seria um problema, desde que outras tarefas necessárias pudessem ocorrer com o tempo de resposta necessário. Interrupções são boas para isso. E latência de 25ms para algo que está apenas monitorando eventos do mundo real para atualizar uma exibição para consumo humano provavelmente não é um problema.
JANM

3

A micro-otimização é importante na codificação?

Não, considerando que existem plataformas como JVM e .NET em que o código é escrito para uma máquina virtual e, portanto, tentar otimizar a execução pode não funcionar tão bem quanto o que é ideal na área de trabalho de um desenvolvedor não é necessariamente o mesmo em um servidor. Veja a que distância do hardware algumas dessas peças de software de alto nível estão em outro ponto aqui. Algo a considerar é dada a diversidade de hardware, quão realista é otimizar o código para chips específicos, como uma CPU ou GPU, quando um novo modelo provavelmente será lançado em menos de um ano?

Outra questão aqui a considerar é o desempenho medido por qual métrica: velocidade de execução, memória usada na execução, velocidade de desenvolvimento de novos recursos, tamanho da base de código em um servidor em formas compiladas ou descompiladas, escalabilidade, manutenção, etc. .? Se for tomada de maneira ampla o suficiente, a pergunta se torna trivial, mas não tenho certeza de quão amplamente você pretendia levar o desempenho tão real que pode ser quase qualquer coisa, desde que possa ser medido de alguma maneira.


Algumas micro-otimizações podem funcionar e outras podem não funcionar, e é aí que se pode pensar em quanto vale a pena executar esse trabalho em comparação com outro trabalho que pode ser visto como uma prioridade muito maior, como novos recursos ou correção de bugs. A outra pergunta seria se uma atualização de hardware ou software também pode interromper algumas dessas otimizações.


1
Observe que você pode absolutamente fazer micro otimizações em plataformas como a JVM e .NET, elas apenas assumem formas ligeiramente diferentes. Mas o mesmo acontece se você comparar um compilador C simples e antigo com um compilador mais moderno e altamente otimizador: as otimizações que o usuário pode fazer parecerão diferentes.
Joachim Sauer

1

Eu acho que há uma grande diferença entre boa programação e micro-otimização.

Se houver duas maneiras de executar a mesma tarefa, uma sendo mais rápida que a outra e ambas com a mesma legibilidade, você deve usar a mais rápida. Sempre. E isso é uma boa programação. Não há razão para não usar um algoritmo melhor para resolver um problema. E mesmo documentando isso é fácil: forneça o nome do algoritmo, todos poderão pesquisar no Google e encontrar mais informações sobre como ele funciona.

E bons algoritmos já estão otimizados. Eles serão rápidos. Eles serão pequenos. Eles usarão a memória mínima necessária.

Mesmo se usá-los, seu programa ainda não possui esse desempenho, você pode considerar a otimização micro. E você precisará realmente conhecer o idioma para poder otimizar.

E sempre há espaço para gastar mais dinheiro em hardware. O hardware é barato, os programadores são caros . Não gaste muito tempo / dinheiro otimizando quando você pode apenas comprar hardware.


1

A legibilidade do código IMHO é mais importante que a micro otimização, porque na maioria dos casos a micro otimização não vale a pena.

Artigo sobre micro-otimizações sem sentido :

Como a maioria de nós, estou cansado de ler postagens de blog sobre micro-otimizações sem sentido, como substituir impressão por eco, ++ $ i por $ i ++ ou aspas duplas por aspas simples. Por quê? Porque 99.999999% do tempo, é irrelevante. Por quê? Como em 99,99% do tempo, é melhor instalar um acelerador PHP como o APC, adicionar esses índices ausentes nas colunas do banco de dados ou tentar evitar as 1000 solicitações de banco de dados existentes na página inicial.

print usa mais um código de operação, porque na verdade retorna algo. Podemos concluir que o eco é mais rápido que o impresso. Mas um código de operação não custa nada, realmente nada.

Eu tentei uma nova instalação do WordPress. O script é interrompido antes de terminar com um "Erro de barramento" no meu laptop, mas o número de códigos de operação já era superior a 2,3 milhões. Disse o suficiente.

Portanto, na maioria dos casos, a micro-otimização economiza 1 operação entre milhões, mas piora a legibilidade.


1

Outras respostas estão certas no dinheiro. Mas vou acrescentar outro ponto em que é preciso diferenciar o que é otimização / micro-otimização prematura e escrever código de desempenho que reflita uma compreensão do comportamento das construções de linguagem / estrutura (desculpe, não consegui encontrar uma palavra para o último) . O último é uma boa prática de codificação e geralmente se deve fazer!

Eu vou explicar A otimização ruim (leitura prematura / micro otimização) não ocorre quando você otimiza seções de código sem criar um perfil para saber se realmente são os gargalos. É quando você otimiza com base em suas suposições, boatos e comportamentos não documentados. Se está documentado e faz algo de uma maneira mais eficiente / lógica , por menor que seja, eu chamo de boa otimização . Como outros já declararam, ambos têm contras e quase nenhum profissional, no que diz respeito a ganhar bons negócios, mas ainda assim faço o último, não o primeiro, se isso não prejudica totalmente a legibilidade. Sim, a legibilidade / manutenção é da maior importância e é sobre onde você deve traçar a linha.

Reiterarei os pontos apontados por outros aqui como a futilidade de otimizações boas e ruins:

  1. Suas dependências para um problema específico podem mudar e qualquer tempo gasto na otimização antes de concluir a seção lógica do seu aplicativo é uma perda de tempo. Quero dizer, otimizar em um estágio relativamente inicial. Hoje você tem um List<T>e quando o aplicativo é enviado, você precisa alterá-lo LinkedList<T>e agora todo o benchmarking era uma perda de tempo e esforço.

  2. Principalmente, o gargalo real do seu aplicativo (lido como diferença mensurável) pode ser de 5% do seu código (principalmente o sql) e a otimização dos outros 95% não oferece benefícios a seus clientes.

  3. Normalmente, o código "tecnicamente" com melhor desempenho significa mais verbosidade, o que, por sua vez, significa mais código propenso a erros, o que, por sua vez, significa manutenção mais difícil e mais tempo gasto, o que, por sua vez, significa que você ganha menos dinheiro.

  4. A pegada de carbono que você economiza para o mundo inteiro com 1% de ganho de desempenho é facilmente reduzida pelos gases de efeito estufa que sua equipe precisará emitir ao depurar e manter esse código.

Os negativos da otimização ruim, em particular, são:

  1. Não costuma dar o desempenho que você espera. Veja esta pergunta no SO, onde as otimizações deram errado . De fato, pode ter efeitos adversos. Esse é o problema com o comportamento não documentado.

  2. De qualquer forma, os compiladores modernos farão isso por você.

Vou dar alguns exemplos de otimização ruim e boa:

O mal -

  1. uso de tipos inteiros menores em vez de Int32.

  2. ++i usado em vez de i++

  3. forem vez de foreach(o pior que eu já vi, derrota totalmente a lógica)

  4. evitando variáveis ​​fechadas

    string p;
    foreach (var item in collection)
        p = ...;
    
  5. usando em charvez de string durante a concatenação de string, como:

    string me = 'i' + "me myself"; // something along that line - causes boxing
    

O bom (do mundo .NET. Deve ser auto-explicativo) -

  1. Pesquisa dupla

    if (Dictionary<K, V>.TryGetValue(K, out V))
        do something with V
    

    ao invés de

    if (Dictionary<K, V>.ContainsKey(K))
        do something with Dictionary<K, V>[K]
    
  2. Carregue todos

    DirectoryInfo.EnumerateFiles();
    

    ao invés de

    DirectoryInfo.GetFiles();
    
  3. Fundição em dois estágios:

    s = o as string;
    if (s != null)
        proceed
    

    ao invés de

    if (o is string)
        s = (string)o;
    
  4. Se o pedido não importa

    if (counter < X || expensiveFunction())
    

    ao invés de

    if (expensiveFunction() || counter < X)
    
  5. Boxe

    void M<T>(T o) //avoids boxing
    {
    
    }
    

    ao invés de

    void M(object o)
    {
    
    }
    

Se você me perguntar se isso oferece benefícios visíveis de desempenho, eu diria que não. Mas eu sugeriria que se devesse usá-las porque decorre de uma compreensão do comportamento dessas construções. Por que fazer duas chamadas quando você pode fazer apenas 1? Do ponto de vista filosófico, é uma boa prática de codificação. E 1 e 3 também são um pouco menos legíveis em termos estritos, mas eles superam a legibilidade? Não, não muito, então eu uso. Agora essa é a chave - manter um desempenho decente em relação à legibilidade. E quando é isso, é sobre onde você desenha a linha.


1

"Vale a pena" precisa de contexto, como o mais simples de escrever, ler e manter, e o quanto mais rápido torna algo para o usuário muito mais responsivo e interativo, exigindo menos tempo para esperar.

Economizar alguns centavos para comprar uma lata de refrigerante não me fará muito bem se eu tiver que percorrer uma distância para economizar esses centavos, principalmente porque raramente tomo refrigerante hoje em dia. Economizar alguns centavos por lata na compra de um milhão de latas de refrigerante pode ser um grande negócio.

Enquanto isso, economizo alguns centavos quando duas pessoas estão ao meu lado e uma oferece exatamente a mesma coisa por algumas mais baratas e a outra não, e eu escolho a mais cara porque gosto mais do chapéu delas, parece um caso tolo de pessimização.

O que costumo encontrar pessoas chamando de "micro-otimizações" parece curiosamente desprovido de medições, contexto e discussão do usuário, quando deveriam existir os três para considerar essas otimizações, caso não sejam triviais. Para mim, uma micro otimização adequada hoje em dia está relacionada a coisas como layouts de memória e padrões de acesso e, embora possam parecer "micro" em foco, eles não são micro em efeito.

Consegui, há pouco tempo, reduzir uma operação de 24 segundos para 25 milissegundos (cerca de 960 vezes mais rápido), com saídas idênticas (protegidas por testes automatizados), sem alteração na complexidade algorítmica, para a cobertura volumétrica de difusão de calor, através de "micro-otimizações" (a maior das quais veio de uma alteração no layout da memória, que reduziu para cerca de 2 segundos, o restante foram coisas como SIMD e análises adicionais de falhas de cache no VTune e algum rearranjo adicional do layout da memória).

Wolfire explica a técnica aqui e lutou com o tempo necessário: http://blog.wolfire.com/2009/11/volumetric-heat-diffusion-skinning/

Minha implementação conseguiu fazer isso em milissegundos enquanto ele lutava para reduzi-lo a menos de um minuto: insira a descrição da imagem aqui

Depois que eu "otimizei" o micro de 24 segundos para 25ms, isso mudou o fluxo de trabalho. Agora, os artistas podem mudar suas plataformas em tempo real a mais de 30 FPS sem esperar 24 segundos cada vez que fazem pequenas alterações em suas plataformas. E isso realmente mudou todo o design do meu software, já que eu não precisava mais da barra de progresso e coisas desse tipo, tudo se tornou interativo. Portanto, isso pode ser uma "micro-otimização" no sentido de que todas as melhorias ocorreram sem nenhuma melhoria na complexidade algorítmica, mas foi uma "mega-otimização" em vigor que tornou o que antes era um processo doloroso e não interativo. para um interativo em tempo real que mudou completamente a maneira como os usuários trabalhavam.

Medição, Requisitos de Usuário Final, Contexto

Gostei muito do comentário de Robert aqui e talvez não tenha conseguido expressar o que queria:

Bem, vamos lá. Ninguém vai argumentar que esse tipo de mudança não "vale a pena". Você conseguiu demonstrar um benefício tangível; muitas das chamadas micro-otimizações não podem.

Apesar de trabalhar em um campo muito crítico para o desempenho, com requisitos frequentemente em tempo real, é o único momento em que considero qualquer micro-otimização que exija que eu saia do meu caminho.

E eu enfatizaria não apenas as medições, mas também o lado do usuário. Sou uma pessoa estranha porque cheguei ao meu campo atual (e anteriormente gamedev) como usuário / fã primeiro, desenvolvedor segundo. Portanto, nunca fiquei tão empolgado com as coisas usuais que empolgam os programadores como resolver quebra-cabeças técnicos; Achei um fardo para eles, mas aguentaria com eles o sonho do usuário final que compartilhei com outros usuários. Mas isso me ajudou a garantir que, se eu estivesse otimizando alguma coisa, teria um impacto real nos usuários com benefícios reais. É minha salvaguarda contra a otimização micro sem rumo.

Isso é realmente tão importante quanto o criador de perfil na minha opinião, porque eu tive colegas que fizeram coisas como otimizar a subdivisão de um cubo em um bilhão de facetas apenas para engasgar com modelos de produção do mundo real, como personagens e veículos. O resultado foi impressionante em algum sentido de "demonstração tecnológica", mas quase inútil para os usuários reais, porque eles estavam criando perfis, medindo e comparando casos que não estavam alinhados com os casos de uso do mundo real. Portanto, é muito importante entender primeiro o que é importante para os usuários, aprendendo a pensar e usar o software como um ou colaborando com eles (idealmente ambos, mas pelo menos colaborando com eles).


2
Bem, vamos lá. Ninguém vai argumentar que esse tipo de mudança não "vale a pena". Você conseguiu demonstrar um benefício tangível; muitas das chamadas micro-otimizações não podem.
Robert Harvey

1
@RobertHarvey Esse foi o tipo de argumento que eu esperava enfatizar, já que o que algumas pessoas chamam de "micro-otimização" não é necessariamente microscópico em efeito, mas é tão dependente do contexto, medições etc. issetvs. strlenparece mais minúsculo em foco ausente o contexto e as medidas. :-D
Dragon Energy

1
@RobertHarvey Eu esperava dizer, talvez indiretamente, que se houver um contexto negativo para "micro-otimizações", é o tipo que tende a ser desprovido dessas medidas, contextos e necessidades do usuário. Eu poderia continuar com o último caso também, pois tinha um colega que otimizava demais algo que era legal, exceto que ninguém o usava. Eu até acho que a otimização adequada requer algum entendimento do usuário final, caso contrário, poderíamos criar perfis e ajustar coisas com as quais os usuários não se importam.
Dragon Energy

1
Algumas otimizações são impulsionadas pela necessidade premente, enquanto outras são motivadas pela curiosidade (busca intelectual e aventureiro). Nós precisamos de ambos. Na história de Dragon Energy, provavelmente não era uma "necessidade premente", já que os artistas aparentemente não se queixaram em voz alta de não ver nenhum resultado de renderização até 24 segundos após cada edição. De fato, os usuários podem não saber o quão rápido poderia ter sido, até que um programador investisse em todo o esforço para bater o recorde de velocidade. Limitar-nos à demanda direcionada faz sentido para os negócios, mas isso perderá algumas oportunidades surpreendentes de otimização ou mudanças no jogo.
rwong

1
Falando em senso comercial, há também a questão da monetização. Cada movimento (por exemplo, um programador trabalhando na otimização de desempenho) custa dinheiro e o custo precisa ser recuperado para fazer sentido nos negócios. Portanto, é preciso perguntar se a melhoria na velocidade de mudança do jogo pode ser "vendida" ou quanto dinheiro seria "economizado", se o programador precisar obter a aprovação de um gerente de negócios.
rwong

0

Vou colocar desta maneira - a micro-otimização é um processo de otimização de algo que não é um gargalo. Por exemplo, se seu programa chama duas funções A e B, e A leva 100 milissegundos para ser concluído e B leva 2 microssegundos, e você continua otimizando a função B. Isso não é apenas importante, é absolutamente errado. Mas a função de otimização B é chamada de otimização e não de micro-otimização. A importância da otimização depende. Diga que você não tem mais nada a fazer e seu programa está livre de erros; então, sim, é importante. Mas geralmente você tem prioridades. Digamos que você precise adicionar / gravar a função C. Se você acha que a função de gravação C lhe renderá mais dinheiro do que tornar seu programa mais rápido sem essa funcionalidade, vá para a otimização. Caso contrário, prossiga com a funcionalidade. Além disso, programadores experientes focados no desempenho não gastam muito tempo otimizando, apenas escrevem programas rápidos. Pelo menos, eles sabem quais ferramentas usar e o que não fazer para passar anos fazendo otimizações sem sentido (leia micro).


é difícil ler este post (parede de texto). Você se importaria de editá -lo em uma forma melhor?
Gnat
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.