Normalmente eu odeio a palavra "otimização prematura", mas isso cheira a isso. Vale a pena notar que Knuth usou essa famosa citação no contexto de pressionar para usar goto
instruções para acelerar o código em áreas críticas . Essa é a chave: caminhos críticos .
Ele estava sugerindo o uso goto
para acelerar o código, mas alertando contra os programadores que desejam fazer esse tipo de coisa com base em palpites e superstições de códigos que nem são críticos.
Favorecer switch
declarações o máximo possível de maneira uniforme em toda a base de código (independentemente de qualquer carga pesada ser manipulada) é o exemplo clássico do que Knuth chama de programador "tostão e tolo" que passa o dia todo lutando para manter seus "otimizados" "código que se transformou em um pesadelo de depuração como resultado da tentativa de economizar centavos por libras. Esse código raramente pode ser mantido e muito menos eficiente em primeiro lugar.
Ele está certo?
Ele está correto da perspectiva da eficiência muito básica. Nenhum compilador que eu saiba pode otimizar código polimórfico envolvendo objetos e envio dinâmico melhor do que uma instrução switch. Você nunca terminará com uma tabela LUT ou de salto para código embutido a partir de código polimórfico, pois esse código tende a servir como uma barreira otimizadora para o compilador (ele não saberá qual função chamar até o momento em que o envio dinâmico ocorre).
É mais útil não pensar nesse custo em termos de tabelas de salto, mas mais em termos da barreira de otimização. Para o polimorfismo, a chamada Base.method()
não permite que o compilador saiba qual função realmente será chamada se method
for virtual, não selada e puder ser substituída. Como não sabe para qual função realmente será chamada antecipadamente, não pode otimizar a chamada de função e utilizar mais informações para tomar decisões de otimização, pois na verdade não sabe para qual função será chamada. a hora em que o código está sendo compilado.
Os otimizadores estão no seu melhor quando podem espiar uma chamada de função e fazer otimizações que achatam completamente o chamador e o receptor, ou pelo menos otimizam o chamador para trabalhar com mais eficiência com o receptor. Eles não podem fazer isso se não souberem qual função será realmente chamada com antecedência.
Ele está apenas falando mal?
Usar esse custo, que geralmente equivale a centavos, para justificar transformar isso em um padrão de codificação aplicado de maneira uniforme é geralmente muito tolo, especialmente para locais com necessidade de extensibilidade. Essa é a principal coisa que você deseja observar com otimizadores prematuros genuínos: eles querem transformar pequenas preocupações de desempenho em padrões de codificação aplicados uniformemente em toda uma base de código, sem considerar a manutenção.
Eu me ofereço um pouco com a citação "old C hacker" usada na resposta aceita, já que sou uma dessas. Nem todo mundo que codifica há décadas a partir de hardware muito limitado se transformou em um otimizador prematuro. No entanto, eu também encontrei e trabalhei com eles. Mas esses tipos nunca medem coisas como erros de previsão de ramificação ou erros de cache, eles acham que sabem melhor e baseiam suas noções de ineficiência em uma complexa base de código de produção baseada em superstições que não são verdadeiras hoje em dia e às vezes nunca são verdadeiras. As pessoas que realmente trabalharam em campos críticos para o desempenho geralmente entendem que a otimização efetiva é uma priorização efetiva, e tentar generalizar um padrão de codificação degradante da manutenção para economizar centavos é uma priorização muito ineficaz.
Moedas de um centavo são importantes quando você tem uma função barata que não faz tanto trabalho, que é chamado um bilhão de vezes em um loop muito apertado e crítico para o desempenho. Nesse caso, acabamos economizando 10 milhões de dólares. Não vale a pena raspar centavos quando você tem uma função chamada duas vezes, pela qual o corpo por si só custa milhares de dólares. Não é aconselhável gastar seu tempo discutindo moedas de um centavo durante a compra de um carro. Vale a pena pechinchar se você estiver comprando um milhão de latas de refrigerante de um fabricante. A chave para uma otimização eficaz é entender esses custos em seu contexto adequado. Alguém que tenta economizar centavos em cada compra e sugere que todo mundo tente pechinchar, não importa o que está comprando, não é um otimizador qualificado.