2017-01-09 4 views
1

長いコードを2つに分けて読みやすくするために、行間にプラス記号が挿入されます(テキスト間で分割されている場合)。 たとえば、テキストの一部をロギングしているテキストの途中で長い行を分割します。長いログラインを2つに分割する際のパフォーマンスの問題

これは、文字列連結を追加することで回避できますか?あるいは、読みやすさのトレードオフが重くなるでしょうか?

+1

私はコンパイラがあなたのために1つのすばらしい文字列リテラルに変換することを約99%確信しています – Rogue

答えて

2

はい、パフォーマンスにわずかな影響があります。通常のコンパイラは最適化を行いません。単に+演算子をStringBuilderメソッド呼び出しに置き換えます。例えば。 String s = "x" + "y" + "z";がある場合は、バイトコードにコンパイルする前にString s = new StringBuilder().append("x").append("y").append("z");に置き換えてもかまいません。しかしここには本当の最適化はありません。バイトコードを生成する前に、それをString s = "xyz";に置き換えることはありません。 JITコンパイラがネイティブプロセッサ命令を生成する前に最適化を行っているかどうかはわかりません。しかし、それが実行されても、実行時には小さなパフォーマンスが発生します。

個人的には、パフォーマンスが極端に低下した場合、私は優雅さと可読性をもっと気にします。

0

すべての通常のJavaコンパイラは、実行時に文字列リテラルを連結するようなやり方で成熟していません。確認しよう。このコードを考える:

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); 
    } 
} 

私のJavaコンパイラ8 - オラクルの標準は - javap出力によって示されるように正しいことを行います。

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

それは依存します。

定数だけがある場合、javacがそれを処理します。以下のプログラム:

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

次のバイトコード(一部非関連部分を削除)に変わる:

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 
} 

あなたがそこにfoobarの定数を見ることができます。この場合、パフォーマンスが低下することはありません。我々はより現実的なものにプログラムを変更するかどうただし

public class Main { 

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

我々は、次のバイトコードを取得:あなたは、「foo」と「bar」を見ることができるように

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 
} 

ではありませんが自動的に連結されます。

JITが不要な連結を削除できるかどうかはわかりません。

関連する問題