AFAIU, CollectionConverters
- это оболочки, просто делегирующие вызовы в базовую коллекцию, поэтому стоимость должна состоять в выделении одного объекта, а затем в косвенном вызове метода, например, Преобразование между Java и Scala Collections состояний
Внутренне, эти преобразования работают, устанавливая объект-оболочку, который перенаправляет все операции в базовый объект коллекции. Таким образом, коллекции никогда не копируются при преобразовании между Java и Scala.
Анализ SetWrapper
на самом деле мы видим, что он просто делегирует вызов underlying
collection
class SetWrapper[A](underlying: Set[A]) extends ju.AbstractSet[A] with Serializable { self =>
...
def size = underlying.size
...
}
Однако рассмотрим следующий эталонный тест jmh
import org.openjdk.jmh.annotations._
import scala.jdk.CollectionConverters._
import java.{util => ju}
@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So31830028 {
val size = 1000000
val scalaSet: Set[Int] = (1 to size).toSet
val javaSet: ju.Set[Int] = (1 to size).toSet.asJava
@Benchmark def scala = scalaSet.size
@Benchmark def scalaAsJava = scalaSet.asJava.size
@Benchmark def java = javaSet.size
@Benchmark def javaAsScala = javaSet.asScala.size
}
, где sbt "jmh:run -i 10 -wi 5 -f 2 -t 1 bench.So31830028"
дает
[info] Benchmark Mode Cnt Score Error Units
[info] So31830028.java thrpt 20 356515729.840 ± 64691657.672 ops/s
[info] So31830028.javaAsScala thrpt 20 270053471.338 ± 36854051.611 ops/s
[info] So31830028.scala thrpt 20 448415156.726 ± 53674976.259 ops/s
[info] So31830028.scalaAsJava thrpt 20 211808793.234 ± 57898858.737 ops/s
Почему, кажется, существует значительное снижение производительности, если CollectionConverters
простые обертки?
Вопрос вызван Стоимость неявного преобразования из java в scala коллекций