Last active
March 9, 2021 03:10
-
-
Save douglarek/6085957eae1acfeecee4a0185d594ede to your computer and use it in GitHub Desktop.
java stringBuilder vs stringConcat with JMH
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# JMH version: 1.28 | |
# VM version: JDK 11.0.10, OpenJDK 64-Bit Server VM, 11.0.10+9-Ubuntu-0ubuntu1.20.04 | |
# VM invoker: /usr/lib/jvm/java-11-openjdk-amd64/bin/java | |
# VM options: <none> | |
# Blackhole mode: full + dont-inline hint | |
# Warmup: 3 iterations, 10 s each | |
# Measurement: 5 iterations, 10 s each | |
# Timeout: 10 min per iteration | |
# Threads: 1 thread, will synchronize iterations | |
# Benchmark mode: Average time, time/op | |
# Benchmark: org.sample.MyBenchmark.stringBuilder | |
# Parameters: (count = 100) | |
# Run progress: 0.00% complete, ETA 00:05:20 | |
# Fork: 1 of 1 | |
# Warmup Iteration 1: 0.403 ms/op | |
# Warmup Iteration 2: 0.987 ms/op | |
# Warmup Iteration 3: 1.331 ms/op | |
Iteration 1: 1.639 ms/op | |
Iteration 2: 1.882 ms/op | |
Iteration 3: 2.250 ms/op | |
Iteration 4: 2.111 ms/op | |
Iteration 5: 2.323 ms/op | |
Result "org.sample.MyBenchmark.stringBuilder": | |
2.041 ±(99.9%) 1.079 ms/op [Average] | |
(min, avg, max) = (1.639, 2.041, 2.323), stdev = 0.280 | |
CI (99.9%): [0.962, 3.120] (assumes normal distribution) | |
# JMH version: 1.28 | |
# VM version: JDK 11.0.10, OpenJDK 64-Bit Server VM, 11.0.10+9-Ubuntu-0ubuntu1.20.04 | |
# VM invoker: /usr/lib/jvm/java-11-openjdk-amd64/bin/java | |
# VM options: <none> | |
# Blackhole mode: full + dont-inline hint | |
# Warmup: 3 iterations, 10 s each | |
# Measurement: 5 iterations, 10 s each | |
# Timeout: 10 min per iteration | |
# Threads: 1 thread, will synchronize iterations | |
# Benchmark mode: Average time, time/op | |
# Benchmark: org.sample.MyBenchmark.stringBuilder | |
# Parameters: (count = 10000) | |
# Run progress: 25.00% complete, ETA 00:04:00 | |
# Fork: 1 of 1 | |
# Warmup Iteration 1: 6.367 ms/op | |
# Warmup Iteration 2: 17.183 ms/op | |
# Warmup Iteration 3: 22.627 ms/op | |
Iteration 1: 27.120 ms/op | |
Iteration 2: 29.092 ms/op | |
Iteration 3: 31.841 ms/op | |
Iteration 4: 34.816 ms/op | |
Iteration 5: 36.769 ms/op | |
Result "org.sample.MyBenchmark.stringBuilder": | |
31.928 ±(99.9%) 15.274 ms/op [Average] | |
(min, avg, max) = (27.120, 31.928, 36.769), stdev = 3.967 | |
CI (99.9%): [16.653, 47.202] (assumes normal distribution) | |
# JMH version: 1.28 | |
# VM version: JDK 11.0.10, OpenJDK 64-Bit Server VM, 11.0.10+9-Ubuntu-0ubuntu1.20.04 | |
# VM invoker: /usr/lib/jvm/java-11-openjdk-amd64/bin/java | |
# VM options: <none> | |
# Blackhole mode: full + dont-inline hint | |
# Warmup: 3 iterations, 10 s each | |
# Measurement: 5 iterations, 10 s each | |
# Timeout: 10 min per iteration | |
# Threads: 1 thread, will synchronize iterations | |
# Benchmark mode: Average time, time/op | |
# Benchmark: org.sample.MyBenchmark.stringConcat | |
# Parameters: (count = 100) | |
# Run progress: 50.00% complete, ETA 00:02:40 | |
# Fork: 1 of 1 | |
# Warmup Iteration 1: 4.259 ms/op | |
# Warmup Iteration 2: 8.805 ms/op | |
# Warmup Iteration 3: 11.861 ms/op | |
Iteration 1: 13.923 ms/op | |
Iteration 2: 16.093 ms/op | |
Iteration 3: 18.706 ms/op | |
Iteration 4: 21.460 ms/op | |
Iteration 5: 21.314 ms/op | |
Result "org.sample.MyBenchmark.stringConcat": | |
18.299 ±(99.9%) 12.664 ms/op [Average] | |
(min, avg, max) = (13.923, 18.299, 21.460), stdev = 3.289 | |
CI (99.9%): [5.636, 30.963] (assumes normal distribution) | |
# JMH version: 1.28 | |
# VM version: JDK 11.0.10, OpenJDK 64-Bit Server VM, 11.0.10+9-Ubuntu-0ubuntu1.20.04 | |
# VM invoker: /usr/lib/jvm/java-11-openjdk-amd64/bin/java | |
# VM options: <none> | |
# Blackhole mode: full + dont-inline hint | |
# Warmup: 3 iterations, 10 s each | |
# Measurement: 5 iterations, 10 s each | |
# Timeout: 10 min per iteration | |
# Threads: 1 thread, will synchronize iterations | |
# Benchmark mode: Average time, time/op | |
# Benchmark: org.sample.MyBenchmark.stringConcat | |
# Parameters: (count = 10000) | |
# Run progress: 75.00% complete, ETA 00:01:20 | |
# Fork: 1 of 1 | |
# Warmup Iteration 1: 1128.453 ms/op | |
# Warmup Iteration 2: 1100.954 ms/op | |
# Warmup Iteration 3: 1462.695 ms/op | |
Iteration 1: 1983.978 ms/op | |
Iteration 2: 2379.345 ms/op | |
Iteration 3: 2521.124 ms/op | |
Iteration 4: 2744.632 ms/op | |
Iteration 5: 2943.203 ms/op | |
Result "org.sample.MyBenchmark.stringConcat": | |
2514.456 ±(99.9%) 1410.239 ms/op [Average] | |
(min, avg, max) = (1983.978, 2514.456, 2943.203), stdev = 366.234 | |
CI (99.9%): [1104.218, 3924.695] (assumes normal distribution) | |
# Run complete. Total time: 00:05:32 | |
REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on | |
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial | |
experiments, perform baseline and negative tests that provide experimental control, make sure | |
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts. | |
Do not assume the numbers tell you what you want them to tell. | |
Benchmark (count) Mode Cnt Score Error Units | |
MyBenchmark.stringBuilder 100 avgt 5 2.041 ± 1.079 ms/op | |
MyBenchmark.stringBuilder 10000 avgt 5 31.928 ± 15.274 ms/op | |
MyBenchmark.stringConcat 100 avgt 5 18.299 ± 12.664 ms/op | |
MyBenchmark.stringConcat 10000 avgt 5 2514.456 ± 1410.239 ms/op |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2014, Oracle America, Inc. | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* * Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the following disclaimer. | |
* | |
* * Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* * Neither the name of Oracle nor the names of its contributors may be used | |
* to endorse or promote products derived from this software without | |
* specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
* THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
package org.sample; | |
import java.util.concurrent.TimeUnit; | |
import org.openjdk.jmh.annotations.Benchmark; | |
import org.openjdk.jmh.annotations.BenchmarkMode; | |
import org.openjdk.jmh.annotations.Fork; | |
import org.openjdk.jmh.annotations.Measurement; | |
import org.openjdk.jmh.annotations.Mode; | |
import org.openjdk.jmh.annotations.OutputTimeUnit; | |
import org.openjdk.jmh.annotations.Param; | |
import org.openjdk.jmh.annotations.Scope; | |
import org.openjdk.jmh.annotations.Setup; | |
import org.openjdk.jmh.annotations.State; | |
import org.openjdk.jmh.annotations.Warmup; | |
import org.openjdk.jmh.runner.Runner; | |
import org.openjdk.jmh.runner.RunnerException; | |
import org.openjdk.jmh.runner.options.Options; | |
import org.openjdk.jmh.runner.options.OptionsBuilder; | |
@BenchmarkMode({ Mode.AverageTime }) | |
@State(Scope.Thread) | |
@Fork(1) | |
@OutputTimeUnit(TimeUnit.MILLISECONDS) | |
@Warmup(iterations = 3) | |
@Measurement(iterations = 5) | |
public class MyBenchmark { | |
@Param({ "100", "10000" }) | |
private int count; | |
private String s; | |
private StringBuilder sb; | |
@Setup | |
public void setUp() { | |
s = ""; | |
sb = new StringBuilder(); | |
} | |
@Benchmark | |
public String stringConcat() { | |
for (int i = 0; i < count; i++) { | |
s += i; | |
} | |
return s; | |
} | |
@Benchmark | |
public String stringBuilder() { | |
for (int i = 0; i < count; i++) { | |
sb.append(i); | |
} | |
return sb.toString(); | |
} | |
public static void main(String[] args) throws RunnerException { | |
Options options = new OptionsBuilder().include(MyBenchmark.class.getSimpleName()).build(); | |
new Runner(options).run(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment