我正在學(xué)習(xí)如何使用JMH對事物進(jìn)行微基準(zhǔn)測試。我從看似簡單的內(nèi)容開始:StringBuildervs的字符串連接String +=。據(jù)我了解,我應(yīng)該制作一個State包含的實例的對象,StringBuilder因為我不想對其構(gòu)造函數(shù)進(jìn)行基準(zhǔn)測試(無論如何,我也不想每次迭代都為空)。這同樣適用于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()在每次迭代結(jié)束時都調(diào)用。我僅測試串聯(lián)。因此,我決定通過返回null而將其刪除。但是,這是在第一次熱身迭代期間發(fā)生的: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)我知道,如果JMHStringBuilder盡可能快地追加,我將很快耗盡內(nèi)存,因此我對這個OutOfMemoryError問題并不感到驚訝。但是我不明白為什么要builder.toString()修復(fù)它。所以我的問題是:為什么要builder.toString()避免出現(xiàn)OutOfMemoryError問題?StringBuilder還是不將所有字符都保留在內(nèi)存中嗎?假設(shè)我既不希望StringBuilder的構(gòu)造.toString()方法也不希望其 方法成為基準(zhǔn)測試的一部分,那么如何正確編寫此測試?
1 回答

揚帆大魚
TA貢獻(xiàn)1799條經(jīng)驗 獲得超9個贊
調(diào)用toString()
會花費時間,并產(chǎn)生垃圾,這需要運行GC,從而進(jìn)一步降低了代碼的速度。
由于測試是有時間限制的,因此這些減速可能會導(dǎo)致測試在消耗所有內(nèi)存之前停止。如果增加時間限制,即使使用,代碼也可能因OOM而失敗toString
,這只會花費很多時間。
添加回答
舉報
0/150
提交
取消