In beiden Fällen werden um einen einzigen String der gewünschten Länge aufzubauen, in der Größenordnung von 1000 kurzlebige Objekte als Zwischenresultate aufgebaut, nur um sofort wieder zerstört zu werden. Das gleiche Kunststück ist natürlich auch in C möglich, wenn man Speicherbereiche mit realloc Byte-weise vergrößert. |
In beiden Fällen werden um einen einzigen String der gewünschten Länge aufzubauen, in der Größenordnung von N kurzlebige Objekte als Zwischenresultate aufgebaut, nur um sofort wieder zerstört zu werden. Das gleiche Kunststück ist natürlich auch in C möglich, wenn man Speicherbereiche mit realloc Byte-weise vergrößert. |
Alternativ dazu könnte man in Java z.B. mit einem StringBuffer oder mit: |
Alternativ dazu könnte man in Java z.B. mit einem StringBuffer entweder so [[Code] public static final String StringCreateCharLen?(char c,int len) { StringBuffer? string = new StringBuffer?(); for(int i=0; i<len; i++) { string.append(c); } return string.toString(); } ] (etwa log2(len/16) temporäre Arrays im StringBuffer?) oder so [[Code] public static final String StringCreateCharLen?(char c,int len) { StringBuffer? string = new StringBuffer?(len); // <--- !!! for(int i=0; i<len; i++) { string.append(c); } return string.toString(); } ] (keine temporären Arrays) oder mit: |
Bei häufigerem Gebrauch mit gleichem Zeichen c bietet sich außerdem das Caching (SprachPolizei?) des String(Buffer)s an: [[Code] public class CharacterRepeater? { private char character; private StringBuffer? concatenation = new StringBuffer?(); public CharacterRepeater?(char character) { this.character = character; } public String concatenation(int length) { ensureLength(length); return concatenation.toString().substring(0, length); } private void ensureLength(int length) { int oldLength = concatenation.toString().length(); concatentation.ensureCapacity(length); for (int l = oldLength; l < concatenation.capacity; l++) { concatenation.append(character); } } } ] |
Standardbeispiel |
Das Standardbeispiel, wie man mit kurzlebigen Objekten die Performance ruiniert ist uralt und stammt in seiner Ur-Form noch aus alten BASIC-Zeiten (hatte immer schon dynamische Speicherverwaltung und GC bezüglich Strings). Ziel des Beispiels ist der Aufbau einer Zeichenkette aus N (z.B. 1000) Zeichen c$:
![]() |
|
![]() |
|
In beiden Fällen werden um einen einzigen String der gewünschten Länge aufzubauen, in der Größenordnung von N kurzlebige Objekte als Zwischenresultate aufgebaut, nur um sofort wieder zerstört zu werden. Das gleiche Kunststück ist natürlich auch in C möglich, wenn man Speicherbereiche mit realloc Byte-weise vergrößert.
Alternativ dazu könnte man in Java z.B. mit einem StringBuffer entweder so
![]() |
|
(etwa log2(len/16) temporäre Arrays im StringBuffer?)
oder so
![]() |
|
(keine temporären Arrays)
oder mit:
![]() |
|
die temporären, kurzlebigen Objekte vermeiden. Der Unterschied ist gewaltig.
Bei häufigerem Gebrauch mit gleichem Zeichen c bietet sich außerdem das Caching (SprachPolizei?) des String(Buffer)s an:
![]() |
|
Das gleiche als schlechtes Beispiel in SprachePython:
![]() |
|
![]() |
|
Variationen zu diesem Thema:
Ein andere Dimension dieses Problem findet sich bei temporären anonymen Variablen beim Auswerten von Ausdrücken über komplexe Datentypen.