2017-01-09 3 views
1

Wenn wir eine lange Codezeile zur besseren Lesbarkeit in zwei Teile aufteilen, wird zwischen den Zeilen ein Pluszeichen eingefügt (falls zwischen dem Text geteilt). Zum Beispiel das Teilen einer langen Zeile in der Mitte des Textes, der etwas Text protokolliert.Leistungsproblem beim Aufteilen der langen Protokollzeile in zwei

Also sollte dies vermieden werden zusätzliche String-Verkettung bringt es ins Bild? Oder ein Kompromiss aus besserer Lesbarkeit wiegt höher?

+1

Ich bin zu 99% sicher, dass der Compiler es nur in ein nettes großes String-Literal für Sie verwandelt – Rogue

Antwort

2

Ja, es gibt ein kleines bisschen Leistung Auswirkungen. Der reguläre Compiler führt keine Optimierung durch. Es ersetzt einfach den Operator + durch StringBuilder Methodenaufrufe. Z.B. Wenn Sie String s = "x" + "y" + "z"; haben, kann es vor dem Kompilieren in Bytecodes durch String s = new StringBuilder().append("x").append("y").append("z"); ersetzt werden. Aber hier gibt es keine wirkliche Optimierung. Es ersetzt es nicht durch String s = "xyz"; vor dem Erzeugen des Byte-Codes. Ich bin nicht sicher, ob der JIT-Compiler es optimiert, bevor die nativen Prozessoranweisungen generiert werden. Aber selbst wenn dies der Fall ist, verursacht es zur Laufzeit einen winzigen Leistungseinbruch.

Persönlich würde ich mehr für Eleganz und Lesbarkeit interessieren, wenn sie um einen Preis von kleinen Leistungshit kommen.

0

Alle üblichen Java-Compiler sind viel zu ausgereift, um etwas Dummes wie verkettete String-Literale zur Laufzeit auszuführen. Lass uns das Prüfen. Vor diesem Code:

public class CatStrings { 
    public static void main(String [] args) { 
    String a = "This is a long long long string broken up " 
     + "into parts to see if the compiler " 
     + "optimizes the concatenation."; 
    System.out.println(a); 
    } 
} 

Mein Java 8 Compiler - Oracle Standard - tut das Richtige, wie durch javap Ausgang gezeigt:

stack=2, locals=2, args_size=1 
    0: ldc   #2     // String This is a long long long string broken up into parts to see if the compiler optimizes the concatenation. 
    2: astore_1 
    3: getstatic  #3     // Field java/lang/System.out:Ljava/io/PrintStream; 
    6: aload_1 
    7: invokevirtual #4     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    10: return 
0

Es hängt davon ab.

Wenn es nur Konstanten gibt, kümmert sich der Javac darum. Das folgende Programm:

public class Main { 
    public static void main(String[] args) { 
     System.out.println("foo"+"bar"); 
    } 
} 

Schaltet in den folgenden Bytecode (entfernt einige nicht relevante Teile):

public class com/hazelcast/Main { 

    // access flags 0x9 
    public static main([Ljava/lang/String;)V 
    L0 
    LINENUMBER 9 L0 
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream; 
    LDC "foobar" 
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V 
    L1 
    LINENUMBER 10 L1 
    RETURN 
    L2 
    LOCALVARIABLE args [Ljava/lang/String; L0 L2 0 
    MAXSTACK = 2 
    MAXLOCALS = 1 
} 

können Sie sehen die foobar Konstante drin. In diesem Fall gibt es keinen Leistungseinbruch.

Allerdings, wenn wir das Programm etwas realistischere ändern würde:

public class Main { 

    public static void main(String[] args) { 
     int a = 1; 
     System.out.println(a+"foo" + "bar"); 
    } 
} 

Wir erhalten die folgenden Bytecode:

public class com/hazelcast/Main { 

    // access flags 0x9 
    public static main([Ljava/lang/String;)V 
    L0 
    LINENUMBER 9 L0 
    ICONST_1 
    ISTORE 1 
    L1 
    LINENUMBER 10 L1 
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream; 
    NEW java/lang/StringBuilder 
    DUP 
    INVOKESPECIAL java/lang/StringBuilder.<init>()V 
    ILOAD 1 
    INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder; 
    LDC "foo" 
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; 
    LDC "bar" 
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; 
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String; 
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V 
    L2 
    LINENUMBER 11 L2 
    RETURN 
    L3 
    LOCALVARIABLE args [Ljava/lang/String; L0 L3 0 
    LOCALVARIABLE a I L1 L3 1 
    MAXSTACK = 3 
    MAXLOCALS = 2 
} 

Wie Sie sehen können, "foo" und "bar" sind nicht automatisch verkettet.

Ich habe keine Ahnung, ob das JIT die unerwünschte Verkettung entfernen kann.

Verwandte Themen