Ricerca…


Approccio generale

Internet è pieno di suggerimenti per il miglioramento delle prestazioni dei programmi Java. Forse il consiglio numero uno è la consapevolezza. Questo significa:

  • Identificare possibili problemi di prestazioni e colli di bottiglia.
  • Utilizzare strumenti di analisi e test.
  • Conoscere buone pratiche e cattive pratiche.

Il primo punto dovrebbe essere fatto durante la fase di progettazione se si parla di un nuovo sistema o modulo. Se si parla di codice legacy, gli strumenti di analisi e testing entrano in scena. Lo strumento più basilare per analizzare le tue prestazioni JVM è JVisualVM, che è incluso nel JDK.

Il terzo punto riguarda principalmente l'esperienza e la ricerca approfondita e, ovviamente, i suggerimenti grezzi che verranno visualizzati in questa pagina e altri, come questo .

Riduzione della quantità di stringhe

In Java, è troppo "facile" creare molte istanze String che non sono necessarie. Questo e altri motivi potrebbero far sì che il tuo programma abbia molte stringhe che il GC è impegnato a ripulire.

Alcuni modi in cui potresti creare istanze String:

myString += "foo";

O peggio, in un ciclo o ricorsione:

for (int i = 0; i < N; i++) {
    myString += "foo" + i;
}

Il problema è che ogni + crea una nuova stringa (di solito, poiché i nuovi compilatori ottimizzano alcuni casi). Una possibile ottimizzazione può essere fatta usando StringBuilder o StringBuffer :

StringBuffer sb = new StringBuffer(myString);
for (int i = 0; i < N; i++) {
    sb.append("foo").append(i);
}
myString = sb.toString();

Se si costruiscono spesso stringhe lunghe (ad esempio SQL), utilizzare un'API di costruzione di stringhe.

Altre cose da considerare:

  • Ridurre l'uso di replace , substring ecc.
  • Evitare String.toArray() , specialmente nel codice di accesso frequente.
  • Le stampe di registro che sono destinate a essere filtrate (a causa del livello di registro per esempio) non dovrebbero essere generate (il livello di registro deve essere controllato in anticipo).
  • Usa librerie come questa se necessario.
  • StringBuilder è migliore se la variabile viene utilizzata in modo non condiviso (attraverso thread).

Un approccio evidence-based all'ottimizzazione delle prestazioni di Java

Donald Knuth è spesso citato come dicendo questo:

"I programmatori sprecano enormi quantità di tempo a pensare, o preoccuparsi, la velocità di parti non critiche dei loro programmi, e questi tentativi di efficienza in realtà avere un forte impatto negativo quando il debug e la manutenzione sono considerati. Dobbiamo dimenticare le piccole efficienze, dicono di Il 97% delle volte : l'ottimizzazione prematura è la radice di tutti i mali, tuttavia non dovremmo perdere le nostre opportunità in quel 3% critico ".

fonte

Tenendo presente questo consiglio, ecco la procedura consigliata per l'ottimizzazione dei programmi:

  1. Prima di tutto, progetta e codifica il tuo programma o libreria con particolare attenzione alla semplicità e alla correttezza. Per cominciare, non spendere molto per le prestazioni.

  2. Portalo a uno stato di lavoro e (idealmente) sviluppa test unitari per le parti chiave del codice base.

  3. Sviluppare un benchmark delle prestazioni a livello di applicazione. Il benchmark dovrebbe coprire gli aspetti critici delle prestazioni della vostra applicazione e dovrebbe eseguire una serie di attività tipiche di come l'applicazione verrà utilizzata nella produzione.

  4. Misura le prestazioni.

  5. Confronta le prestazioni misurate con i tuoi criteri per la velocità con cui l'applicazione deve essere. (Evita criteri non realistici, irraggiungibili o non quantificabili come "il più velocemente possibile".)

  6. Se hai soddisfatto i criteri, FERMA. Il lavoro è finito (Qualsiasi ulteriore sforzo è probabilmente una perdita di tempo.)

  7. Profili l'applicazione mentre sta eseguendo il tuo benchmark delle prestazioni.

  8. Esamina i risultati del profilo e scegli i "hotspot di prestazione" più grandi (non ottimizzati); cioè sezioni del codice in cui l'applicazione sembra passare più tempo.

  9. Analizza la sezione del codice hotspot per cercare di capire perché è un collo di bottiglia e pensa a un modo per renderlo più veloce.

  10. Implementalo come una proposta di modifica del codice, test e debug.

  11. Rieseguire il benchmark per vedere se il cambio di codice ha migliorato le prestazioni:

    • Se Sì, quindi tornare al passaggio 4.
    • Se No, abbandonare la modifica e tornare al punto 9. Se non si stanno facendo progressi, selezionare un punto di attivazione diverso per l'attenzione.

Alla fine arriverete a un punto in cui l'applicazione è abbastanza veloce o avete preso in considerazione tutti gli hotspot significativi. A questo punto devi fermare questo approccio. Se una sezione di codice sta consumando (diciamo) l'1% del tempo complessivo, allora anche un miglioramento del 50% renderà l'applicazione solo dello 0,5% più veloce nel complesso.

Chiaramente, c'è un punto oltre il quale l'ottimizzazione dell'hotspot è uno spreco di energie. Se arrivi a quel punto, devi adottare un approccio più radicale. Per esempio:

  • Guarda la complessità algoritmica dei tuoi algoritmi core.
  • Se l'applicazione sta spendendo un sacco di tempo per la garbage collection, cerca modi per ridurre la velocità di creazione dell'oggetto.
  • Se le parti chiave dell'applicazione sono ad uso intensivo della CPU e single-thread, cerca opportunità per il parallelismo.
  • Se l'applicazione è già multi-thread, cerca i colli di bottiglia della concorrenza.

Ma ovunque sia possibile, affidati a strumenti e misure piuttosto che all'istinto per indirizzare i tuoi sforzi di ottimizzazione.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow