Normalmente odio la parola "ottimizzazione prematura", ma questo la spaventa. Vale la pena notare che Knuth ha usato questa famosa citazione nel contesto della spinta per usare le istruzioni goto
per accelerare il codice nelle aree critiche . Questa è la chiave: percorsi critici .
Stava suggerendo di usare goto
per accelerare il codice ma mettere in guardia contro quei programmatori che vorrebbero fare questo tipo di cose sulla base di intuizioni e superstizioni per codice che non è nemmeno critico.
Favorire il più possibile le dichiarazioni switch
uniformemente in un codebase (indipendentemente dal fatto che sia gestito o meno un carico pesante) è il classico esempio di ciò che Knuth chiama "penny-wise and pound- programmatore "folle" che passa tutto il giorno a lottare per mantenere il proprio codice "ottimizzato" che si è trasformato in un incubo di debugging come risultato del tentativo di risparmiare penny oltre sterline. Tale codice è raramente mantenibile e tanto meno efficiente anche in primo luogo.
Is he right?
È corretto dal punto di vista dell'efficienza di base. Nessun compilatore a mia conoscenza può ottimizzare il codice polimorfico che coinvolge oggetti e dispatch dinamico meglio di un'istruzione switch. Non finirai mai con una LUT o una tabella di salto a codice inte- rato da codice polimorfo, poiché tale codice tende a fungere da barriera di ottimizzazione per il compilatore (non saprà quale funzione chiamare fino al momento in cui la spedizione dinamica si verifica).
È più utile non pensare a questo costo in termini di tabelle di salto, ma più in termini di barriera di ottimizzazione. Per il polimorfismo, chiamare Base.method()
non consente al compilatore di sapere quale funzione verrà effettivamente chiamata se method
è virtuale, non sigillata e può essere ignorata. Dal momento che non sa quale funzione verrà effettivamente chiamata in anticipo, non può ottimizzare la chiamata di funzione e utilizzare più informazioni nel prendere decisioni di ottimizzazione, poiché non sa in realtà quale funzione verrà chiamata a il momento in cui il codice è in fase di compilazione.
Gli ottimizzatori sono al loro meglio quando possono effettuare il peer di una chiamata di funzione e fare ottimizzazioni che appiattiscono completamente il chiamante e il chiamante, o almeno ottimizzano il chiamante per funzionare in modo più efficiente con il chiamato. Non possono farlo se non sanno quale funzione verrà effettivamente chiamata in anticipo.
Is he just talking out his ass?
L'uso di questo costo, che spesso equivale a pochi centesimi, per giustificare la trasformazione di questo in uno standard di codifica applicato uniformemente è generalmente molto sciocco, specialmente per i luoghi che hanno bisogno di estensibilità. Questa è la cosa principale che vuoi osservare con veri e propri ottimizzatori prematuri: vogliono trasformare i problemi di prestazioni minori in standard di codifica applicati uniformemente in una base di codice senza alcun riguardo per la manutenzione di qualsiasi tipo.
Mi rendo un po 'offensivo della frase "vecchio hacker C" usata nella risposta accettata, dato che io sono uno di quelli. Non tutti quelli che sono stati codificati per decenni a partire da hardware molto limitato si sono trasformati in un ottimizzatore prematuro. Eppure ho incontrato e lavorato anche con quelli. Ma questi tipi non misurano mai cose come la predizione errata o la mancanza di cache, pensano di conoscere meglio e basano le loro nozioni di inefficienza in una base di codice di produzione complessa basata su superstizioni che non valgono oggi e che a volte non sono mai vere. Le persone che hanno realmente lavorato in campi critici per le prestazioni spesso capiscono che l'ottimizzazione efficace è una priorità effettiva, e tentare di generalizzare uno standard di codifica che riduce la manutenibilità per risparmiare penny è una priorità molto inefficace.
I penny sono importanti quando si dispone di una funzione economica che non fa molto lavoro, che è chiamata un miliardo di volte in un ciclo molto stretto e critico per le prestazioni. In tal caso, finiremo per risparmiare 10 milioni di dollari. Non vale la pena di rasarsi i penny quando si ha una funzione chiamata due volte per cui il corpo da solo costa migliaia di dollari. Non è saggio passare il tempo a litigare per pochi centesimi durante l'acquisto di un'auto. Vale la pena contrattare per pochi centesimi se si acquista un milione di lattine di soda da un produttore. La chiave per un'efficace ottimizzazione è comprendere questi costi nel loro contesto appropriato. Qualcuno che cerca di risparmiare centesimi su ogni singolo acquisto e suggerisce che tutti gli altri provano a contrattare per pochi centesimi indipendentemente da ciò che stanno acquistando, non è un ottimizzatore esperto.