StringBuilder vs. Stringverkettung

Status
Nicht offen für weitere Antworten.

Youlian

Mitglied
Hallo,

ich wollte mal dem Interesse halber nachfragen was schneller ist:

Code:
StringBuilder qry = new StringBuilder();
for(... 2 verschachtelte Schleifen ...) {
  qry.append("(" + columns[j] + " = '" + searchPatterns[i] + "')");
}

... oder ...

Code:
StringBuilder qry = new StringBuilder();
for(... 2 verschachtelte Schleifen ...) {
  qry.append("(");
  qry.append(columns[j]);
  qry.append(" = '");
  qry.append(searchPatterns[i]);
  qry.append("')");
}

Das '+' für die Stringverkettung ist in Java eine der wenigen (der einzige?! mit fällt grad keiner anderer ein ^^) überladene Operator.
Weiß jemand welche der beiden Methoden schneller ist? - Ich glaube mich dunkel daran zu erinnern, irgendwo einmal gelesen zu haben, das man die exzessive Anwendung von Stringverkettung vermeiden soll. Da da bei jeder Verkettung ein neues String Objekt mit der größe der beiden zu verkettenden angelegt wird. (Da Strings ja immutable sind)

Ist Stringverkettung also gleichzusetzen mit (Bsp aus der API):
"to".concat("get").concat("her") returns "together" ??

Ist das richtig so? - Oder doch ganz anders? ;-)
Kann mir da jemand kurz die internas erklären und vor allem: Was ist jetzt schneller?

lg
Youlian
 
S

SlaterB

Gast
StringBuilder ist schneller als +, das sollte klar sein,
ein StringBuilder erzeugt keine Zwischenstrings,

kannst deinen Code auch 1 Mio. mal ausführen und die Systemzeit messen,
bei deutlich weniger Strings in Mini-Anwendungen wirst du aber keinen Unterschied merken

string.concat(string) erzeugt auch Zwischenstrings wie +,
scheint das gleiche zu sein, kann ich persönlich aber nicht genau sagen
 

Youlian

Mitglied
Ok, Danke für die (sehr) schnelle Antwort.
Bin trotzdem noch dankbar für eine längere Ausführung oder aber auch über einen Link zum Thema.

lg
Youlian
 

mephi

Bekanntes Mitglied
als ich es mal getestet habe kam dabei raus dass ein StringBuilder ca doppelt so schnell ist.
ob mein test sehr aussage kräftig war kann ich nicht sagen ;)
bin weniger der analytiker :)
 

Wildcard

Top Contributor
Je nach Anwendungsfall kann das auch 1000 mal schneller sein. Es hängt davon ab wie die Strings verkettet werden.
Eigentlich können Strings nämlich gar nicht verkettet werden, sondern es werden im schlimmsten Fall Millionen von StringBuffern instanziert.
 

krel

Mitglied
Wird der StringBuilder nicht intern sowieso verwendet? Habe letztens mal ne Class Datei dekompiliert und festgestellt, dass dort nur der StringBuilder verwendet wird,anstatt der "+"?

Krel
 

Saxony

Top Contributor
Hiho,

habe das mal gestestet.

Code:
private static void stringPlus() {
		
    String s = "";
		
    for(int i = 100000; i > 0; i--) {
		
        s += "a";
    }
}

Analog dazu noch Methoden mit:

Code:
s.concat("a");
StringBuilder.append("a");
StringBuffer.append("a");

Resultat war (in millisekunden bei 100.000 bzw. 2.000.000 Durchläufen jeweils):

Code:
String + String (100k) : 24001
String.concat (100k) : 12094
StringBuilder (2M) : 94
StringBuffer (2M) : 141

Was verwundert: concat ist doch um einiges fixer als +.
Die Abweichung zwischen StringBuilder und StringBuffer liegt an der threadsicheren Implementierung des Buffers.

Ergänzung:

bei StringBuilder und StringBuffer lohnt es sich dem Konstruktor schon zu sagen wie groß man es brauch.

Code:
StringBuilder s = new StringBuilder(10000000);
StringBuffer s = new StringBuffer(10000000);

ohne InitialWert:
StringBuilder (10M) : 609
StringBuffer (10M) : 1296

mit InitialWert:
StringBuilder (10M) : 469
StringBuffer (10M) : 1187

Ohne Initialwert treten zum Beispiel bei 20M Durchgängen "Out of of Memory-Exceptions" auf, welche mit vorherigem Initialwert nicht auftreten.

Edit:
Werte für s = s.concat("a") angepasst.

bye Saxony
 

Wildcard

Top Contributor
Bitte den gesamten Code posten, den du zum testen verwendet hast.
Mikrobenchmarks sind schwieriger zu realisieren als den meisten klar ist.
Insbesondere bei Strings ist da Vorsicht geboten.
 

Saxony

Top Contributor
Hiho,

hier isser:

Code:
public class StringTester {
	
	public static void main(String[] args) {
	
		long timeStart = System.currentTimeMillis();
		stringPlus();
		System.out.println("String + String (100k) : " + (System.currentTimeMillis() - timeStart));
		timeStart = System.currentTimeMillis();
		stringConcat();
		System.out.println("String.concat (100k) : " + (System.currentTimeMillis() - timeStart));
		timeStart = System.currentTimeMillis();
		stringBuilder();
		System.out.println("StringBuilder (10M) : " + (System.currentTimeMillis() - timeStart));
		timeStart = System.currentTimeMillis();
		stringBuffer();
		System.out.println("StringBuffer (10M) : " + (System.currentTimeMillis() - timeStart));
	}
	
	private static void stringPlus() {
		
		String s = "";
		
		for(int i = 100000; i > 0; i--) {
		
			s += "a";
		}
	}
	
	private static void stringConcat() {
		
		String s = "";
		
		for(int i = 100000; i > 0; i--) {
		
			s.concat("a");
		}
	}
	
	private static void stringBuilder() {
		
		StringBuilder s = new StringBuilder(10000000);
		
		for(int i = 10000000; i > 0; i--) {
		
			s.append("a");
		}
		
		s.toString();
	}
	
	private static void stringBuffer() {
		
		StringBuffer s = new StringBuffer(10000000);
		
		for(int i = 10000000; i > 0; i--) {
		
			s.append("a");
		}
		
		s.toString();
	}
}

bye Saxony
 

Wildcard

Top Contributor
Ok, der Test ist definitiv falsch.
Zwei wichtige Dinge zu beachten:

1. Du gibst der VM die Gelegenheit zu optimieren, wodurch die späteren Resultate schneller werden als die ersten und im dümmsten Fall die ganze Schleife ersetzt wird. Immer nur ein Test gleichzeitig!

2. String sind immutable, weil die VM sie munter im ganzen und partiell wiederverwertet.
concat kann davon vermutlich massiv profitieren, weil du mit String + String den Pool schon gut gefüllt hast.

Deine Ergebnisse sind IMO unbrauchbar.
 

Saxony

Top Contributor
So naja - auch wenn ich für jede Methode eine eigene Anwendung schreibe, ändert sich nix an den Laufzeiten.

bye Saxony
 

Wildcard

