über mich
Startseite
Links
Programmieren
- CodeOptimierung
- CodeConventionen
- GFA-Basic
Atari
Hardware- Basteleien
Witze
Zitate
Sprüche
Braille
Kunst
Buch-Tip
historisches
Impressum
|
Quellcode Optimierungs-Tips
Auf dieser Seite sammle ich Tips, die ich zur Optimierungen
für geeignet halte. Speziell solche, die kaum Mehraufwand für
den Programmierer bedeuten und man sich nur zu benutzen angewöhnen
muß. Aber auch andere, die nicht für den ständigen Einsatz
gedacht sind.
Vorwort:
Im allgemeinen sollte man vor Codebasteleien zur Optimierung lieber erst
über effizientere Algorithmen und geeignetere Datenstrukturen /
Repräsentationen nachdenken.
Primitives Beispiel:
Lineare-Suche O(n) wird zur Binären-Suche
O(log n), wenn man die Daten sortiert hält.
Mit einer Hash-Funktion (wenn ohne Kollisionen) sogar O(1).
Zudem sollte man die 90%-10%-Regel beachten,
die besagt, daß erfahrungsgemäß 90% der Laufzeit eines
Programms in nur 10% des Quellcodes verbracht werden. Folglich sollte man
nicht seine Energie/Zeit auf die Optimierung wenig benutzter
Code-Abschnitte verschwenden.
Man sollte seine Aufmerksamkeit primär den 10% widmen, die in 90% der
Laufzeit ausgeführt werden.
Sollten sie nicht wissen, welche Stellen in ihrem Programm das sind, stoppen
sie doch die Zeit für einzelne Abschnitte in ihrem Programm, oder
verwenden sie ein Profiling-Tool.
Aus gründen der Verständlichkeit sollten sie immer eine unoptimierte
Version ihres Codes behalten. Diese ist in der Regel für Fremde leichter
verständlich für und kann auch als Referenzimplementierung bei
Funktionstests und als Lieferant für Referenzwerte für
Geschwindigkeitsvergleiche u.ä. verwendet werden.
Optimierungen durch Codebasteleien verschlechtern fast immer die
Lesbarkeit / Wartbarkeit des Codes und sollten, wenn sie zu dieser Kategorie
gehören, nur eingesetzt werden, wenn man nicht vor hat den Code in
Zukunft häufig zu Verändern.
Klassifizierung der Tips:
Typ 0) |
Optimierungen ohne / fast ohne Mehraufwand für den Programmierer.
(gewöhnen sie sich diese Optimierungen an und Profitieren sie
in Zukunft ohne weiteres Nachdenken)
Sollte man immer nutzen, wenn die Lesbarkeit nicht deutlich darunter
leidet. |
Typ 1) |
Optimierungen, die Extra-Aufwand für den Programmierer bedeuten.
Sollten, wegen des Mehraufwandes, nur an kritischen Stellen eingesetzt
werden. |
Typ 2) | Sonstiges Tips |
Wenn sie weitere Optimierungs-Tips kennen, schreiben sie sie mir ruhig, bei
Gefallen füge ich diese dann zu dieser Seite hinzu.
Ich freue mich immer über sachliche Kommentare / Erfahrungsberichte
zu einzelnen Tips. Schreiben sie mir also ruhig eine E-Mail an
Folke_R@gmx.de [Betreff: "HOMEPAGE: programming/opti"].
Wenn Ich den Inhalt ihrer E-Mail auch für andere interessant halte,
werde ich ihren Inhalt bei dem entsprechenden Tip erwähnen.
Typ: 0 |
if .. else statt % |
Wenn man den den % -Operator verwendet, aber weiß, daß bei
x=i%m gilt i>=0 und i<2*m-1 ,
dann ist es besser auf den % -Operator zu verzichten.
|
Negativ-Beispiele: |
Besser: |
while(...)
{
...
x=(x+1)%7;
...
}//wend
|
while(...)
{
...
if(6>x)
x++;
else
x=0;
...
}//wend
|
|
Grund:
Der Rechenaufwand des % -Operators ist offenbar höher, als
der eines Vergleichs und einer Addition.
|
Bemerkung:
Für 0<=i und m eine Potenz von 2
ist der Tip
"
statt
%2 , %4 , %8 , %16 , ... lieber
&1 , &3 , &7 , &15 , ..."
effektiver, als dieser.
|
Gemessene Testwerte |
System / VM | Ergebnis |
PIII (800MHz) "Java HotSpot(TM) Client/Server VM (build 1.4.0_01-b03, mixed mode)" |
77% faster |
|
zurück zum Index [^]
|
Typ: 0 |
wahrscheinlichste Fälle zuerst |
Wenn zwischen mehreren Fällen unterschieden werden muß, dann versuche die
wahrscheinlichsten mit möglichst wenig Aufwand zu erkennen.
Für switch bedeutet das, daß oben die wahrscheinlichsten
Fälle stehen sollten, da die switch -Anweisung vom Compiler in
Code, der Ähnlichkeit mit einer
if...else if...else if...else -Konstruktion
hat, übersetzt wird (zumindest bei Java).
|
Negativ-Beispiele:
int i=0;
while(true)
{
if(1==(i/9)) // 10%
{
i=0;
}
else if(0==(i/9)) // 90%
{
...
}
i++;
}//wend
|
int i=0;
while(true)
{
switch(i/9)
{ case 1: //10%
i=0;
break;
case 0: //90%
...
break;
}//end switch
i++;
}//wend
|
|
Besser:
int i=0;
while(true)
{
if(0==(i/9)) // 90%
{
...
}
else if(1==(i/9)) // 10%
{
i=0;
}
i++;
}//wend
|
int i=0;
while(true)
{
switch(i/9)
{ case 0: //90%
...
break;
case 1: //10%
i=0;
break;
}//end switch
i++;
}//wend
|
|
Grund:
Die einzelnen Fälle werden von oben nach unten durchgetestet, bis ein
Test positiv ist. Stehen die häufigen Fälle oben, dann werden im
Durchschnitt weniger Test durchgeführt.
Weniger durchgeführte Tests bedeuten höhere Geschwindigkeit.
|
Bemerkung:
Wenn sie nicht wissen, wie häufig welche Fälle sind, lassen sie ihr
Programm doch einfach mal zum Test mitzählen.
Wenn es sich um wirklich zeitkritischen Code handelt, lesen sie den
Typ 1-Tip:
"
if-else -Baum statt switch "
|
zurück zum Index [^]
|
Typ: 0 |
benutze final bei Variablen wennimmer möglich |
Variablen oder Parameter sollten, wenn sie später nicht nochmal etwas
zugewiesen werden als final deklariert werden.
Vor allem Methoden-Parameter sind, zumindest bei mir, fast immer
final .
|
Grund:
- Hinweis für den Compiler / die VM . Je mehr man diesen Programmen
hilft desto höher die Chance, dass diese die Hinweise zur Optimierung
nutzen können.
- bessere Lesbarkeit des Codes(Verständnishilfe)
- Selbstkontrolle des Programmierers
|
zurück zum Index [^]
|
Typ: 0 | vermeiden sie unnötige Mehrfachaufrufe von Methoden |
Oft werden Methoden unnötigerweise häufiger mit gleichen Parametern aufgerufen,
obwohl klar ist, daß sie immer das gleiche Ergebnis liefern.
Besonders häufige Beispiele für solche Methoden sind:
.length
.length()
.size()
|
Negativ-Beispiel: for(int i=0; i<a.length(); i++)
{
... //Code der die Länge von a nicht verändert
}//next i
(a.length() wird in jedem Schleifendurchlauf aufgerufen)
|
Besser a): //runter- statt raufzählen
for(int i=a.length()-1; 0<=i; i--)
{
... //Code der die Länge von a nicht verändert
}//next i
(a.length() wird nur einmal, bei der Initialisierung von
i , aufgerufen)
|
Besser b): (wenn Runterzählen nicht in Frage kommt) {//start block
final int len=a.length()
for(int i=0; len>i; i++)
{
... //Code der die Länge von a nicht verändert
}//next i
}//end block
(a.length() wird nur einmal, bei der Initialisierung von
len , aufgerufen)
|
Besser c): (Alternative zu b) ) for(int len=a.length(), i=0; len>i; i++)
{
... //Code der die Länge von a nicht verändert
}//next i
(a.length() wird nur einmal, bei der Initialisierung von
len , aufgerufen)
|
Grund:
Unnötige Arbeit sollte man immer einsparen. Zudem weiß man nie, wie aufwändig
die unnötig oft aufgerufene Methode ist.
|
Bemerkung:
Bei .length für Arrays wissen wir, daß es relativ billig ist.
Aber nicht so billig, wie Einsparen.
|
zurück zum Index [^]
|
Typ: 0 |
verhindere unnötige Mehrfachberechnungen |
Negativ-Beispiel: for(int y=0; 40>y; y++)
{ for(int x=0; 20>x; x++)
{ c[y*40+x]=1;
}//next x
}//next y
(y*40 wird unnötigerweise mit gleichem y immer wieder berechnet)
|
Besser: for(int y=0; 40>y; y++)
{ final int y40=y*40;
for(int x=0; 20>x; x++)
{ c[y40+x]=1;
}//next x
}//next y
|
Grund:
Mehrfachberechnungen kosten unnötig Performance.
|
Bemerkung:
0.) Ich weiß, daß einige Compiler selber versuchen derartige Berechnungen
aus Schleifen, zur Optimierung, auszulagern. Aber bei komplizierteren Code
ist es Compilern meist nicht möglich zu erkennen, ob eine derartige
Veränderung des Codes zulässig ist.
1.)Mir ist klar, daß man diesen Code weiter optimieren könnte.
Was man z.B. noch machen könnte: for(int yOffset=0; (40*40)>yOffset; yOffset+=40)
{ for(int i=yOffset+20-1; 0<=i; i--)
{ c[i]=1;
}//next i
}//next yOffset
|
zurück zum Index [^]
|
Typ: 0 |
statt
%2 , %4 , %8 , %16 , ... lieber
&1 , &3 , &7 , &15 , ... |
Bei m=2, 4, 8, 16 ... ist
x%m == x&(m-1)
für positive, ganzzahlige x .
Diese Optimierung ist so alt, wie das Programmieren selbst.
Diese Optimierung wird z.B von fast jedem C/C++ -Compiler bei
unsigned Variablen automatisch gemacht.
Da java aber keine rein positiven Variablentypen
(außer char ) kennt, darf der java-Compiler derartige
Optimierungen nicht machen.
Da der Programmierer aber weiß, ob seine Zahlen positiv sind,
oder er damit leben kann, daß er für negative Zahlen auch positive Reste
erhält, kann er selbst diese Optimierung nutzen.
|
Negativ-Beispiele: |
Besser: |
y=i%32;
d%=64;
|
y=i&31;
d&=63;
|
|
Grund:
Der & -Operator ist eine reine Bitverknüpfung ohne Rechenaufwand,
während der % -Operator auf quasi jedem Computer langsamer ist.
|
Bemerkung:
Das Verhalten bei negativen Zahlen ist mir persönlich bei der Variante
mit & sogar lieber als das der % -Variante.
|
Bemerkung2:
Der Entscheidung der Java-Designer keine unsigned Typen
in die Sprache aufzunehmen verdanken wir es, daß diese Optimierung nicht vom
Compiler gemacht werden kann :-(
|
Bemerkung3:
Diese Optimierung bring mehr, als der Tip:
"
if-else statt % "
Der ist dafür aber für beliebige m anwendbar.
|
Gemessene Testwerte |
System / VM | Ergebnis |
PIII (800MHz) "Java HotSpot(TM) Server VM (build 1.4.0_01-b03, mixed mode)" |
41% faster |
PIII (800MHz) "Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)" |
92% faster |
|
zurück zum Index [^]
|
Typ: 0 |
statt
/2 , /4 , /8 , /16 , ... lieber
>>1 , >>2 , >>3 , >>4 , ... |
Teilen durch Potenzen von 2 (2, 4, 8, 16, 32 ...) bei positiven ganzen
Zahlen sollte man durch Bitschieben (um 1, 2, 3, 4, 5, ...) ersetzen.
Diese Optimierung ist so alt, wie das Programmieren selbst.
Teilt man eine negative Zahl auf diese Weise, ist Das Ergebnis nicht
genau gleich, da das Bitschieben bei negativen Zahlen immer aufrundet statt
abzurunden.
Diese Optimierung wird z.B von fast jedem C/C++ -Compiler bei
unsigned Variablen automatisch gemacht.
Da java aber keine rein positiven Variablentypen
(außer char ) kennt, darf der java-Compiler derartige
Optimierungen nicht machen.
Da der Programmierer aber weiß, ob seine Zahlen positiv sind,
oder er damit leben kann, daß er für negative Zahlen aufgerundet wird,
kann er selbst diese Optimierung nutzen.
|
Negativ-Beispiele: |
Besser: |
i=j/16;
h/=256;
|
i=j>>4;
h>>=8;
|
|
Grund:
Bitschiebereien sind auf allen mir bekannten Systemen deutlich
(um ein vielfaches) schneller als Dividieren.
|
Bemerkung:
Der Entscheidung der Java-Designer keine unsigned Typen
in die Sprache aufzunehmen verdanken wir es, daß diese Optimierung nicht vom
Compiler gemacht werden kann :-(
|
Gemessene Testwerte |
System / VM | Ergebnis |
PIII (800MHz) "Java HotSpot(TM) Server VM (build 1.4.0_01-b03, mixed mode)" |
92% faster |
PIII (800MHz) "Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)" |
84% faster |
|
zurück zum Index [^]
|
Typ: 0 |
statt
*2 , *4 , *8 , *16 , ... lieber
<<1 , <<2 , <<3 , <<4 , ... |
Multiplizieren mit Potenzen von 2 (2, 4, 8, 16, 32 ...) bei ganzen
Zahlen sollte man durch Bitschieben (um 1, 2, 3, 4, 5, ...) ersetzen.
Diese Optimierung ist so alt, wie das Programmieren selbst.
Diese Optimierung wird z.B von fast jedem C/C++ -Compiler
Ganzzahlvariablen automatisch gemacht.
|
Negativ-Beispiele: |
Besser: |
i=j*16;
h*=256;
|
i=j<<4;
h<<=8;
|
|
Grund:
Bitschiebereien sind auf allen mir bekannten Systemen
schneller als Multiplizieren.
|
Bemerkung:
Auch, wenn man glaubt, daß der Compiler diese Optimierung macht,
kann es nicht schaden sie selbst vorzunehmen.
|
Gemessene Testwerte |
System / VM | Ergebnis |
PIII (800MHz) "Java HotSpot(TM) Server VM (build 1.4.0_01-b03, mixed mode)" |
17% faster |
PIII (800MHz) "Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)" |
13% slower |
|
zurück zum Index [^]
|
Typ: 0 |
statt
3-x , 7-x , 15-x , ... lieber
3 XOR x , 7 XOR x ,
15 XOR x , ... |
Wenn sie von positiven Zahl n eine Zahl x abziehen wollen,
n=2k-1 und x<=n , dann ist
das bitweise exklusiv-oder (XOR) gleich der Subtraktion.
Also nur für Werte von x , so daß das Ergebnis
positiv bleibt!
Bemerkung1: Die Bitverknüpfung XOR wird in java mit
^ ausgedrückt.
Bemerkung2: Mir ist klar, daß diese Optimierung nur selten anwendbar
ist.
|
Negativ-Beispiele: |
Besser: |
pos=255-x1;
x=7-x;
|
pos=255^x1;
x=7^x;
|
|
Grund:
Bit-Operationen sind, auf allen mir bekannten Systemen, schneller als
Rechenoperationen. (eventuell aber nur sehr wenig)
|
Bemerkung:
n=2k-1 sind Zahlen, die in der binären
Darstellung nur aus Einsen bestehen. Die oben zur Optimierung angegebenen
Subtraktionen (binäre Zahlendarstellung!), sind solche, bei denen beim
Berechnen keine Überträge entstehen.
Wenn der Programmierer aufgrund der in seinem Programm vorkommenden Zahlen
weiß, daß in der Subtraktion (binäre Zahlendarstellung!) keine Überträge
vorkommen, kann auch in solchen Fällen XOR statt der Subtraktion verwenden.
(Aber Vorsicht, sie sollten ganz sicher sein!)
|
Gemessene Testwerte |
System / VM | Ergebnis |
PIII (800MHz) "Java HotSpot(TM) Server VM (build 1.4.0_01-b03, mixed mode)" |
32% faster |
PIII (800MHz) "Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)" |
8% faster |
|
zurück zum Index [^]
|
Typ: 0 |
Reihenfolge von Bedingungen durchdenken |
Bei Bedingungen, die aus mehreren Teilbedingungen bestehen sollte man,
auf die Reihenfolge achten.
Bedingungen werden von links nach rechts ausgewertet!
Wenn man z.B. den Fall:
if((Bedingung1) && (Bedingung2))
Wenn beide Bedingungen ähnlich teuer sind, dann sollte man den, der am
wahrscheinlichsten false liefert nach vorn stellen.
(wenn Bedingung1 false liefert, wird Bedingung2 gar nicht
ausgewertet.)
Kriterien der Reihenfolge sollten sein:
- Aufwand beim Prüfen der Bedingungen
- bei und-Verknüpfung wahrscheinlicher fehlschlagende Bedingungen nach links
- bei oder-Verknüpfung wahrscheinlicher erfolgreiche Bedingungen nach links
|
Grund:
So minimiert man den durchschnittlichen Aufwand bei der Auswertung der
Gesamtbedingung.
|
zurück zum Index [^]
|
Typ: 1 |
If-else -Baum statt switch |
Eine switch -Verzweigung wird vom Compiler in eine Art von
hintereinander stehende if -Anweisungen übersetzt.
(Da immer die selbe variable getestet wird, gibt es einen speziellere Bytecode
als wenn man selbst lauter if -Anweisungen schreibt.)
Bei gleicher Wahrscheinlichkeit aller n Fälle,
werden im Durchschnitt n/2
Vergleiche gemacht.
Die Idee diese Tips ist es die Fälle zu ordnen, und dann durch
fortlaufende Intervallhalbierung den richtigen Fall zu finden.
Das reduziert die Anzahl der durchschnittlichen Vergleiche auf
log2n .
Bildlich ergibt das einen binär-verzweigten Entscheidungsbaum.
Sollten die Fälle nicht alle gleich wahrscheinlich sein, und man die
Wahrscheinlichkeiten der Einzelfälle kennen, kann man statt das Intervall
in jedem Schritt zu halbieren auch eine andere Aufteilung wählen, so daß
die Wahrscheinlichkeit der entstehenden beiden Intervalle annähernd
gleich ist.
(siehe: Huffman-Kodierung, Shannon-Fano-Kodierung
[siehe WIKIPEDIA]).
|
Negativ-Beispiel: |
Besser: |
int j=-1;
switch(i)
{ case 0:j=299;
break;
case 1:j=298;
break;
case 2:j=297;
break;
case 3:j=296;
break;
case 4:j=295;
break;
case 5:j=294;
break;
case 6:j=293;
break;
case 7:j=292;
break;
}//end-switch
return j;
|
int j=-1;
if(4>i) // 0 .. 3
{ if(2>i) // 0,1
{ if(0==i)
j=299;
else if(1==i)
j=298;
}//endif
else // 2,3
{ if(2==i)
j=297;
else if(3==i)
j=296;
}//end-else
}//endif
else // 4 .. 7
{ if(6>i) // 4,5
{ if(4==i)
j=295;
else if(5==i)
j=294;
}//endif
else //6,7
{ if(6==i)
j=293;
else if(7==i)
j=292;
}//end-else
}//end-else
return j;
|
|
Grund:
Wie in der Beschreibung erklärt, sinkt die Anzahl der durchschnittlichen
Vergleiche von O(n) auf
O(log n) .
Damit rentiert sich dieser Tip mit zunehmender Anzahl von Fällen immer mehr.
|
Bemerkung:
In einem Test für gleich wahrscheinliche Fälle hat sich dieser Tip
bei mir schon bei 8 verschiedenen Fällen (manchmal sogar schon bei 4)
gelohnt.
|
Bemerkung:
Im Beispiel kann man sogar bei den innersten else if
nur else schreiben, da dort immer nur noch der eine Fall
möglich ist. (weil alle Zahlen von 0 bis 7 vorkommen).
|
Gemessene Testwerte (16-Fällle) |
System / VM | Ergebnis |
PIII (800MHz) "Java HotSpot(TM) Server VM (build 1.4.0_01-b03, mixed mode)" |
17% faster |
PIII (800MHz) "Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)" |
46% faster |
|
zurück zum Index [^]
|
Typ: 2 |
Rekursionen vermeiden |
Viele Algorithmen werden rekursiv erklärt, können aber auch mit
Schleifen implementiert werden. In solchen Fällen sollte
man die nicht rekursive Variante bevorzugen, auch wenn der Programmcode
meist komplizierter erscheint.
Viele Algorithmen basieren auf der Idee "divide and conquer"
("Teile und herrsche")
[siehe WIKIPEDIA] und sind daher schon
von ihrer Idee her rekursiv.
Daher sind sie auch besonders elegant und leicht verständlich, wenn
sie als rekursives Programm geschrieben werden. Rekursionen bedeuten aber
besonderen Aufwand für den Computer. Deshalb gibt es für viele Algorithmen
auch eine nicht-rekursive Variante, die zwar meist komplizierter aussieht,
aber fast immer schneller und speichersparender ist.
|
Negativ-Beispiel: int fakultaet(final int n)
{
if(1>=n)
return 1;
return fakultaet(n-1)*n;
}
|
Besser: int fakultaet(final int n)
{
int erg=1;
for(int i=n; 1<i; i--)
erg*=i;
return erg;
}
|
Grund:
Bei einer Rekursion (wenn der Compiler sie nicht selbst zu einer
Schleife optimieren kann ("Optimierung von Endrekursion"
[WIKIPEDIA])),
Müssen, wie bei jedem Methoden-Aufruf alle lokalen Variablen und
Prozessor-Register gesichert, ein Sprung zum Code der Methode durchgeführt,
...
pro Rekursionsschritt gemacht werden.
Dieser nicht unerhebliche Aufwand entfällt bei einer nicht-rekursiven
Lösung, die dadurch, auch wenn sie komplexer aussieht, meist schneller
ist und weniger Speicher benötigt.
|
Bemerkung:
Die Berechnung der Fakultät ist ein Beispiel, das sich besonders
leicht in eine Schleifenvariante bringen läßt, da der rekursive Algorithmus
endrekursiv ist [WIKIPEDIA].
Dieser spezielle Rekursionstyp wird von vielen Compilern erkannt und
selbst zu einer Schleife optimiert (aber nicht von jedem Compiler
:-( ). Komplizierte Rekursionen
können aber nicht vom Compiler optimiert werden, da das Auflösen in
Schleifen oft zusätzliche Verwaltungsstrukturen benötigt, die der
Programmierer sich problemspezifisch überlegen muß.
|
Gemessene Testwerte |
System / VM | Ergebnis |
PIII (800MHz) "Java HotSpot(TM) Server VM (build 1.4.0_01-b03, mixed mode)" |
35% faster |
PIII (800MHz) "Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)" |
43% faster |
|
zurück zum Index [^]
|
Typ: 2 |
Spezielle Klassen schreiben |
Wenn es eine Klasse (z.B. in einer großen Bibliothek) gibt, die sie
verwenden könnten, dann ist diese nicht unbedingt optimal für ihr Problem.
Zum Beispiel Containerklassen sind in Bibliotheken meist so geschrieben,
daß sie eine weite Spanne von Zugriffsarten/Manipulationen erlauben.
Aber z.B. Einfügen/Löschen ist je nach Implementierung sehr verschieden
wenn sie am Position 0, in der Mitte oder am Ende einer Datenstruktur
gemacht werden. Deshalb gibt es auch in den Bibliotheken so viele
verschiedene Containerklassen mit oft sehr ähnlicher, oder gleicher
Pragrammierschnittstelle.
Hat man aber einen sehr speziellen Anwendungsfall lohnt es sich oft
selbst eine für diesen Fall optimierte Implementation zu schreiben.
|
Grund:
Allgemeine Lösungen sind fast nie optimal für einen speziellen Fall,
wie eine maßgeschneiderte Lösung.
|
zurück zum Index [^]
|
Java-Spezifisches
java Typ: 0 |
ArrayList statt Vector |
Verwenden sie java.util.ArrayList statt
java.util.Vector .
Der Unterschied besteht darin, daß in der Klasse Vector
die Methoden synchronized sind, was zu geringerer
Geschwindigkeit führt. In der Klasse ArrayList
ist nicht synchronized .
Oft braucht man die Synchronisation jeder einzelnen Methode nicht.
Wenn doch, kann man die Zugriffe auf ArrayList -Objekte ja
selbst synchronisieren.
|
zurück zum Index [^]
|
java Typ: 0 |
StringBuffer statt String |
Wenn sie eine Zeichenkette zusammenbauen wollen, dann vermeiden sie es
den '+ '-Operator für Strings zu verwenden. Dieser ist
relativ langsam, da immer neue Objekte erzeugt und der Inhalt kopiert
werden.
Vorzuziehen ist es die Zeichenkette in einem
java.lang.StringBuffer -Objekt
zusammenzubauen und, wenn er fertig ist in einen java.lang.String
umzuwandeln. Das ist deutlich schneller.
|
zurück zum Index [^]
|
java Typ: 0 |
arraycopy verwenden |
Wenn sie ein Array kopieren wollen, verwenden sie nicht eine
selbstprogrammierte Schleife, sondern die
java.lang.System.arraycopy(...) Methode.
|
zurück zum Index [^]
|
Hinweis zum Test-Java-Applet
Der Wert der Testergebnisse spiegeln nicht den Gewinn/Verlust der Optimierung
wieder, sonder nur die Laufzeiten im Falle meines speziellen Testprogramms.
Schleifen, Rechenoperationen u.ä. werden nicht rausgerechnet! Die Test
sollen nur zeigen, das tatsächlich eine Optimierung stattfindet und eine
Vorstellung verschaffen, ob sie eher gering oder erheblich ist.
Die Werte schwanken auch stark mit der verwendeten Java-VM und können bei
ihnen im Browser von den Werten auf der Konsole abweichen.
Hier der Programmcode meiner Tests (testJavaSource.zip)
Sollten sie Verbesserungsvorschläge für die Tests haben, schicken
sie mir ruhig den Programmcode eines besseren Tests.
zurück zur Programmier-Seite des Folkes
zurück zur Startseite des Folkes
Stand: 16.12.2007 (Inhaltlich: 21.08.2007) Brief an Folke:(Folke_R@gmx.de)
|