Stiamo lavorando su una base di codice C ++ di dimensioni moderate (10Mloc) che attraverso i nostri sforzi di ottimizzazione sta diventando uniformemente lento .
Questo codice base è un insieme di librerie che combiniamo per metterle al lavoro. Quando è stato sviluppato il quadro generale di come queste librerie comunicano, c'è stata una certa enfasi sulle prestazioni e in seguito, quando più parti sono state aggiunte, il quadro generale non è stato modificato molto. L'ottimizzazione è stata eseguita quando necessario e man mano che il nostro hardware si è evoluto. Ciò ha reso la decisione iniziale molto costosa solo molto più tardi. Siamo ora in un punto in cui ulteriori ottimizzazioni sono molto più costose in quanto richiederebbero la riscrittura di ampie parti della base di codice. Ci troviamo di fronte a un minimo locale indesiderabile poiché sappiamo che in linea di principio il codice dovrebbe essere in grado di funzionare molto più velocemente.
Esistono metodologie di successo che aiutano a decidere quali cambiamenti prendere l'evoluzione di una base di codice verso una soluzione globalmente performante che non sia facilmente confusa da facili opportunità di ottimizzazione?
Modifica
Per rispondere alla domanda su come stiamo attualmente profilo:
In realtà abbiamo solo 2 diversi scenari su come utilizzare questo codice, sia in modo imbarazzante che parallelo. La profilazione viene eseguita sia con una media temporale dell'orologio a muro su un ampio campione di input e con esecuzioni più dettagliate (costi di istruzione, previsioni errate delle branche e problemi di memorizzazione nella cache). Funziona bene poiché eseguiamo esclusivamente macchine estremamente omogenee (un cluster di un paio di migliaia di macchine identiche). Dato che di solito teniamo tutte le nostre macchine occupate per la maggior parte del tempo a correre più velocemente significa che possiamo guardare altre cose nuove. Il problema è ovviamente che quando si presentano nuove variazioni di input, potrebbero ottenere una penalità in ritardo poiché abbiamo rimosso le più evidenti micro-inefficienze per gli altri casi di utilizzo, riducendo quindi il numero di scenari "in esecuzione ottimale". Le risposte attuali suggeriscono giustamente di separare i dati e gli algoritmi in modo che questo sia più facile da regolare.