Come evitare "Intuizione di ottimizzazione errata dello sviluppatore"?


22

Ho visto un articolo che ha presentato questa affermazione:

Gli sviluppatori adorano ottimizzare il codice e con buone ragioni. È così soddisfacente e divertente. Ma sapere quando ottimizzare è molto più importante. Sfortunatamente, gli sviluppatori hanno generalmente un'orribile intuizione su dove saranno effettivamente i problemi di prestazioni in un'applicazione.

Come può uno sviluppatore evitare questa cattiva intuizione? Ci sono buoni strumenti per trovare quali parti del tuo codice necessitano davvero di ottimizzazione (per Java)? Conosci alcuni articoli, suggerimenti o buone letture su questo argomento?


1
Questo si riduce a "Come posso evitare di [fare affidamento] sulle intuizioni [quando prendo decisioni]?" Semplice: verifichi con dati e fatti concreti. Quindi, nel caso dell'ottimizzazione, dal punto di vista dello sviluppatore: fai il benchmark.
haylem,

Risposte:


44
  • Usa un buon profiler per identificare metodi costosi.
  • Documenta quanto tempo hanno impiegato i punti caldi.
  • Scrivi un'implementazione più rapida degli hot spot
  • Documenta quanto tempo impiegano ora gli hot spot, speriamo di non renderli più hotspot.

In sostanza, devi essere in grado di dimostrare agli altri dov'era il problema e che questo cambiamento l'ha fatto sparire.

Non potendo dimostrare un miglioramento, si qualifica - a mio parere personale - per il rollback immediato alla versione originale.


51
O per dirla ancora più semplicemente: "Per evitare una cattiva intuizione dell'ottimizzazione, non usare l'intuizione. Misura".
Kyralessa,

6
Ecco perché la tua è una risposta e la mia è solo un commento. : P
Kyralessa,

2
@Thomas, se giocherelli con leggibilità e manutenibilità non stai osservando esattamente i problemi di prestazioni, vero?

3
@Thomas, non sono d'accordo. Anche all'interno delle specifiche, è necessario ripetere nuovamente il test del nuovo codice. Questo non è necessario per il vecchio codice. Ripristina.

2
@ Thorbjørn Dopo l'ottimizzazione delle prestazioni, è necessario ripetere nuovamente il test del nuovo codice. Risparmiare tempo o memoria non ha senso se si introduce un difetto.
Thomas Owens

10

L'unico modo per sapere dove ottimizzare è profilare il codice. Invece di apportare modifiche che ritieni possano offrire un vantaggio, sappi con certezza dove si trova il codice con le prestazioni peggiori e inizia da lì.

Java lo rende piuttosto semplice con lo strumento VisualVM , che è stato fornito in bundle con le recenti versioni di Java Development Kit (JDK). L'idea è quella di scoprire quali metodi sono chiamati di più e in quali metodi stai spendendo la maggior parte del tuo tempo, sia nel tuo codice che in librerie esterne. È inoltre possibile ottenere dati sulle prestazioni della garbage collection in modo da poter ottimizzare il raccoglitore e regolare lo spazio heap min / max richiesto dall'applicazione.


VisualVM non è nel JRE, ma solo nel JDK.

1
@ Thorbjørn Ravn Andersen Buona chiamata. Dovrei chiarire. Tuttavia, se stai sviluppando Java, di solito hai installato JDK (anche se potresti eseguire OpenJDK o simili - non so se quelli vengono con VisualVM).
Thomas Owens

1
Molto spesso cambio area di lavoro in Eclipse, che per impostazione predefinita passa a JRE che ha lanciato Eclipse. Poiché è molto più facile installare JRE che JDK, siamo passati lentamente a un processo di generazione di formiche che include il compilatore Eclipse e quindi può essere eseguito su JRE semplice. Quindi, in questi giorni puoi effettivamente fare un vero lavoro senza JDK. VisualVM può essere scaricato separatamente facilitando l'utilizzo con un determinato versino Java, poiché in JVM a 64 bit di Windows non è possibile connettersi a JVM a 32 bit e viceversa.

9

Dato che qualcuno qui parla di profiler, mi concentrerò su questa parte della domanda.

Come può uno sviluppatore evitare questa cattiva intuizione?

