scala.collection.immutable.LongMapのメモリ効率

Scalaの標準ライブラリにはLongMapやIntMapという、keyが特定の型に特化したMapがあります。

特化しているなら、それらの型の場合にはこれを使った方が効率いいのでは???と思うかもしれません。

しかし、先に結論を書いておくと、2025年時点のScalaにおいて、そんなことはない、という記事です。*1

速度は知りませんが、以下の方法ですごく雑に実験をしました

  • Scala 2.13.17のREPLを起動
  • REPL上で、以下のように、immutableなHashMapとLongMapを大量に生成
    • もちろん、それぞれREPLは起動し直してします
  • 他の条件は同じ
  • メモリ解放されないようにあえてlazy valで保持したので、そこからさらに System.gc などしても大して変わらない
    • lazyなのは、単にREPLに表示させようとすると無駄に時間消費するだけなので、それ避けるため
  • そのREPLのJVMプロセスを、このツール https://visualvm.github.io/ で観察
Welcome to Scala 2.13.17 (OpenJDK 64-Bit Server VM, Java 21.0.8).
Type in expressions for evaluation. Or try :help.

scala> lazy val x = List.tabulate(10000)(n => scala.collection.immutable.HashMap((1 to n).map(a => (a: Long) -> a): _*))
lazy val x: List[scala.collection.immutable.HashMap[Long,Int]] // unevaluated

scala> println(x.size)
10000
Welcome to Scala 2.13.17 (OpenJDK 64-Bit Server VM, Java 21.0.8).
Type in expressions for evaluation. Or try :help.

scala> lazy val x = List.tabulate(10000)(n => scala.collection.immutable.LongMap((1 to n).map(a => (a: Long) -> a): _*))
lazy val x: List[scala.collection.immutable.LongMap[Int]] // unevaluated

scala> println(x.size)
10000

結果の画像は一番下に貼っておきますが、まとめると

  private[immutable] case class Tip[+T](key: Long, value: T) extends LongMap[T] {
    // 中身省略
  }

  private[immutable] case class Bin[+T](prefix: Long, mask: Long, left: LongMap[T], right: LongMap[T]) extends LongMap[T] {
    // 中身省略
  }

matsu-chara.hatenablog.com

LongMap

HashMap

*1:少なくともimmutable版において