用于性能的Vector或MutableList / ListBuffer

时间:2012-12-27 17:30:32

标签: performance scala playframework-2.0 immutability

如果这是重复的道歉 - 我做了一些搜索并且找不到我需要的东西。

我们的应用程序具有性能关键部分,可将Play 2.0 Enumerator(可被视为Stream)转换为List(或类似)。我们将在fold上使用Enumerator方法,问题是最有效的方法。 (我会在代码中使用Stream代替Enumerator,但这个想法应该是相同的。)

val incoming: Stream[Int] = ???
val result: Seq[Int] = incoming.fold(Seq.empty)(_ + _)
val result2: Seq[Int] = incoming.fold(MutableList.empty(_ += _).toSeq

所以问题基本上是,如何反复追加不可变的Vector比较重复追加性能关键代码中的可变MutableListListBuffer?我们已经抛出List,因为我们需要O(1)追加(不是前置)。但是,可变数据结构是否在性能或垃圾收集方面为我们提供了任何东西?

1 个答案:

答案 0 :(得分:17)

最好使用ArrayBuffer。在我的机器上,您每秒可获得以下数量的附加内容:

preallocated Array[Int]    -- 830M
resized (x2) Array[Int]    -- 263M
Vector.newBuilder + result -- 185M
mutable.ArrayBuffer        -- 125M
mutable.ListBuffer         -- 100M
mutable.MutableList        --  71M
immutable.List + reverse   --  68M
immutable.Vector           --   8M

我认为你并不总是只是存储整数,并且你希望所有的集合都没有额外的包装,所以ArrayBuffer是性能最佳的解决方案,只要你只需要追加到一端即可。该列表支持双向添加,具有可比性。相比之下,矢量非常慢 - 只有在你可以利用大量数据共享的情况下才使用它,或者一次性创建它们(参见Vector.newBuilder结果,这太棒了;它是一个很棒的访问数据结构,迭代,创建和备用更新,而不是一直更新。