title: Costly performance of CollectionConverters despite being wrappers?
body: <p>AFAIU, <a href="https://www.scala-lang.org/api/current/scala/jdk/CollectionConverters$.html" rel="nofollow noreferrer"><code>CollectionConverters</code></a> are wrappers simply delegating calls to the underlying collection, thus the cost should be single object allocation and then single method call indirection, for example, <a href="https://docs.scala-lang.org/overviews/collections-2.13/conversions-between-java-and-scala-collections.html" rel="nofollow noreferrer">Conversion Between Java and Scala Collections</a> states</p>
  
  <blockquote>
    <p>Internally, these conversion work by setting up a “wrapper” object
    that forwards all operations to the underlying collection object. So
    collections <strong>are never copied</strong> when converting between Java and Scala.</p>
  </blockquote>
  
  <p>Analysing <a href="https://github.com/scala/scala/blob/bc050293f99d6905df096db9c02560c3af854b47/src/library/scala/collection/convert/JavaCollectionWrappers.scala#L130" rel="nofollow noreferrer"><code>SetWrapper</code></a> indeed we see it simply delegates the call to the <code>underlying</code> collection</p>
  
  <pre><code>class SetWrapper[A](underlying: Set[A]) extends ju.AbstractSet[A] with Serializable { self =&gt;
    ...
    def size = underlying.size
    ...
  }
  </code></pre>
  
  <p>However, consider the following jmh benchmark</p>
  
  <pre><code>import org.openjdk.jmh.annotations._
  import scala.jdk.CollectionConverters._
  import java.{util =&gt; 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
  }
  </code></pre>
  
  <p>where <code>sbt "jmh:run -i 10 -wi 5 -f 2 -t 1 bench.So31830028"</code> gives</p>
  
  <pre><code>[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
  </code></pre>
  
  <p>Why there seems to be a significant performance penalty if <code>CollectionConverters</code> are simple wrappers?</p>
  
  <p><sup>The question is inspired by <a href="https://stackoverflow.com/q/31830028/5205022">Cost of implicit conversion from java to scala collections</a></sup></p>