Java Language
Java Performance Tuning
Sök…
Allmän riktlinje
Internet är packat med tips för prestandaförbättring av Java-program. Det kanske toppnumret är medvetenhet. Det betyder:
- Identifiera möjliga prestandaproblem och flaskhalsar.
- Använd analys- och testverktyg.
- Känner till god praxis och dålig praxis.
Den första punkten bör göras under designstadiet om man talar om ett nytt system eller modul. Om man talar om äldre kod kommer analys- och testverktyg in i bilden. Det mest grundläggande verktyget för att analysera din JVM-prestanda är JVisualVM, som ingår i JDK.
Den tredje punkten handlar mest om erfarenhet och omfattande forskning, och naturligtvis råa tips som dyker upp på denna sida och andra, som denna .
Minska mängden strängar
I Java är det för "lätt" att skapa många sträng-instanser som inte behövs. Det och andra orsaker kan göra att ditt program har massor av strängar som GC är upptagen med att städa upp.
Några sätt du kan skapa strängförekomster:
myString += "foo";
Eller värre, i en loop eller rekursion:
for (int i = 0; i < N; i++) {
myString += "foo" + i;
}
Problemet är att varje +
skapar en ny sträng (vanligtvis eftersom nya kompilatorer optimerar vissa fall). En möjlig optimering kan göras med hjälp av StringBuilder
eller StringBuffer
:
StringBuffer sb = new StringBuffer(myString);
for (int i = 0; i < N; i++) {
sb.append("foo").append(i);
}
myString = sb.toString();
Om du bygger långa strängar ofta (till exempel SQL) använder du ett API för strängbyggnad.
Andra saker att tänka på:
- Minska användningen av
replace
,substring
etc. - Undvik
String.toArray()
, särskilt i ofta åtkomna kod. - Loggutskrifter som är avsedda att filtreras (till exempel på grund av loggnivå) bör inte genereras (loggnivå bör kontrolleras i förväg).
- Använd bibliotek som detta om det behövs.
- StringBuilder är bättre om variabeln används på ett icke-delat sätt (över trådar).
Ett evidensbaserat tillvägagångssätt för Java-prestandatuning
Donald Knuth citeras ofta för att säga detta:
"Programmerare slösar enorma mängder tid med att tänka på eller oroa sig för hastigheten på icke-kritiska delar av sina program, och dessa försök till effektivitet har faktiskt en stark negativ inverkan när felsökning och underhåll beaktas. Vi bör glömma små effektivitet, säga om 97% av tiden : för tidig optimering är roten till allt ont. Men vi borde inte överföra våra möjligheter i de kritiska 3%. "
Med tanke på detta visstips är här det rekommenderade förfarandet för att optimera program:
Först och främst design och kod ditt program eller bibliotek med fokus på enkelhet och korrekthet. Till att börja med lägger du inte mycket på prestanda.
Få det till ett fungerande tillstånd och (idealiskt) utveckla enhetstester för viktiga delar av kodbasen.
Utveckla en prestanda benchmark för applikationsnivå. Riktmärket ska täcka prestandakritiska aspekter av din applikation och bör utföra en rad uppgifter som är typiska för hur applikationen kommer att användas i produktionen.
Mät prestanda.
Jämför det uppmätta resultatet mot dina kriterier för hur snabbt applikationen behöver vara. (Undvik orealistiska, ouppnåeliga eller obestämliga kriterier som "så snabbt som möjligt".)
Om du har uppfyllt kriterierna, STOPP. Ditt jobb är gjort. (Varje ytterligare ansträngning är förmodligen slöseri med tid.)
Profilera applikationen medan den kör ditt prestanda benchmark.
Undersök profileringsresultaten och välj de största (opimiserade) "hotspots för prestanda"; dvs delar av koden där applikationen verkar spendera mest tid.
Analysera hotspot-kodavsnittet för att försöka förstå varför det är en flaskhals och tänk på ett sätt att göra det snabbare.
Implementera det som en föreslagen kodändring, test och felsökning.
Kör riktmärket igen för att se om kodändringen har förbättrat prestandan:
- Om Ja, gå tillbaka till steg 4.
- Om Nej, släpp sedan ändringen och gå tillbaka till steg 9. Om du inte gör några framsteg, välj en annan hotspot för din uppmärksamhet.
Så småningom kommer du till en punkt där applikationen antingen är tillräckligt snabb, eller så har du övervägt alla viktiga hotspots. Just nu måste du stoppa denna strategi. Om en kodsektion konsumerar (säg) 1% av den totala tiden, kommer till och med en 50% förbättring bara att göra applikationen 0,5% snabbare totalt sett.
Det är uppenbart att det finns en punkt bortom vilken hotspot-optimering är ett slöseri med ansträngning. Om du kommer till den punkten måste du ta en mer radikal inställning. Till exempel:
- Titta på den algoritmiska komplexiteten för dina kärnalgoritmer.
- Om applikationen lägger ner mycket tid på skräpuppsamling, leta efter sätt att minska hastigheten på att skapa objekt.
- Om nyckeldelar i applikationen är CPU-intensiva och entrådiga, leta efter möjligheter till parallellitet.
- Om applikationen redan är flertrådad, leta efter flaskhalsar för samtidighet.
Men när så är möjligt, lita på verktyg och mätning snarare än instinkt för att rikta din optimeringsinsats.