Top Contributor
Zum einen glaube ich dir nicht, das sich die Laufzeiten nicht verändern, zum anderen ist das kein praxisnahes Beispiel, weil du immer wieder den gleichen String aus dem Pool fischst und als letztes ist es sowieso ziemlich sinnlos concat, +, builder und buffer mit völlig unterschiedlichen Werten zu testen.
 
S

SlaterB

Gast
ihr seid ja paar Streithähne, mit so komischen Argumenten..

> 1. Du gibst der VM die Gelegenheit zu optimieren, wodurch die
> späteren Resultate schneller werden als die ersten und im
> dümmsten Fall die ganze Schleife ersetzt wird. Immer nur ein
> Test gleichzeitig!

? Beispiel ?

> 2. String sind immutable, weil die VM sie munter im ganzen und
> partiell wiederverwertet.
> concat kann davon vermutlich massiv profitieren, weil du mit
> String + String den Pool schon gut gefüllt hast.

? lächerlich
dreh doch einfach die Reihenfolge um oder führe die Tests abwechselnd durch.. (damit fällt auch 'späteren Resultate schneller' weg ;) )

> zum anderen ist das kein praxisnahes Beispiel, weil du immer wieder den gleichen String aus dem Pool fischst

du meinst, Java hat intern irgendeine Optimierung für concat vorgesehen,
die es für + nicht gibt?
selbst wenn: wäre das schlimm?, geht doch gerade darum, den Unterschied darzustellen?

> letztes ist es sowieso ziemlich sinnlos concat, +, builder und buffer mit völlig unterschiedlichen Werten zu testen

? es ist doch immer nur das eine 'a',
meinst du die Anzahlen? für + und concat ist es die gleiche,
Buffer und Builder sind eh außer Konkurrenz

der Code von Saxony hat natürlich einen gravierenden Fehler:
s.concat("a");
statt
s = s.concat("a");


richtiger ist es so (auch noch mit zufälligen Buchstaben statt nur a, das dürfte das Wegoptimieren schwer machen ;) ):

Code:
public class StringTester
{
    static int k = 30000;

    public static void main(String[] args)
    {
        stringConcat();
        stringPlus();
        stringConcat();
        stringPlus();
        stringConcat();
        stringPlus();
    }

    private static void stringPlus()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            s += (char)(Math.random() * 200);
        }
        System.out.println("String +     : " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringConcat()
    {
        long timeStart = System.currentTimeMillis();

        String s = "";
        for (int i = k; i > 0; i--)
        {

            s = s.concat(String.valueOf((char)(Math.random() * 200)));
        }
        System.out.println("String.concat: " + (System.currentTimeMillis() - timeStart));
    }
}



Ausgabe:

String.concat: 1030
String +     : 2419
String.concat: 1030
String +     : 2575
String.concat: 1014
String +     : 2528

irgendwie schneller ist concat also trotzdem,
wenn man a statt des Zufallsstrings nimmt, ändert sich übrigens praktisch gar nix
 

Saxony

Top Contributor
SlaterB hat gesagt.:
ihr seid ja paar Streithäne, mit so komischen Argumenten..

Ich streite ja gar net. ;)

SlaterB hat gesagt.:
der Code von Saxony hat natürlich einen gravierenden Fehler:
s.concat("a");
statt
s = s.concat("a");

Danke für den Hinweis! Deswegen war mein concat so fix. Hehe!
Yep also concat ist also so 50-60% schneller als die reine "Stringaddition".

Im Endeffekt hatte ich also bis auf den Tippfehler schon den Finger drauf. ;)

bye Saxony
 

Wildcard

Top Contributor
Für was?
Spitzen Argument :toll:
dreh doch einfach die Reihenfolge um oder führe die Tests abwechselnd durch.. (damit fällt auch 'späteren Resultate schneller' weg
Besser noch: Ein Testlauf pro Methode, so schließt man Seiteneffekte besser aus.

irgendwie schneller ist concat also trotzdem
Genau das lässt sich nicht pauschal schließen.
Der Compiler wandelt String + String in einen StringBuilder (welcher nach deiner Meinung ja schon ausser Konkurrenz ist :wink: ) um, während concat einfach ein neues Array allokiert in das beide Strings passen. Die Sache hängt also massiv von den Laufzeitdaten ab, weshalb ich auch darauf hinweise, dass Mikrobenchmarks immer sehr kritisch zu betrachten sind und genau überlegt sein wollen.
 

Saxony

Top Contributor
Wildcard hat gesagt.:
Besser noch: Ein Testlauf pro Methode, so schließt man Seiteneffekte besser aus.

Hatte ich ja schon gemacht mit gleichem Ergebnis.

Aber das glaubste mir ja net. :?:

Wildcard hat gesagt.:
Zum einen glaube ich dir nicht, das sich die Laufzeiten nicht verändern

???:L

Dann musstes halt ma selber schreibn - vielleicht glaubste dir selber ja eher mal. :applaus:

bye Saxony
 
S

SlaterB

Gast
Wildcard hat gesagt.:
für deine Optimierungstheorien,
es zeigt sich doch sehr deutlich, dass absolut gar nix passiert

irgendwie schneller ist concat also trotzdem
Genau das lässt sich nicht pauschal schließen.
Der Compiler wandelt String + String in einen StringBuilder um, während concat einfach ein neues Array allokiert in das beide Strings passen. Die Sache hängt also massiv von den Laufzeitdaten ab, weshalb ich auch darauf hinweise, dass Mikrobenchmarks immer sehr kritisch zu betrachten sind und genau überlegt sein wollen.
und was bedeutet das?
was heißt Laufzeitdaten? wieso hängt das von irgendwas ab?
wenn man das 10x ausführt, passiert 10x das gleiche, was genau soll in irgendeiner Form zu beachten sein?


dass andere VM oder andere Compiler ein ganz anderes Programm draus machen gilt natürlich für jedes Programm der Welt..
(jetzt bin ich der Streithahn, ich weiß, mach ich ja so gerne ;) )
 

Wildcard

Top Contributor
für deine Optimierungstheorien,
es zeigt sich doch sehr deutlich, dass absolut gar nix passiert
Und diese Aussage triffst du pauschal für jeden Hotspot/JIT, ohne auch nur den Bytecode gesehen zu haben, oder die Optimierung ausgeschaltet zu haben (wobei dann wieder sehr fraglich ist, ob das Resultat noch irgendetwas mit der Realität zu tun hat)?


und was bedeutet das?
was heißt Laufzeitdaten? wieso hängt das von irgendwas ab?
wenn man das 10x ausführt, passiert 10x das gleiche, was genau soll in irgendeiner Form zu beachten sein?
Beide Methoden wählen einen unterschiedlichen Ansatz. Beide müssen Objekte erzeugen und Arrays kopieren, machen das jedoch auf unterschiedliche Weise.
Wie kannst du/ihr behaupten das der eine Ansatz dem anderen pauschal überlegen ist?
Wenn es wirklich so wäre, warum wandelt der SUN Compiler dann String + String in einen StringBuilder statt String.concat(String) um?
Die Art (und in diesem Fall Länge) der Daten ist entscheidend.
 

Saxony

