なぜ.toString()は、StringBuilderのためのOutOfMemoryError例外を修正しているように見えるのでしょうか?

JVon:

私はJMHで物事をマイクロベンチマークする方法を学んでいます。以下のための文字列の連結:私は、一見単純な何かを始めStringBuilderVS 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がかかります。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=203570&siteId=1