Yet another post about performance and microbenchmarks. Yes, I know.

Very small JMH benchmark:

@BenchmarkMode(Array(Mode.AverageTime))

@OutputTimeUnit(TimeUnit.NANOSECONDS)

@Fork(value = 2, jvmArgs = Array("-Xmx2G"))

@Measurement(iterations = 7, time = 3, timeUnit = TimeUnit.SECONDS)

@Warmup(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)

class StringBuilderBenchmark {



@Benchmark

def javaStringBuilder: String = {

new java.lang.StringBuilder().append("abc").append("def")

.toString

}



@Benchmark

def javaStringBuilder2: String = {

new java.lang.StringBuilder().append(495-char-length-string).append(495-char-length-string).toString

} @Benchmark

def scalaStringBuilder: String = {

new scala.collection.mutable.StringBuilder().append("abc")

.append("def").toString

} @Benchmark

def scalaStringBuilder: String = {

new scala.collection.mutable.StringBuilder().append(495-char-length-string).append(495-char-length-string).toString

}

}

And the result:

Benchmark Mode Cnt Score Error Units

javaStringBuilder avgt 14 8.754 ± 0.465 ns/op

javaStringBuilder2 avgt 14 237.280 ± 0.828 ns/op

scalaStringBuilder avgt 14 27.299 ± 0.096 ns/op

scalaStringBuilder2 avgt 14 720.742 ± 3.528 ns/op

Wow. Apparently, JVM doesn’t do some optimization over wrapped StringBuilder. I’ve noticed this performance degradation on a more complex test, so, I don’t think it’s just about “microbenchmarking is evil”.

The saddest part, that Scala developers “suffer” just to have StringBuilder as a collection. But do we really need collection features from it? I doubt it.

Source code is on GitHub.