Top Contributor
Wildcard hat gesagt.:
Wenn es wirklich so wäre, warum wandelt der SUN Compiler dann String + String in einen StringBuilder statt String.concat(String) um?

Naja weil StringBuilder die schnellste Variante darstellt um zwei Strings zu addieren - würde ich mal annehmen.

Nachdem ich das mit s = s.concat("a") verbessert habe, ergeben sich auch folgende Werte:

Code:
String + String (100k) : 24001
String.concat (100k) : 12094
StringBuilder (2M) : 94
StringBuffer (2M) : 141

Ich persönlich würde nun die Variante mit der kleinsten Ausführungszeit nehmen.
Und - O Wunder - es deckt sich mit der von SUN gewählten.

bye Saxony
 
S

SlaterB

Gast
Wildcard hat gesagt.:
für deine Optimierungstheorien,
es zeigt sich doch sehr deutlich, dass absolut gar nix passiert
Und diese Aussage triffst du pauschal für jeden Hotspot/JIT, ohne auch nur den Bytecode gesehen zu haben, oder die Optimierung ausgeschaltet zu haben (wobei dann wieder sehr fraglich ist, ob das Resultat noch irgendetwas mit der Realität zu tun hat)?
ich gehe nun mal von Tatsachen aus,
ich behaupte ja gar nix, du behauptest, dass irgendwelche Optimierungen stattfinden, obwohl gar nix passiert


Wie kannst du/ihr behaupten das der eine Ansatz dem anderen pauschal überlegen ist?
diese Aussage kann natürlich nur für die gegebenen Beispiele gelten
und soll wie gesagt natürlich nicht für alle komischen HotSpot-Dinger dieser Welt gelten

Die Art (und in diesem Fall Länge) der Daten ist entscheidend.
na warum sagst du das nicht gleich,
das ist natürlich ein interessanter Punkt, der bisher außen vor blieb,

allerdings wird zumindest bei mir mit höherer Länge der Vorsprung von concat() sogar noch größer..

Wenn es wirklich so wäre, warum wandelt der SUN Compiler dann String + String in einen StringBuilder statt String.concat(String) um?
vieleicht ist es damit einfacher auch die ganzen ints und chars zu addieren?

nie würde jemand mit einem ein 10 Zeilen-Programm behaupten, dass Java alles falsch macht,
aber das tut der Aussage concat schneller als + keinen Abbruch
(gerne mit dem Zusatz: in den bisher betrachteten Regionen)
 
S

SlaterB

Gast
Saxony hat gesagt.:
Wildcard hat gesagt.:
Wenn es wirklich so wäre, warum wandelt der SUN Compiler dann String + String in einen StringBuilder statt String.concat(String) um?

Naja weil StringBuilder die schnellste Variante darstellt um zwei Strings zu addieren - würde ich mal annehmen.
ne gerade das stimmt ja nicht, + verwendet StringBuilder und ist damit sehr langsam,
hier mal ein Vergleichsprogramm mit langen Teilstrings:

Code:
public class StringTester
{
    static int k = 1800;
    static String append = "aaaaaaaaaaaaaaaaaaaaaaaaaaaa";

    public static void main(String[] args)
    {
        stringConcat();
        stringBuilderFast();
        stringBuilderSlow();
        stringPlus();

        stringConcat();
        stringBuilderFast();
        stringBuilderSlow();
        stringPlus();

        stringConcat();
        stringBuilderFast();
        stringBuilderSlow();
        stringPlus();
    }

    private static void stringPlus()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            s += append;
        }
        System.out.println("String +     : " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringBuilderFast()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            StringBuilder b = new StringBuilder(s.length() + append.length());
            b.append(s);
            b.append(append);
            s = b.toString();
        }
        System.out.println("String b f   : " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringBuilderSlow()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            StringBuilder b = new StringBuilder();
            b.append(s);
            b.append(append);
            s = b.toString();
        }
        System.out.println("String b s   : " + (System.currentTimeMillis() - timeStart));
    }


    private static void stringConcat()
    {
        long timeStart = System.currentTimeMillis();

        String s = "";
        for (int i = k; i > 0; i--)
        {

            s = s.concat(append);
        }
        System.out.println("String.concat: " + (System.currentTimeMillis() - timeStart));
    }
}

Ausgabe:
String.concat: 172
String b f   : 500
String b s   : 1328
String +     : 1360
String.concat: 171
String b f   : 485
String b s   : 1359
String +     : 1375
String.concat: 188
String b f   : 500
String b s   : 1359
String +     : 1360
gilt natürlich nicht für HotSpot ;)
 

Wildcard

Top Contributor
Saxony hat gesagt.:
Wildcard hat gesagt.:
Wenn es wirklich so wäre, warum wandelt der SUN Compiler dann String + String in einen StringBuilder statt String.concat(String) um?

Naja weil StringBuilder die schnellste Variante darstellt um zwei Strings zu addieren - würde ich mal annehmen.

Nachdem ich das mit s = s.concat("a") verbessert habe, ergeben sich auch folgende Werte:

Code:
String + String (100k) : 24001
String.concat (100k) : 12094
StringBuilder (2M) : 94
StringBuffer (2M) : 141

Ich persönlich würde nun die Variante mit der kleinsten Ausführungszeit nehmen.
Und - O Wunder - es deckt sich mit der von SUN gewählten.

bye Saxony

Und, O Wunder, String + String resultiert in einem StringBuilder. Wie deckt sich das mit deiner Aussage? :roll:

Verändern wir die Testdaten (die nach Slater's Meinung ja irrelevant sind):
Code:
public class StringTester
{
    static int k = 10000;

    public static void main(String[] args)
    {
        stringPlus();
        stringConcat();
        stringPlus();
        stringConcat();
        stringPlus();
        stringConcat();
        stringPlus();
        stringConcat();
    }

    private static void stringPlus()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            s = s + k + k*2;
        }
        System.out.println("String +     : " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringConcat()
    {
        long timeStart = System.currentTimeMillis();

        String s = "";
        for (int i = k; i > 0; i--)
        {

            s = s.concat(String.valueOf(k)).concat(String.valueOf(k*2));
            
        }
        System.out.println("String.concat: " + (System.currentTimeMillis() - timeStart));
    }
}

Wie sieht das Ergebnis jetzt aus?

Code:
String +     : 3156
String.concat: 3328
String +     : 3219
String.concat: 3109
String +     : 2610
String.concat: 2547
String +     : 2625
String.concat: 2547

Plötzlich sind beide gleich schnell.
ich gehe nun mal von Tatsachen aus,
ich behaupte ja gar nix, du behauptest, dass irgendwelche Optimierungen stattfinden, obwohl gar nix passiert

Wie du an den Werten sehen kannst, findet sehr wohl eine Optimierung statt.
Nach dem ersten Durchlauf müssen alle Klassen geladen sein, warum wird die Sache aber im zweiten Durchlauf nochmal schneller?

aber das tut der Aussage concat schneller als + keinen Abbruch

Siehe Testdaten.
 

Wildcard

Top Contributor
Noch ein interessantes Detail:
Verändert man
Code:
s = s.concat(String.valueOf(k)).concat(String.valueOf(k*2));
zu
Code:
s = s.concat(String.valueOf(k)).concat(String.valueOf(k*2));
s = new String(s);
s = new String(s);
so sollte eine spürbare Verlangsamung eintreten. Plötzlich müssen wesentlich mehr Objekte erzeugt werden und die Strings sind gegen Ende der Schleife ja nicht gerade klein.
Es ändert sich aber gar nichts.
Warum? Es wird optimiert, daher kann man das alles in der Pfeife rauchen solange der Compiler, der JIT und der HopSpot Compiler daran rumbasteln.
 

Saxony

Top Contributor
Hmm,

wenn String + String eh in einem StrinBuilder endet, wieso soll man dann überhaupt einen StringBuilder bei vielen Stringadditionen nehmen?

Oder anders gefragt wieso ist die Verwendung von StrinBuilder alleine wesentlich schneller als die Verwendung von String + String, wenn dieses sowieso wieder auf nen StringBuilder zurück fällt.?

bye Saxony
 

Wildcard

Top Contributor
Saxony hat gesagt.:
wenn String + String eh in einem StrinBuilder endet, wieso soll man dann überhaupt einen StringBuilder bei vielen Stringadditionen nehmen?

Oder anders gefragt wieso ist die Verwendung von StrinBuilder alleine wesentlich schneller als die Verwendung von String + String, wenn dieses sowieso wieder auf nen StringBuilder zurück fällt.?
Der Trick ist es, den StringBuilder an der richtigen Stelle, mit der richtigen Kapazität zu initialisieren.

Übrigens lassen sich die gewonnen Erkenntnisse auch sehr leicht umdrehen, wie dieser Test beweißt:


Code:
public class StringTester
{
    static int k = 10000;

    public static void main(String[] args)
    {
        stringPlus();
        stringConcat();
        stringPlus();
        stringConcat();
        stringPlus();
        stringConcat();
    }

    private static void stringPlus()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            s = s + k + k*2 + k*3;
        }
        System.out.println("String +     : " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringConcat()
    {
        long timeStart = System.currentTimeMillis();

        String s = "";
        for (int i = k; i > 0; i--)
        {

            s = s.concat(String.valueOf(k)).concat(String.valueOf(k*2)).concat(String.valueOf(k*3));
            
        }
        System.out.println("String.concat: " + (System.currentTimeMillis() - timeStart));
    }
}

Werte:

Code:
String +     : 6141
String.concat: 10593
String +     : 6407
String.concat: 10672
String +     : 5015   <-----optimierung
String.concat: 7281 <-----optimierung

Was lernen wir daraus?

1. Die Sache ist hochgradig Parameterabhängig
2. Mikrobenchmarks sind nicht trivial und generell wenig aussagekräftig.
 
S

SlaterB

Gast
pff, jetzt wirst du aber billig, das ist nicht dein Niveau..

dass concat() nur für Strings schneller ist stand von Anfang an fest,
habe ich ja auch vor dir geschrieben:

SlaterB hat gesagt.:
Wenn es wirklich so wäre, warum wandelt der SUN Compiler dann String + String in einen StringBuilder statt String.concat(String) um?
vieleicht ist es damit einfacher auch die ganzen ints und chars zu addieren?

---------

Wildcard hat gesagt.:
Wie du an den Werten sehen kannst, findet sehr wohl eine Optimierung statt.
Nach dem ersten Durchlauf müssen alle Klassen geladen sein, warum wird die Sache aber im zweiten Durchlauf nochmal schneller?
weil hier Strings gecached werden, was sich hier verständlicherweise auf beide Additonen gleich auswirkt,

was hat das mit dem vorherigen Programm zu tun?
habe ich behauptet, dass in allen Programmen der Welt nie etwas gecacht wird? ;)

was hat das mit dem Vergleich zwischen + und concat() zu tun?

Es ändert sich aber gar nichts.
Warum? Es wird optimiert, daher kann man das alles in der Pfeife rauchen solange der Compiler, der JIT und der HopSpot Compiler daran rumbasteln.
noch mal: behaupte ich dass das Wort Optimierung nicht im Lexikon steht?
dann hast du natürlich Recht..

aber wenn wir bei den Fakten bleiben, also
String + String
sowie
String concat(String)
gegenüberstellen, dann ist concat schneller..


----------

aber einen neuen bisher nicht beachteten Umgebungsparameter hast du wieder aufgezeigt:
bei Hintereinanderausführung mehrerer Stringadditionen ist + bald schneller als concat:

Code:
public class StringTester
{
    static int k = 3800;
    static String append = "aaaa";

    public static void main(String[] args)
    {
        stringConcat();
        stringPlus();

        stringConcat();
        stringPlus();

        stringConcat();
        stringPlus();
    }

    private static void stringPlus()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            s += append + append + append;
        }
        System.out.println("String +     : " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringConcat()
    {
        long timeStart = System.currentTimeMillis();

        String s = "";
        for (int i = k; i > 0; i--)
        {

            s = s.concat(append).concat(append).concat(append);
        }
        System.out.println("String.concat: " + (System.currentTimeMillis() - timeStart));
    }
}

Ausgabe:
String.concat: 1313
String +     : 765
String.concat: 1094
String +     : 766
String.concat: 1094
String +     : 765

und sehr gerne stimme ich dir da zu, falls das an einer Optimierung liegt,
ich verschließe mich dem Wort Optimierung nicht auch wenn ich erkenne, dass in den frühenen Beispielen keine auftrat ;)

(edit: ach, liegt wohl nur daran, dass die kleinen Teilstrings zuerst zusammengefügt werden, nix optimiert ;) )

damit muss die Aussage weiter verfeinert werden:
concat schlägt sich umso besser, je weniger Additionen in einer Zuweisung stehen,
am besten bei genau einer

dass das nur für Strings gilt war von Anfang an klar,
je länger die Strings desto besser stehts für concat()

Wildcard hat gesagt.:
1. Die Sache ist hochgradig Parameterabhängig
dem kann keiner wiedersprechen
Wildcard hat gesagt.:
2. Mikrobenchmarks sind nicht trivial und generell wenig aussagekräftig.
was du gegen die Aussage hast verstehe ich aber nicht,
wahrscheinlich spielst du auf die Auswirkung in realen Programmen ab,
aber das ist ja immer ein sinnloses Unterfangen

der Test kann nur das aussagen, was er selber aussagt..,
wenn man tausendmal Wurzel aus 4 berechnet und sich wundert, dass im realen Leben tausendmal Wurzel aus 5 länger zu berechnen dauert,
dann ist man wirklich selber Schuld ;)
 

Wildcard

Top Contributor
SlaterB hat gesagt.:
pff, jetzt wirst du aber billig, das ist nicht dein Niveau..

dass concat() nur für Strings schneller ist stand von Anfang an fest,
habe ich ja auch vor dir geschrieben:
Was soll denn jetzt das bitte heißen?
Glaubst du String + irgendwas kann zaubern?
Die Konvertierung in einen String muss in beiden Fällen erfolgen, das tut nichts zur Sache.
Die Schleifenvariable zu verwenden war lediglich die einfachste Möglichkeit um den String Pool auszuhebeln, weil ich keine zufälligen char[]s erzeugen wollte.
 
