Dove ho lavorato, utilizziamo sempre più livelli di profilazione; se vedi un problema, scorri un po 'più in basso l'elenco fino a capire cosa sta succedendo:
- Il "profiler umano", noto anche come gioco ; ti senti lento o "agganciato" di tanto in tanto? Notare animazioni a scatti? (Come sviluppatore, tieni presente che sarai più sensibile ad alcuni tipi di problemi di prestazioni e ignaro di altri. Pianifica di conseguenza ulteriori test.)
- Attiva il display FPS , che è un FPS medio di 5 secondi a finestra scorrevole. Spese generali minime da calcolare e visualizzare.
- Attiva le barre del profilo , che sono solo una serie di quadranti (colori ROYGBIV) che rappresentano diverse parti del fotogramma (ad esempio vblank, preframe, update, collision, render, postframe) usando un semplice timer "cronometro" attorno a ciascuna sezione del codice . Per enfatizzare ciò che vogliamo, impostiamo una larghezza di barra dello schermo che sia rappresentativa di un frame di destinazione a 60Hz, quindi è davvero facile vedere se hai ad esempio il 50% di budget (solo una mezza barra) o il 50% di oltre ( la barra si avvolge e diventa una e mezza). È anche abbastanza facile dire cosa generalmente mangia la maggior parte del frame: rosso = rendering, giallo = aggiornamento, ecc ...
- Costruisci una speciale build strumentata che inserisce "cronometro" come il codice attorno a ciascuna funzione. (Tieni presente che potresti fare grandi prestazioni, dcache e icache quando lo fai, quindi è decisamente invadente. Ma se ti manca un profiler di campionamento adeguato o un supporto decente sulla CPU, questa è un'opzione accettabile. Puoi anche essere intelligente sulla registrazione di un minimo di dati sulla funzione enter / exit e sulla ricostruzione di calltraces in seguito.) Quando abbiamo creato il nostro, abbiamo imitato gran parte del formato di output di gprof .
- Soprattutto, eseguire un profiler di campionamento ; VTune e CodeAnalyst sono disponibili per x86 e x64, hai vari ambienti di simulazione o emulazione che potrebbero fornirti dati qui.
(C'è una storia divertente del GDC dell'anno scorso di un programmatore grafico che ha scattato quattro foto di se stesso - felice, indifferente, infastidito e arrabbiato - e ha mostrato un'immagine appropriata nell'angolo delle build interne basata sul framerate. i creatori di contenuti impararono rapidamente a non attivare shader complicati per tutti i loro oggetti e ambienti: avrebbero fatto arrabbiare il programmatore. Ecco il potere del feedback.)
Nota che puoi anche fare cose divertenti come rappresentare graficamente le "barre del profilo" in modo continuo, in modo da poter vedere modelli di spike ("stiamo perdendo un frame ogni 7 frame") o simili.
Per rispondere direttamente alla tua domanda, però: nella mia esperienza, mentre è allettante (e spesso gratificante - di solito imparo qualcosa) a riscrivere singole funzioni / moduli per ottimizzare il numero di istruzioni o le prestazioni di icache o dcache, e in realtà dobbiamo fare questo a volte quando abbiamo un problema di prestazioni particolarmente odioso, la stragrande maggioranza dei problemi di prestazione che affrontiamo su base regolare si riduce alla progettazione . Per esempio:
- Dovremmo memorizzare nella cache RAM o ricaricare dal disco i frame di animazione dello stato "attacco" per il lettore? Che ne dici di ogni nemico? Non abbiamo RAM per eseguirli tutti, ma i carichi del disco sono costosi! Puoi vedere l'autostop se 5 o 6 nemici diversi saltano fuori contemporaneamente! (Okay, che ne dici di spawning sbalorditivo?)
- Stiamo eseguendo un solo tipo di operazione su tutte le particelle o tutte le operazioni su una singola particella? (Questo è un compromesso icache / dcache e la risposta non è sempre chiara.) Che ne dici di separare tutte le particelle e memorizzare le posizioni insieme (la famosa "struttura di matrici") rispetto a mantenere tutti i dati delle particelle in un unico posto (" matrice di strutture ").
Lo senti fino a quando non diventa odioso in qualsiasi corso di informatica a livello universitario, ma: si tratta davvero di strutture di dati e algoritmi. Trascorrere un po 'di tempo in algoritmo e progettazione del flusso di dati ti farà guadagnare di più per il dollaro in generale. (Assicurati di aver letto le eccellenti insidie delle diapositive sulla programmazione orientata agli oggetti di un collega dei Servizi per gli sviluppatori Sony per avere un'idea qui.) Questo non "sembra" come ottimizzazione; è principalmente tempo impiegato con una lavagna o uno strumento UML o con la creazione di molti prototipi, piuttosto che rendere il codice corrente più veloce. Ma in genere è molto più utile.
E un'altra utile euristica: se sei vicino al "core" del tuo motore, potrebbe valere la pena di dedicare qualche sforzo e sperimentazione in più per l'ottimizzazione (es. Vettorializzare quei moltiplicatori di matrici!). Più lontano dal core, meno dovresti preoccuparti a meno che uno dei tuoi strumenti di profilazione non ti dica diversamente.