Tu. fare. non. Invece non ottimizzi mai in anticipo .
Ripetilo ancora e ancora e ancora, poiché è un mantra religioso.

Ti ritroverai a farlo e scoprirai che non avresti dovuto.
E poi di nuovo.
E di nuovo.

L'ottimizzazione precoce è uno dei peccati capitali dei programmatori .

Strumenti e cose fanno parte della successiva ottimizzazione che è un mestiere affermato .


Ottimizzazione anticipata del "codice contorto", di sicuro. La scelta di algoritmi e / o strutture di dati che si adattano al tuo problema e (con il carico di elaborazione previsto) hanno buone caratteristiche prestazionali è qualcosa che dovrebbe essere fatto prima di iniziare a scrivere codice.
Vatine,

@Vatine Sì, ci sono stato. No, non farlo. Fai ciò che si adatta alla tua mappa mentale del problema in questione. Essa potrebbe essere l'algoritmo più performante , e vi auguro che, esso non ha bisogno di.
ZJR,

mi sembra il principio YAGNI - NON SEI NECESSARIO!
EL Yusubov,

7

Questi strumenti sono chiamati profiler . Puoi usarli per misurare effettivamente quali parti del tuo programma impiegano più tempo per l'esecuzione, quindi dove concentrare i tuoi sforzi di ottimizzazione.

È altrettanto importante misurare nuovamente dopo le modifiche, per verificare che le modifiche abbiano l'effetto desiderato.


5

Guarda anche quanta memoria utilizza il tuo programma, non solo la sua velocità o tempo di esecuzione.

Molti programmatori che lavorano con linguaggi raccolti come Garbage, come Java, hanno l'impressione errata che Garbage Collection prevenga perdite di memoria. Questo non è il caso. Se si tiene un riferimento a un oggetto che non è più necessario, non verrà raccolto e quindi perderà.

Ho visto applicazioni Web Java che erano così fuoriuscite che avrebbero esaurito il loro server dallo spazio di scambio!

Se usi sia un profiler di runtime sia un qualche tipo di profiler di memoria, imparerai a scrivere codice più veloce e più snello in modo intuitivo. Ciò ha l'effetto che è più probabile che il tuo codice venga eseguito rapidamente al primo tentativo.


1

il mio rimedio è iniziare ottenendo risposte chiare a due domande:

  1. come misurare le prestazioni (es. misurare il tempo di caricamento dei dati )
  2. qual è il valore target (ad es. i dati vengono caricati in 3 secondi o meno con una sicurezza del 95% )

