長いコードを2つに分けて読みやすくするために、行間にプラス記号が挿入されます(テキスト間で分割されている場合)。 たとえば、テキストの一部をロギングしているテキストの途中で長い行を分割します。長いログラインを2つに分割する際のパフォーマンスの問題
これは、文字列連結を追加することで回避できますか?あるいは、読みやすさのトレードオフが重くなるでしょうか?
長いコードを2つに分けて読みやすくするために、行間にプラス記号が挿入されます(テキスト間で分割されている場合)。 たとえば、テキストの一部をロギングしているテキストの途中で長い行を分割します。長いログラインを2つに分割する際のパフォーマンスの問題
これは、文字列連結を追加することで回避できますか?あるいは、読みやすさのトレードオフが重くなるでしょうか?
はい、パフォーマンスにわずかな影響があります。通常のコンパイラは最適化を行いません。単に+演算子をStringBuilder
メソッド呼び出しに置き換えます。例えば。 String s = "x" + "y" + "z";
がある場合は、バイトコードにコンパイルする前にString s = new StringBuilder().append("x").append("y").append("z");
に置き換えてもかまいません。しかしここには本当の最適化はありません。バイトコードを生成する前に、それをString s = "xyz";
に置き換えることはありません。 JITコンパイラがネイティブプロセッサ命令を生成する前に最適化を行っているかどうかはわかりません。しかし、それが実行されても、実行時には小さなパフォーマンスが発生します。
個人的には、パフォーマンスが極端に低下した場合、私は優雅さと可読性をもっと気にします。
すべての通常の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
それは依存します。
定数だけがある場合、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が不要な連結を削除できるかどうかはわかりません。
私はコンパイラがあなたのために1つのすばらしい文字列リテラルに変換することを約99%確信しています – Rogue