为什么在Scala的标准库中@specialized的东西很少?

时间:2011-03-29 19:14:25

标签: performance scala collections autoboxing specialized-annotation

我在Scala 2.8.1的标准库的源代码中搜索了@specialized的使用。看起来只有少数特征和类使用此注释:Function0Function1Function2Tuple1Tuple2Product1Product2AbstractFunction0AbstractFunction1AbstractFunction2

所有集合类都不是@specialized。为什么不?这会产生太多的课程吗?

这意味着使用带有基本类型的集合类效率非常低,因为会有很多不必要的装箱和拆箱。

拥有IndexedSeq s的不可变列表或序列(具有Int特征)的最有效方法是什么,避免装箱和拆箱?

3 个答案:

答案 0 :(得分:18)

专业化课程的成本很高,因此必须仔细考虑。在收藏品的特殊情况下,我认为影响将是巨大的。

尽管如此,这仍是一项持续的努力 - Scala图书馆几乎没有开始专业化。

答案 1 :(得分:16)

在类的大小和编译时,Specialized可能很昂贵(指数)。它的大小不仅仅是接受的答案。

打开你的scala REPL并输入。

import scala.{specialized => sp}
trait S1[@sp A, @sp B, @sp C, @sp D] { def f(p1:A): Unit }

抱歉:-)。它就像一个编译器炸弹。

现在,让我们采取一个简单的特征

trait Foo[Int]{ }

以上将导致两个编译类。 Foo,纯接口和Foo $ 1,类实现。

现在,

trait Foo[@specialized A] { }

此处的专用模板参数会针对9种不同的基本类型(void,boolean,byte,char,int,long,short,double,float)进行扩展/重写。所以,基本上你最终会得到20个而不是2个。

回到具有5个专用模板参数的特征,为每种可能的基元类型组合生成类。即其复杂性呈指数级增长。

2 * 10 ^ (没有专门的参数)

如果要为特定基元类型定义类,则应该更加明确它,例如

trait Foo[@specialized(Int) A, @specialized(Int,Double) B] { }

可以理解的是,在构建通用库时,必须使用专业人员才能节俭。

Here是保罗菲利普斯咆哮的。

答案 2 :(得分:6)

对我自己的问题的部分回答:我可以像这样在IndexedSeq中包装一个数组:

import scala.collection.immutable.IndexedSeq

def arrayToIndexedSeq[@specialized(Int) T](array: Array[T]): IndexedSeq[T] = new IndexedSeq[T] {
  def apply(idx: Int): T = array(idx)
  def length: Int = array.length
}

(当然,如果你有权访问底层数组,你仍然可以修改内容,但我会确保数组不会传递给我程序的其他部分。)