Ho imparato sopra i trucchi dai ragazzi della tigre che una volta sono stati invitati a salvare una versione non funzionante del nostro prodotto. Quel rilascio è stato interrotto per motivi di prestazioni, potrebbe far perdere il cliente strategico alla società, il che ha giustificato il coinvolgimento dei tigre (piuttosto costoso tra l'altro). Mi è stato assegnato il compito di assisterli nel chiarire i dettagli del progetto; usato anche questo come un'opportunità per imparare un po 'o due sulle prestazioni.


1

Quello che ho trovato è il miglior antidoto all'ottimizzazione prematura è questo metodo .

Una volta che lo hai utilizzato per accelerare un po 'di codice (come in questo esempio ), diventa una sua dipendenza e capisci che il primo principio di ottimizzazione delle prestazioni non è la modifica del codice, sta trovando il problema .

La vera ottimizzazione è l'ottimizzazione prematura come la caccia per nutrire la tua famiglia è come sparare alle lattine. Si tratta di trovare la cava.


1
E sfortunatamente, puoi portare solo 200 sterline alla tua famiglia, quindi non sparare scoiattoli tutto il giorno.
Giordania,

1

Vecchia domanda, ma offrirò questa risposta che differisce notevolmente dalle altre.

Le grandi opportunità di miglioramento delle prestazioni derivano dall'elaborazione parallela. Prova a progettare il tuo codice per sfruttare più thread. (Anche se, per semplicità, non lo fai nella versione 1). Sono necessarie poche congetture o intuizioni.

Qualsiasi altra cosa è un'ottimizzazione prematura e richiede la tua intuizione, che spesso è sbagliata.


Davvero un buon punto. In passato, si poteva contare sul fatto che i processori diventavano molto più veloci ogni pochi anni. Ora dovresti solo aspettarti che ci saranno più processori.
JimmyJames il

0

La tua intuizione può migliorare con il tempo. Lo butterei fuori, forse un po 'controverso, ma nel corso di molti anni di utilizzo di VTune e CodeAnalyst e ora CodeXL, direi che sono molto più preciso nelle mie intuizioni rispetto a prima su dove saranno gli hotspot, almeno per il punto in cui non sono più colto di sorpresa quando profilo un po 'di codice. Ciò non significa che cerco di ottimizzare le cose alla cieca.

La profilazione ha effettivamente aumentato la mia dipendenza dai profiler, non diminuita. Sto solo dicendo che posso anticipare più facilmente quali saranno i risultati della profilazione in una certa misura e inoltre, eliminare con successo gli hotspot e migliorare il tempo necessario per completare l'operazione dell'utente finale senza prendere pugnalate cieche nel buio e mancanti (qualcosa che può fare anche quando si utilizza un profiler fino a quando non si inizia a capire non solo quali sono gli hotspot, ma perché esattamente sono hotspot rispetto, ad esempio, ai mancati cache).

Tuttavia, non è stato fino a quando ho iniziato a utilizzare i profiler che ho iniziato a migliorare quell'intuizione. Uno dei motivi è perché se hai familiarità con il tuo codice, le tue intuizioni potrebbero essere corrette rispetto ai punti più grandi e ovvi, ma non tutte le sottigliezze nel mezzo. Naturalmente, se hai un'operazione di fine utente che richiede un'ora per il completamento e c'è un algoritmo di complessità quadratica spalancata che elabora un input che comprende centinaia di migliaia di elementi, probabilmente puoi uscirne ricco scommettendo i tuoi risparmi sulla vita intera sull'idea che è la complessità quadratica algoritmo in difetto qui. Ma questo non ti dà alcuna visione dettagliata o, diciamo, ti fa sapere esattamente cosa non sta contribuendo al tempo.

C'è così tanto valore da avere quando inizi a profilare e vedere dove tutte le cose che pensi possano essere state un contributo maggiore del tempo non hanno contribuito molto tempo; non le evidenti fonti di inefficienza spalancate, ma quelle che sospettavi potrebbero essere state leggermente inefficienti ma, dopo aver profilato, capito che a malapena hanno contribuito in qualsiasi momento. Ed è potenzialmente lì che ottieni le intuizioni più intuitive è trovarti a essere mostrato sbagliato in tutte quelle aree sottili in cui non è ovvio esattamente quanto tempo viene speso.

L'intuizione umana oltre l'evidente complessità algoritmica spesso inizierà in modo errato perché ciò che è efficiente per la macchina e ciò che è efficiente per la mente umana sono molto diversi. All'inizio non è così intuitivo pensare alle gerarchie di memoria che vanno dai registri alla cache della CPU, dalla DRAM al disco. Non viene intuitivamente pensare che l'aritmetica ridondante possa essere più veloce rispetto a fare più ramificazioni o accessi alla memoria di una tabella di ricerca per saltare alcuni lavori di elaborazione. Tendiamo a pensare in termini di quanto lavoro c'è da fare mentre scontiamo cose come il costo di prendere decisioni, carichi di memoria e negozi. Ciò che è efficiente per l'hardware è spesso molto intuitivo in modi che spezzeranno tutti i tuoi presupposti umani,

Laddove migliorare l'intuizione può aiutare, attraverso la profilazione, è la progettazione dell'interfaccia . I progetti di interfaccia sono molto costosi da cambiare a posteriori, con costi che aumentano in proporzione al numero di posti a seconda di tale interfaccia. Quando inizi a migliorare la tua intuizione, puoi iniziare a progettare meglio le interfacce la prima volta in modi che lascino spazio per l'ottimizzazione futura senza costose modifiche alla progettazione. Ancora una volta, però, quell'intuizione è qualcosa che generalmente sviluppi e continui a sviluppare indefinitamente, avendo sempre in mano quel profiler.


0

I profiler aiutano a correggere la cattiva intuizione quando si tratta di codice. Dato quanto hardware prevede in questi giorni non è umanamente pratico prevedere le prestazioni del tuo codice, ma ciò era ancora vero ai tempi di Knuth, così tanti decenni fa, che sosteneva che i profiler dovrebbero essere inclusi come parte degli strumenti standard per lo sviluppo per risolvere il natura "pazzesca e insensibile" degli sviluppatori. Ma ho intenzione di seguire una strada molto diversa con questa risposta, data la completezza delle risposte sotto altri aspetti e dire che la comprensione da parte dell'utente è l'altra "soluzione".

Ho visto, nella mia esperienza personale, uno sviluppatore particolarmente brillante (ma con punti ciechi spalancati su come gli utenti utilizzano effettivamente il software) ottimizzando un algoritmo di suddivisione con profiler in mano (molto buono, costoso e completo: Intel VTune con grafico delle chiamate campionamento in cima ai profilatori GPU) per le mesh ottengono risultati sorprendenti con miliardi di sfaccettature sulla GPU quando si suddividono primitivi semplici come cubi con 6 poligoni a gabbia / input. Tranne che ha messo a punto e messo a punto quel caso di test che era diverso da qualsiasi caso d'uso reale (gli utenti non vogliono un miliardo di sfaccettature per un cubo suddiviso che inizia ad assomigliare a una sfera perfetta, i loro input di suddivisione tendono ad essere cose come personaggi e veicoli e altri input complessi).

Stranamente sono andato oltre con una metà del cervello funzionale come lui e nessun dottorato di ricerca nella mia carriera, per il semplice motivo che ho capito cosa volevano gli utenti, cosa voleva il marketing, cosa volevano i designer. Non posso davvero sottolineare abbastanza quanto sia utile essere in grado di metterti nella mentalità e nei panni dell'utente e guardare il tuo software e cosa deve fare come i tuoi utenti reali mentre cerchi di divorziare dagli sforzi che metti nella costruzione di ciò che hai costruito e guardandolo con un nuovo paio di occhi. Ho anche riscontrato dallo sviluppatore sopra che questa è una cosa impossibile da fare; pensava di essere colpevole di avere un simile ego simile a quello che hanno tutti gli sviluppatori tecnicamente esperti ma ignari degli utenti, e ho costantemente dimostrato che si sbagliava quando utenti e designer si affollano da me per parlare esattamente di cosa fare. Sembra molto egoistico, ma lo bilancerò con la dichiarazione di non responsabilità che non sono un programmatore così brillante, ma capisco cosa vogliono utenti e designer, e questo mi ha reso particolarmente favorito nel mio campo in cui questo sembrava essere particolarmente raro qualità per qualche motivo. Come programmatori siamo probabilmente più abituati a testare che a capire e socializzare con persone normali e non tecniche.

Quindi c'è la profilazione e la misurazione corretta, ma c'è anche la necessità fondamentale di assicurarsi effettivamente che si stia misurando un'operazione con il tipo di input che gli utenti del mondo reale forniranno effettivamente all'applicazione. Altrimenti puoi anche avere VTune o CodeAnalyst o gprof o qualsiasi altro profiler in mano e ancora, mentre cerchi di ottimizzare gli hotspot rispetto a quello che potrebbe sembrare un normale test case per lo sviluppatore ma oscuro per gli utenti, finendo per pessimizzare il caso d'uso comune a favore di alcuni casi d'uso oscuri che pochi utenti, se ve ne sono, considerano mai l'applicazione.

Alla fine della giornata tutte le impraticabilità che tendiamo a portare come sviluppatori possono essere bilanciate con il martello di ferro di ciò che rende gli utenti abbastanza felici senza risolvere la fame nel mondo, e la necessità pratica di ottenere soldi in modo da poter pagare l'affitto o comprare birra o guarda le donne nude o qualunque cosa tu voglia / debba fare. Tutto il resto sta potenzialmente lavorando contro quel bisogno commerciale fondamentale, e qualsiasi sviluppatore così nobile, così eroico, da dimenticare che si tratta di fare soldi e, in definitiva, soddisfare gli utenti per farli pagare potrebbe fare bene a mettersi sulla terra e disattiva la modalità dio creando mondi virtuali a favore del mondo reale che devono semplicemente spedire e ottenere del denaro per il cibo. Ci possiamo perdere nelle metriche e nelle pratiche del software, ma fondamentalmente "

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.