S

SlaterB

Gast
ja, ich dachte, dass wäre der Grund, warum das + auf einmal so schnell ist wie das concat(),
aber das stimmte wohl gar nicht, hast Recht,

deine ganzen 'gleich schnell'-Beispiele sind nämlich nur deswegen gleichschnell weil du für + unfair abkürzt:

concat muss
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".concat("a").concat("a")
=
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".concat("a")
=
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
bewältigen,
während + den einfachen Weg
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"+"a"+"a"
=
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"+"aa"
=
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
hat,


welch besseren Beweis gibt es für die Überlegenheit von concat(),
wenn es (in diesem Fall) selbst dann noch gleich schnell ist?


natürlich ist concat() nur im Kampf Mann gegen Mann schneller,
wenn man die Bedingungen also angleicht, sticht die Überlegenheit wieder deutlich hervor ;)

Code:
public class StringTester 
{ 
    static int k = 7000; 

    public static void main(String[] args) 
    { 
        stringPlus(); 
        stringConcat(); 
        stringPlus(); 
        stringConcat(); 
        stringPlus(); 
        stringConcat(); 
        stringPlus(); 
        stringConcat(); 
    } 

    private static void stringPlus() 
    { 
        long timeStart = System.currentTimeMillis(); 
        String s = ""; 
        for (int i = k; i > 0; i--) 
        { 
            s = s + k + k*2; 
        } 
        System.out.println("String +     : " + (System.currentTimeMillis() - timeStart)); 
    } 

    private static void stringConcat() 
    { 
        long timeStart = System.currentTimeMillis(); 

        String s = ""; 
        for (int i = k; i > 0; i--) 
        { 

            s = s.concat(String.valueOf(k).concat(String.valueOf(k*2))); 
            
        } 
        System.out.println("String.concat: " + (System.currentTimeMillis() - timeStart)); 
    } 
} 

Ausgabe:
String +     : 3125
String.concat: 1032
String +     : 3984
String.concat: 1016
String +     : 2390
String.concat: 1016
String +     : 2641
String.concat: 1000
 

Wildcard

Top Contributor
Was erzählst du mir da für einen Unsinn?
Java ist, war und wird immer Linksassoziativ bleiben. :roll:
Du hast die Sache jetzt natürlich umgedreht, was bei der + Variante wegen den ints nicht möglich ist.
So kann man sich auch die Resultate besorgen die man sehen möchte. Du solltest Statistiker werden :toll:
 
S

SlaterB

Gast
was genau ist daran jetzt Unsinn?

> was bei der + Variante wegen den ints nicht möglich ist.

benutzte doch String.valueOf()?
 

Wildcard

Top Contributor
Das Ausdrücke immer von Links nach Rechts ausgewertet werden und nicht mal eben andersrum weil's gerade bequemer ist.
 
S

SlaterB

Gast
wie erklärst du dir
Code:
public class StringTester
{
    static int k = 5000;

    public static void main(String[] args)
    {
        stringPlus1();
        stringPlus2();
        stringConcat();
        stringPlus1();
        stringPlus2();
        stringConcat();
        stringPlus1();
        stringPlus2();
        stringConcat();

    }

    private static void stringPlus1()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            s = k + s + k * 2;
        }
        System.out.println("String +1    : " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringPlus2()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            s = s + k + k * 2;
        }
        System.out.println("String +2    : " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringConcat()
    {
        long timeStart = System.currentTimeMillis();

        String s = "";
        for (int i = k; i > 0; i--)
        {

            s = s.concat(String.valueOf(k).concat(String.valueOf(k * 2)));

        }
        System.out.println("String.concat: " + (System.currentTimeMillis() - timeStart));
    }
}

Ausgabe:
String +1    : 2922
String +2    : 1172
String.concat: 406
String +1    : 2813
String +2    : 1156
String.concat: 375
String +1    : 2797
String +2    : 1156
String.concat: 375
?
 

Wildcard

Top Contributor
Was möchtest du mir damit schon wieder sagen?
Jetzt verwendest du 3 verschiedene Reihenfolgen um die Strings zusammen zu bauen und 2 verschiedene Methoden.
Welchen der 3 Fälle soll ich dir erklären?
 
S

SlaterB

Gast
ich behaupte, dass die Methode
s + k + k * 2
nur deshalb so schnell ist, weil k + k * 2 zuerst zusammengefügt werden


du sagst, dass 'Ausdrücke immer von Links nach Rechts ausgewertet',
also (s + k) + k * 2

dann wundert mich, warum
s = k + s + k * 2;
so viel langsamer ist

concat war in diesem Beispiel nicht von Belang
 

Wildcard

Top Contributor
Du schaffst mich...
Du bemerkst selbst, dass concat auf einmal schneller wird, wenn man die Reihenfolge vorteilhafter gestalltet und wunderst dich dann ernsthaft wenn der gleiche Effekt auch bei String + String auftritt? :lol:

Wenn du der Spezifikation (die eindeutig von Linksassoziativität spricht) nicht glaubst, dann nimm die Sache selbst in die Hand und setz Klammern:
Code:
s = (s + k) + k*2;
Du wirst sehen, das die Werte davon unbeindruckt sind.
Bei deiner concat Lösung hingegen verwendest du s+(k+k*2), was effizienter ist, sich bei ints aber nicht analog übertragen lässt.
Du vergleichst Äpfel mit Birnen, was soll ich dazu noch sagen.
 
S

SlaterB

Gast
Wildcard hat gesagt.:
Du bemerkst selbst, dass concat auf einmal schneller wird, wenn man die Reihenfolge vorteilhafter gestalltet und wunderst dich dann ernsthaft wenn der gleiche Effekt auch bei String + String auftritt? :lol:
hmm? für mich siehst eher so aus:
du hattest mit der vorteilhaften Reihenfolge für + angefangen, und das genutzt um zu sagen, dass + nun gleichschnell wie concat ist,

aber das war unfair, denn concat hatt da nicht die vorteilhafte Reihenfolge genutzt,

nun setze ich auch für concat die vorteilhafte Reihenfolge, was concat promt wieder einen Riesenvorsprung verschafft

wo in dieser Abfolge 'wundere' ich mich?
ich habe den Effekt bei + erkannt und ihn dann auf concat übernommen



Wenn du der Spezifikation (die eindeutig von Linksassoziativität spricht) nicht glaubst, dann nimm die Sache selbst in die Hand und setz Klammern:
Code:
s = (s + k) + k*2;
Du wirst sehen, das die Werte davon unbeindruckt sind.
Bei deiner concat Lösung hingegen verwendest du s+(k+k*2), was effizienter ist, sich bei ints aber nicht analog übertragen lässt.

was genau ist denn da jetzt die Aussage, dass + trotz anderer Klammerung genauso schnell ist?
nun, das mag so sein, ich weiß nicht, wie es intern abläuft,

selbst wenn nun also + auch bei schlechter Klammerung optimal abgearbeitet wird,
bedeutet es doch immer noch, dass zumindest ein geschickt geklammerter concat()-Ausdruck immer (bzw. nur unter den bisher betrachteten Beispielen) schneller ist als ein beliebig geklammerter +-Ausdruck, oder?

