私はJMHで物事をマイクロベンチマークする方法を学んでいます。以下のための文字列の連結:私は、一見単純な何かを始めStringBuilder
VS String +=
。
私の理解から、私は作るべきState
のインスタンスを含むオブジェクトをStringBuilder
、私はベンチマークにそのコンストラクタを望んでいない(また私はすべての反復とにかく空のものにしたいですか)。ので、同じことがのために行くString +=
のテスト-私はしたいString
私の中でオブジェクトをState
新しい文字列と連結します。
これは私のコードです:
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class Test {
@State(Scope.Thread)
public static class BenchmarkState {
public StringBuilder builder;
public String regularString;
@Setup(Level.Iteration)
public void setup() {
builder = new StringBuilder();
regularString = "";
}
}
@Benchmark
public String stringTest(BenchmarkState state) {
state.regularString += "hello";
return state.regularString;
}
@Benchmark
public String stringBuilderTest(BenchmarkState state) {
state.builder.append("hello");
return state.builder.toString();
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(Test.class.getSimpleName())
.forks(1)
.timeUnit(TimeUnit.MILLISECONDS)
.mode(Mode.Throughput)
.measurementTime(TimeValue.seconds(10))
.build();
new Runner(opt).run();
}
}
それは動作しますが、私は考えていた-私はコールする必要はありません.toString()
すべての反復の終わりに。私は唯一の連結をテストしています。だから、僕は返すことでそれを削除することを決めたnull
代わりに。
しかし、その後、これが最初のウォームアップ反復中に発生します。
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
私はJMHがに追加された場合、私はかなり迅速にメモリ不足になることを理解するStringBuilder
ことができるように速いように私はに驚いていないよので、OutOfMemoryError
問題。しかし、私はない理由を理解していないbuilder.toString()
それを修正します。
だから、私の質問は以下のとおりです。
なぜ
builder.toString()
避けるOutOfMemoryError
問題は?ていないStringBuilder
、まだかかわらず、メモリ内のすべての文字を保ちますか?私はどちらも望んでいないと仮定すると
StringBuilder
、コンストラクタもそのの.toString()
方法は、ベンチマークの一部であることを、どのように私は適切にこのテストを書くのですか?
呼び出しは、toString()
さらにコードを減速、GC実行を必要とする、時間がかかり、そしてごみを生成します。
テストは時間制限があるので、それはすべてのメモリを消費する前に、それらの速度低下可能性の高い原因テストが停止します。あなたは制限時間を増やした場合、コードはそうでもしOOMで失敗しますtoString
、それだけで長いLOTがかかります。