无形标记类型的运行时开销

时间:2018-09-24 03:07:07

标签: scala types shapeless

阅读博客后,我得到的印象是,shapeless提供的标记类型没有运行时开销。

  1. 将原始类型实例转换为标记类型确实没有运行时开销吗?
  2. 将原始集合实例转换为标记类型集合是否没有运行时开销是真的吗?

带有来自shapeless的标记类型的相关源代码:

object tag {
  def apply[U] = new Tagger[U]
  trait Tagged[U]
  type @@[+T, U] = T with Tagged[U]
  class Tagger[U] {
    def apply[T](t : T) : T @@ U = t.asInstanceOf[T @@ U]
  }
}

对于带有示例代码的问题1:

trait IdTag
type Id = Long @@ IdTag

val id1: Id = tag[IdTag][Long](1000L) // way #1

val helper = tag[IdTag]
val id2: Id = helper[Long](1000L) // way #2

val id3: Id = 1000L.asInstanceOf[Id] // way #3

以#1和#2的方式tag[IdTag]创建tag.Tagger[IdTag]的实例,它是一个普通对象。 编译器是否会消除创建过程,以免产生运行时开销?还是创造成本如此之小,以至于人们只是忽略了它?

方法3是否合法,并且是避免中间对象创建的更好方法?

对于带有示例代码的问题2:

val m0: Map[Long, Double] = Map(...) // a very large map

val m1: Map[Id, Double] = m0.map(e => tag[IdTag][Long](e._1) -> e._2) // way #1

val helper = tag[IdTag]
val m2: Map[Id, Double] = m0.map(e => helper[Long](e._1) -> e._2) // way #2

val m3: Map[Id, Double] = m0.asInstanceOf[Map[Id, Double]] // way #3

从性能上来说,确实是#3方式是最好的,而#2方式则更糟,因为它需要遍历地图并创建新地图,而#3方式是最差的,因为它不需要仅遍历地图并创建新地图,还创建tag.Tagger s的日志?

0 个答案:

没有答案