Du vergleichst Äpfel mit Birnen, was soll ich dazu noch sagen.
was genau meinst du damit?
 

Wildcard

Top Contributor
Nein, du gehst immer noch davon aus, das in genanntem Beispiel String + String erst die beiden kurzen Strings verknüpft und zum Schluß den langen. Das ist aber falsch, da von links nach rechts gearbeitet wird, also erst lang + kurz und dann + kurz.
Denn unfairen Vorteil den du zu erkennen meintest, hast du selbst erst geschaffen, und zwar auf der concat Seite.
 
S

SlaterB

Gast
Nein, du gehst immer noch davon aus, das in genanntem Beispiel String + String erst die beiden kurzen Strings verknüpft und zum Schluß den langen. Das ist aber falsch, da von links nach rechts gearbeitet wird, also erst lang + kurz und dann + kurz.
was macht das für einen Unterschied, wenn doch letztlich das Ergebnis genau so lange dauert als wenn es so wäre?
ich weiß nicht, wie es intern optimiert wird,
aber es kommt genau die Zeit raus, als wenn erst die beiden kurzen addiert werden,

das Ergebnis stimmt also, der Weg dahin ist doch egal?

und wenn wirklich lang + kurz + kurz in der Reihenfolge (lang + kurz) + kurz ausgewertet wird,
warum ist dann kurz + lang + kurz so viel langsamer?


------------


hmm, also noch mal von vorne, du hattest irgendwann ein erstes Beispiel gepostet,
ich will nicht alles wiederholen, nur zwei Sätze von dir zum Ergebnis

> Wie sieht das Ergebnis jetzt aus?
[..]
> Plötzlich sind beide gleich schnell.

dieses Beispiel fechte ich nun an, ich denke, dass da das + nur deshalb so schnell ist,
weil da irgendwas intern besser läuft,

so, und diesen Vorteil kann man concat() auch verschaffen, oder nicht?,
concat ist dann wieder wahnsinnig schneller

Code:
public class StringTester
{
    static int k = 7000;

    public static void main(String[] args)
    {
        stringPlusFast();
        stringConcatFast();

        stringPlusSlow();
        stringConcatSlow();

        stringPlusFast();
        stringConcatFast();

        stringPlusSlow();
        stringConcatSlow();

    }

    private static void stringPlusFast()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            s = s + k + k * 2;
        }
        System.out.println("\nString +      fast: " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringPlusSlow()
    {
        long timeStart = System.currentTimeMillis();
        String s = "";
        for (int i = k; i > 0; i--)
        {
            s = s + k;
            s = s + k * 2;
        }
        System.out.println("\nString +      slow: " + (System.currentTimeMillis() - timeStart));
    }

    private static void stringConcatFast()
    {
        long timeStart = System.currentTimeMillis();

        String s = "";
        for (int i = k; i > 0; i--)
        {
            s = s.concat(String.valueOf(k).concat(String.valueOf(k * 2)));
        }
        System.out.println("String.concat fast: " + (System.currentTimeMillis() - timeStart));
    }


    private static void stringConcatSlow()
    {
        long timeStart = System.currentTimeMillis();

        String s = "";
        for (int i = k; i > 0; i--)
        {
            s = s.concat(String.valueOf(k)).concat(String.valueOf(k * 2));
        }
        System.out.println("String.concat slow: " + (System.currentTimeMillis() - timeStart));
    }
}

Ausgabe:

String +      fast: 3219
String.concat fast: 1047

String +      slow: 6250
String.concat slow: 2984

String +      fast: 2688
String.concat fast: 1078

String +      slow: 4875
String.concat slow: 2875

+ fast ist hier viel schneller als + slow, weil alles in einer Zeile steht (ob wegen Reihenfolge oder was anderem ist letztlich ja egal),

+ fast ist nun genauso schnell wie Concat slow,
aber bei Concat kann man noch optimieren, während + schon in seiner fast-Version ist,
Concat fast ist wieder deutlich schneller als + fast!
 

Wildcard

Top Contributor
SlaterB hat gesagt.:
und wenn wirklich lang + kurz + kurz in der Reihenfolge (lang + kurz) + kurz ausgewertet wird,
warum ist dann kurz + lang + kurz so viel langsamer?
Zunächst mal solltest du das 'wirklich' weglassen, oder mich vom Gegenteil überzeugen (was dir sehr schwer fallen wird).
Der Grund hängt mit den Internas des Builders zusammen.
Zur Laufzeit wird String + String in dieser Art abgearbeitet:
Code:
new StringBuilder(s).append(k).append(k*2);
Er wird mit einem Overhead von 16 Zeichen erzeugt, kann also im günstigen Fall die anderen Strings appenden ohne ein neues Array anlegen und kopieren zu müssen.
Wenn jetzt allerdings der kleine String k am Anfang übergeben wird, ist der Buffer wesentlich kleiner und es muss in jedem Fall kopiert werden. Das macht einen riesen Unterschied.
Du wirst übrigens feststellen, dass die Reihenfolge die du für dein concatFast verwendest mit einem StringBuilder auf identische Ergebnisse kommt:
Code:
s = new StringBuilder(s).append(new StringBuilder(k).append(k*2).toString()).toString();
Das ganze lässt sich nur nicht 1:1 auf die String + String Variante übertragen, da bei s + (k+k*2) die Klammer als int aufgelöst wird.
Also sei bitte so gut und lass die Reihenfolge ruhen, das ist nicht das schlagende Argument auf das du hoffst und in der Praxis sowieso völlig irrelevant :wink:


das Ergebnis stimmt also, der Weg dahin ist doch egal?
Das ist jetzt einfach nur Blauäugig.

dieses Beispiel fechte ich nun an, ich denke, dass da das + nur deshalb so schnell ist,
weil da irgendwas intern besser läuft,
Was läuft denn da deiner Meinung nach 'intern besser'?

so, und diesen Vorteil kann man concat() auch verschaffen, oder nicht?
Welchen Vorteil? Du vermutest nur irgendeine dubiose höhere Macht und versuchst nun durch Veränderung des Algorithmus zu retten was von deinen Anfangsbehauptungen noch geblieben ist.

Es geht immer nur darum wie viele Arrays erzeugt werden müssen und wie oft umkopiert werden muss.
Man kann nahezu beliebig viele verschiedene Fälle produzieren und je nach Fall wird entweder concat oder String + String schneller sein.

Wenn dir jetzt hoffentlich klar ist, dass man Pauschalaussagen (wie du sie getätigt hast) nicht treffen kann und am besten ganz die Finger von Mikrobenchmarks lässt, können wir das Thema gerne beenden.
 
S

SlaterB

Gast
ah, nun ist ja endlich geklärt, wie die Strings von links aus zusammengeführt werden,
kannst du mir Langsamdenker auch ruhig gleich verraten,
ich gelobe, die Rechtsauswertung zumindest in diesem Thread nicht mehr zu erwähnen ;)

-----

