我是Scala的新手,我正在尝试从IndexedSeq创建一个大地图,我发现在SO上提到功能样式地图创建比命令式Java风格慢得多,决定测试它我的自我。到目前为止,我发现Scala功能样式代码不仅速度慢,而且势在必行。我做错了什么,为什么我的Scala代码慢几倍?在我的家用计算机上,它运行时间为220毫秒(Java)和460毫秒(Scala)
Scala version
private val testSize: Int = 1000000
val seq: IndexedSeq[Int] = for (i <- 0 until testSize) yield Random.nextInt()
val warmupMapt0 = System.nanoTime()
var warmupMap: mutable.HashMap[Int, Int] = new mutable.HashMap[Int, Int]
warmupMap.sizeHint(testSize)
for (i <- 0 until testSize) warmupMap.put(i, seq(i))
val t0 = System.nanoTime()
var map: mutable.HashMap[Int, Int] = new mutable.HashMap[Int, Int]
map.sizeHint(testSize)
for (i <- 0 until testSize) map.put(i, seq(i))
println((System.nanoTime() - t0)/ 1000000 + " ms.")
Java version
private static final int TEST_SIZE = 1_000_000;
public static void main(String[] args) {
int[] ar = new int[TEST_SIZE];
Random random = new Random();
for (int i = 0; i < TEST_SIZE; i++) {
ar[i] = random.nextInt();
}
Map<Integer, Integer> warmupMap = new HashMap<>(TEST_SIZE);
for (int i = 0; i < TEST_SIZE; i++) {
warmupMap.put(i, ar[i]);
}
Map<Integer, Integer> map = new HashMap<>(TEST_SIZE);
long t0 = System.nanoTime();
for (int i = 0; i < TEST_SIZE; i++) {
map.put(i, ar[i]);
}
System.out.println((System.nanoTime() - t0) / 1_000_000 + " ms.");
}
答案 0 :(得分:3)
我认为问题的一个来源是使用IndexedSeq。它默认由Vector实现,它通常是一个智能集合,但在你的情况下,它为创建&#34;数组&#34;添加了相当大的常数因子。数字,而不是通过索引访问它们。如果您希望您的代码更接近于java代码,则以下代码将成为答案:
val ar = new Array(TestSize)
for (i <- 0 until TestSize) ar(i) = Random.next()
我读过有关foreach循环优化的地方,无法找到哪里,基本上给予足够的预热运行foreach循环应该具有与while循环相比的效率,给定传递给它的函数可以内联。
修改强>
代码可以进一步简化:
val ar = Array.fill(TestSize)(Random.next())
Alexey Romanov提出的评论意见。
答案 1 :(得分:0)
这可能是for
理解。在Scala中,它们以与Java中for
循环完全不同的方式工作,并生成JVM无法很好地优化的代码。参见例如http://www.scalablescala.com/roller/scala/entry/why_is_using_for_foreach或http://downloads.typesafe.com/website/presentations/ScalaDaysSF2015/T2_Rytz_Backend_Optimizer.pdf(从幻灯片37开始)。您可以使用while
循环或宏库(如http://scala-blitz.github.io/,https://github.com/non/spire或https://github.com/nativelibs4java/scalaxy-streams来解决此问题。