Muitas vezes vi essa citação usada para justificar código ou código obviamente ruim que, embora seu desempenho não tenha sido medido, provavelmente poderia ser feito mais rapidamente com bastante facilidade, sem aumentar o tamanho do código ou comprometer sua legibilidade.
Em geral, acho que as micro-otimizações iniciais podem ser uma má ideia. No entanto, as otimizações macro (coisas como escolher um algoritmo O (log N) em vez de O (N ^ 2)) costumam valer a pena e devem ser feitas cedo, pois pode ser um desperdício escrever um algoritmo O (N ^ 2) e depois jogue fora completamente em favor de uma abordagem O (log N).
Observe que as palavras podem ser : se o algoritmo O (N ^ 2) for simples e fácil de escrever, você poderá jogá-lo fora mais tarde sem muita culpa, se parecer muito lento. Mas se os dois algoritmos forem igualmente complexos ou se a carga de trabalho esperada for tão grande que você já sabe que precisará da mais rápida, a otimização antecipada é uma boa decisão de engenharia que reduzirá sua carga de trabalho total a longo prazo.
Portanto, em geral, acho que a abordagem correta é descobrir quais são suas opções antes de começar a escrever código e escolher conscientemente o melhor algoritmo para sua situação. Mais importante ainda, a frase "otimização prematura é a raiz de todo mal" não é desculpa para ignorância. Os desenvolvedores de carreira devem ter uma idéia geral de quanto custa operações comuns; eles deveriam saber, por exemplo,
- que strings custam mais que números
- que linguagens dinâmicas são muito mais lentas do que linguagens estaticamente tipadas
- as vantagens das listas de vetores / matrizes sobre listas vinculadas e vice-versa
- quando usar uma hashtable, quando usar um mapa classificado e quando usar um heap
- que (se eles funcionam com dispositivos móveis) "double" e "int" têm desempenho semelhante em desktops (o FP pode até ser mais rápido), mas "double" pode ser cem vezes mais lento em dispositivos móveis de última geração sem FPUs;
- que a transferência de dados pela Internet é mais lenta que o acesso ao HDD, os HDDs são muito mais lentos que a RAM, a RAM é muito mais lenta que o cache e os registros L1, e as operações na Internet podem bloquear indefinidamente (e falhar a qualquer momento).
E os desenvolvedores devem estar familiarizados com uma caixa de ferramentas de estruturas de dados e algoritmos, para que possam usar facilmente as ferramentas certas para o trabalho.
Ter muito conhecimento e uma caixa de ferramentas pessoal permite otimizar quase sem esforço. Colocar muito esforço em uma otimização que pode ser desnecessária é ruim (e admito que caí nessa armadilha mais de uma vez). Mas quando a otimização é tão fácil quanto escolher um conjunto / hashtable em vez de uma matriz ou armazenar uma lista de números em duplo [] em vez de string [], por que não? Eu posso estar discordando de Knuth aqui, não tenho certeza, mas acho que ele estava falando sobre otimização de baixo nível, enquanto eu estou falando sobre otimização de alto nível.
Lembre-se, essa citação é originalmente de 1974. Em 1974, os computadores eram lentos e o poder de computação era caro, o que deu a alguns desenvolvedores a tendência de otimizar demais, linha por linha. Eu acho que é isso que Knuth estava pressionando. Ele não estava dizendo "não se preocupe com o desempenho", porque em 1974 isso seria apenas uma conversa maluca. Knuth estava explicando como otimizar; em resumo, deve-se concentrar apenas nos gargalos e, antes disso, você deve realizar medições para encontrar os gargalos.
Observe que você não pode encontrar os gargalos até escrever um programa para medir, o que significa que algumas decisões de desempenho devem ser tomadas antes que exista algo para medir. Às vezes, essas decisões são difíceis de serem alteradas se você errar. Por esse motivo, é bom ter uma idéia geral de quanto custa as coisas, para que você possa tomar decisões razoáveis quando não houver dados disponíveis.
A rapidez com que otimizar e o quanto se preocupar com o desempenho dependem do trabalho. Ao escrever scripts que você executará apenas algumas vezes, preocupar-se com o desempenho geralmente é uma completa perda de tempo. Mas se você trabalha para a Microsoft ou Oracle e está trabalhando em uma biblioteca que milhares de outros desenvolvedores usarão de milhares de maneiras diferentes, pode valer a pena otimizar tudo, para que você possa cobrir todas as diversas casos de uso com eficiência. Mesmo assim, a necessidade de desempenho sempre deve ser equilibrada com a necessidade de legibilidade, capacidade de manutenção, elegância, extensibilidade e assim por diante.