an meiner Aussage 'wie es dazu kommt, ist egal' darf ich aber festhalten,
denn immer noch gilt: + ist dem Beispiel nur einigermaßen konkurrenzfähig,
weil es eine bestimmte Situation ausnutzt, nämlich zwei kurze Strings dahinter,
(wenn diese Strings aber länger als 16 sind, dann Gnade Gott ;) )

genau auf die gleiche Weise, durch Ausnutzung der Kürze der angefügten Strings, kann man auch concat() optimieren,
was ist daran falsch?
Welchen Vorteil? Du vermutest nur irgendeine dubiose höhere Macht und versuchst nun durch Veränderung des Algorithmus zu retten was von deinen Anfangsbehauptungen noch geblieben ist.
du hast + doch auch durch Veränderung des Algorithmus schneller gemacht?

Man kann nahezu beliebig viele verschiedene Fälle produzieren und je nach Fall wird entweder concat oder String + String schneller sein.
ha, kommen wir also zur Kernaussage:
1.
im Kampf Mann gegen Mann,
also
String stringA = stringB + stringC;
vs
String stringA = stringB.concat(stringC);

ist concat() (bisher ;) ) in ALLEN DENKBAREN Varianten uneinholbar schneller,
wenn dir dieser wichtige Anwendungsfall nichts bedeutet, na dann kann ich dir auch nicht helfen ;)

2.
in BELIEBIGEN Situationen ist a.) concat() in der der Mehrzahl der Möglichkeiten ganz automatisch besser
(etwas subjektiv, welche Situationen man als normal ansieht)
+
b.) concat() kann durch simple Optimierung (richige Klammerung) IMMER schneller als + sein
(wiederum nur für die bisher bekannten Beispiele, wobei man in dem Fall eh zum StringBuilder wechseln würde)

wenn diese beiden Punkte keine durchschlagenden Argumente für die Überlegenheit sind, was dann?


edit: lass es mich nochmal wiederholen:
wenn man bei mehr als 2 String eh hoffentlich einen Stringbuilder einsetzt,
dann bleibt ja eigentlich nur noch 1., und in diesem Fall ist concat() bisher immer besser als + ....
 

Wildcard

Top Contributor
:autsch:
an meiner Aussage 'wie es dazu kommt, ist egal' darf ich aber festhalten,
denn immer noch gilt: + ist dem Beispiel nur einigermaßen konkurrenzfähig,
weil es eine bestimmte Situation ausnutzt, nämlich zwei kurze Strings dahinter,
(wenn diese Strings aber länger als 16 sind, dann Gnade Gott icon_wink.gif )

Um Gottes willen, nein.
Es werden keine 'bestimmten Situationen' ausgenutzt.
Wir haben nur einen sehr speziellen Fall betrachtet.
Näheres dazu später.

du hast + doch auch durch Veränderung des Algorithmus schneller gemacht?
Nein, ich habe die Daten geändert, da (wie wiederholt betont) die Daten entscheidend für die Performance sind.
ist concat() (bisher :wink:) in ALLEN DENKBAREN Varianten uneinholbar schneller,
wenn dir dieser wichtige Anwendungsfall nichts bedeutet, na dann kann ich dir auch nicht helfen
Das ist grundfalsch.

in BELIEBIGEN Situationen ist a.) concat() in der der Mehrzahl der Möglichkeiten ganz automatisch besser
(etwas subjektiv, welche Situationen man als normal ansieht)
Das gleiche wie oben und immernoch falsch
concat() kann durch simple Optimierung (richige Klammerung) IMMER schneller als + sein
(wiederum nur für die bisher bekannten Beispiele, wobei man in dem Fall eh zum StringBuilder wechseln würde)
Ich dachte du wolltest das nicht mehr erwähnen. Das hat weder Gehalt, noch Bewandtnis. In der Realität würdest du weder concat noch + in einer Schleife einsetzen. Wenn doch, dann ist dir in der Regel nicht klar welcher String wie lang ist und wie am besten geklammert wird.

wenn diese beiden Punkte keine durchschlagenden Argumente für die Überlegenheit sind, was dann?
Du hast gar keine Argumente, weil dir nicht klar zu sein scheint wie die Sache funktioniert.

Wie funktioniert concat?
Ein neues Array der Länge String1+String2 wird allokiert und die Werte kopiert.

Wie funktioniert String + String?
Ein StringBuilder wird erzeugt der initial den ersten String aufnimmt + 16 Zeichen overhead.
Wenn das nicht ausreicht wird eine minimale Größe sichergestellt die alle Zeichen aufnehmen kann, in der regel aber verdoppelt.
Der StringBuilder wird also größer und größer und muss bei längeren Strings immer weniger Arbeit leisten.
Bei concat wird der Aufwand aber immer größer weil mehr kopiert werden muss.

Du merkst wohin das führt?
Es hängt davon ab, welche Daten verwendet werden, ab wann sich der Overhead des StringBuilder rechnet und er deutlich schneller wird.

Du kannst jetzt weiter Pseudodaten rumschubsen und dich freuen das du viel cleverer bist als die Leute von SUN, die den StringBuilder statt concat verwendet, oder du wachst auf und kommst auf die Idee, das große Strings das größere Performanceproblem darstellen und der StringBuilder daher absolut Sinn macht weil er besser skaliert. :autsch:

Du bist nun auch schon länger dabei, aber das du dich so hartnäckig dagegen sträubst, dass man die Sache nicht einfach in Schwarz und Weiß aufteilen kann überrascht mich doch sehr.


wenn man bei mehr als 2 String eh hoffentlich einen Stringbuilder einsetzt,

Auch das ist so nicht richtig.

Das ist nicht das entscheidende Kriterium. Entscheidend ist, ob die Codestelle innerhalb einer Schleife oder Rekursion aufgerufen wird. Dann muss nämlich der StringBuilder her (und zwar aussen). Ob das nun 2,3,4 oder 300 Strings im Code sind, ist unerheblich.


So... Fußball jetzt :autsch:
 
S

SlaterB

Gast
Wildcard hat gesagt.:
Um Gottes willen, nein.
Es werden keine 'bestimmten Situationen' ausgenutzt.
Wir haben nur einen sehr speziellen Fall betrachtet.
Näheres dazu später.
schade dass nichts kam

du hast + doch auch durch Veränderung des Algorithmus schneller gemacht?
Nein, ich habe die Daten geändert, da (wie wiederholt betont) die Daten entscheidend für die Performance sind.
du hast
s1 = s1 +s2;
s1 = s1 + s3;
in
s1 = s1 + s2 + s3;
optimiert, wo ist da eine Datenänderung? ;)




Das ist grundfalsch.
Das gleiche wie oben und immernoch falsch
schade, alles ohne Begründung

concat() kann durch simple Optimierung (richige Klammerung) IMMER schneller als + sein
(wiederum nur für die bisher bekannten Beispiele, wobei man in dem Fall eh zum StringBuilder wechseln würde)
Ich dachte du wolltest das nicht mehr erwähnen. Das hat weder Gehalt, noch Bewandtnis. In der Realität würdest du weder concat noch + in einer Schleife einsetzen. Wenn doch, dann ist dir in der Regel nicht klar welcher String wie lang ist und wie am besten geklammert wird.
ich wollte die Rechts- statt Linksauswertung nicht mehr erwähnen,
dass man concat() richtig anordnen kann widerspricht dem nicht,

über die Reihenfolge muss man im ganzen Leben nur einmal nachdenken:
public static String concatIntelligent(String... strings);



Wie funktioniert concat?
[..]
falls da irgendwas zum Thema drin ist, dann musst du das für mich leider nochmal verständlich formulieren,
für mich liest sich das so, als wenn du concat() mit StringBuider vergleichst, das erübrigt sich..


Du kannst jetzt weiter Pseudodaten rumschubsen und dich freuen das du viel cleverer bist als die Leute von SUN, die den StringBuilder statt concat verwendet, oder du wachst auf und kommst auf die Idee, das große Strings das größere Performanceproblem darstellen und der StringBuilder daher absolut Sinn macht weil er besser skaliert. :autsch:
an welcher Stelle habe ich das bisher behauptet oder einen Austausch vorgeschlagen?
die werden sich was dabei gedacht haben, dessen bin ich mir sicher


Du bist nun auch schon länger dabei, aber das du dich so hartnäckig dagegen sträubst, dass man die Sache nicht einfach in Schwarz und Weiß aufteilen kann überrascht mich doch sehr.
warum muss denn ein schwarzes Bild auch weiße Anteile enthalten?
ich halte mich immer an die vorliegenden Fakten, ich sage doch nur wie es sich bisher für mich darstellt,
von alleine kommst du ja nicht dazu, die richtige Sichtweise darzustellen ;)

ich kann mir dabei gut vorstellen dass es weiteres zu bedenken gibt, kein Problem dann mein Bild zu erweitern,

z.B. mit der StringBuilder-Verdoppelung,
damit kann ich mein Argument 2.b) 'concat kann IMMER besser als + gemacht werden' so nicht mehr stehenlassen,
bei der Addition von mehreren etwa gleich großen Strings wirkt sich der Vorteil des StringBuilders aus,
während concat() jedes mal eine neues Array erstellen muss,
kein Problem für mich dies einzubauen,

man muss natürlich wieder sagen, dass das eine Spezialsituation ist, die eigentlich sowieso in den Bereich der expliziten Verwendung eines StringBuilders fällt,



2.b. muss also von 'IMMER' auf 'meistens' abgeschwächt werden, was freilich wie 2.a. von Anfang an subjektiv ist,
und sowieo eher theoretisch, weil man dann meistens mit StringBuilder besser dran ist,

1. scheint mir weiterhin felsenfest, wobei ich nicht wetten würde, dass dagegen nichts sprechen kann,

ich verstehe deine Taktik nicht, warum sagst du zigmal 'das ist irrsinng', statt Schritt für Schritt die Argumente aufzuzählen,
dann ginge das viel schneller voran..
 

Wildcard

Top Contributor
Welche Argumente denn?
Du kaust immer wieder Dinge durch die wir schon hatten.
ich halte mich immer an die vorliegenden Fakten,
....
ich verstehe deine Taktik nicht, warum sagst du zigmal 'das ist irrsinng', statt Schritt für Schritt die Argumente aufzuzählen,
dann ginge das viel schneller voran..
Gute Idee.

Also zu den harten Fakten ohne auf die Implementierung von concat und StringBuilder einzugehen:

Es wurden mit wenigen schwachsinnigen Tests 3 Fälle festgestellt:
1. concat schneller als String + String
2. concat und String + String gleich schnell
3. String + String schneller als concat

Genau das versuche ich seit 3 Seiten Diskussion begreiflich zu machen.
 
S

SlaterB

Gast
tja, wenn du es nicht korrigieren willst (falls es falsch ist),
dann bleibe ich also dabei, vorallem bei

String stringA = stringB + stringC;
(langsamer)
vs
String stringA = stringB.concat(stringC);
(schneller)

ich kann mir nämlich bisher nicht vorstellen, wie es mal andersrum laufen würde,
falls du es weißt, so verrate es bitte
 

Wildcard

Top Contributor
Du redest jetzt vom einfachsten Fall einer String Zuweisung s = s1 + s2 bzw. s = s1.concat(s2) ohne das weitere Dinge mit dem String passieren?
Ja, in diesem Fall wird concat schneller sein.
StringBuilder muss folgende Dinge erledigen:
1. Array allokieren und mit s1 befüllen
2. s2 ins Array übertragen und gegebenfalls ein neues, größeres Array erzeugen
3. ein array mit der Länge des Gesamtstrings erzeugen und mit s1 und s2 befüllen

Bei concat sieht's folgendermaßen aus:
1. Array der Größe s1 + s2 allokieren
2. Array mit s1 und s2 befüllen

Es fällt also ein Schritt weg.

Sobald die Sache komplizierter wird (sprich real), sieht's dann auch schon wieder anders aus :wink:
 
S

SlaterB

Gast
schön, dass das abgehakt ist,
du magst zu 'Sobald die Sache komplizierter wird' überlenken,
für mich ist String + String aber 90% der Wichtigkeit, der einzig richtig sinnvolle Einsatz

bei mehreren Strings ist einem im Grunde entweder die Performance egal (sie spielt keine Rolle, z.B. in Debug-Ausgaben)
oder man verwendet einen StringBuilder

wenn man sich dennoch auf das Gedankenspiel einlässt, dann kommen wir zu 2.a. und 2.b.
da können wir nicht mehr viel diskutieren, denke ich,

ich sehe da die Möglichkeiten von concat() deutlich im Vorteil,

z.B. bei den bisher in dem Thread verwendeten Beispielen
'großen String mit kleinen Strings auffüllen' ist concat besser,
muss natürlich intelligent eingesetzt werden, das kann man ja wohl erwarten,

und wenn man mehr als 16 Chars hinzufügt siehst für + oft sehr übel aus,

die Spezialsituation 'viele gleichgroße String in einer Code-Zeile (!) zusammenzuaddieren',
die den StringBuilder bevorteilt, halte ich dagegen für deutlich schwächer,
aber das ist vollkommen subjektiv
 

Wildcard

Top Contributor
SlaterB hat gesagt.:
für mich ist String + String aber 90% der Wichtigkeit, der einzig richtig sinnvolle Einsatz
Ich sehe dafür überhaupt keinen sinnvollen Einsatz. Gar keinen.
Wenn es sich nicht um eine kritische Stelle handelt mach ich String + String weil's einfacher und völlig egal ist, an kritischen Stellen nehme ich die Sache selbst mit Arrays, ByteBuffern oder StringBuildern in die Hand.
 
S

SlaterB

Gast
aber wozu, wenn concat besser ist?
da kann ich ja mal deine Argumentationsweise verwenden:
warum haben die Sun-Leute concat intern das char-Array gegeben und keinen StringBuilder? ;)


dass + und concat generell nicht so wichtig sind, ändert ja nichts an dem Ergebnis, dass concat besser ist, oder?
(besser vor allem beim dualen String + String)

und sag jetzt nicht, dass nur String + String unwichtig ist, + mit mehreren Teilstrings aber wieder wichtiger ;)
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben