Scala“原始”优化

时间:2011-05-09 14:58:53

标签: optimization scala types primitive

在一些地方,我看到过类似的声明:

“Scala编译器在编译代码中尽可能使用Java数组,原始类型和本机算法” (在Scala书中编程)。 但实际上我没有看到这一点,例如在下面的代码中,scala类型使用的内存多于java类型(我使用totalMemory和freeMemory方法计算):

long[] la = new Array[java.lang.Long](1024 * 1024);
for(i <- 0 until la.length)
  la(i) = new java.lang.Long(0);

val La = new Array[Long](1024 * 1024);
for(i <- 0 until La.length)
  La(i) = 0l;

mem_used(java long):&gt;&gt; 28.811M

mem_used(scala long):&gt;&gt; 36.811M

我意识到scala任何类型都有额外的开销,但优化发生在哪里?

3 个答案:

答案 0 :(得分:9)

为什么要花费这么费力的方式来试图找出什么被编译成什么?只需在类上运行javap,您就会看到完全它是什么。

C:\>type La.scala
class La {
    val La = new Array[Long](1024 * 1024);
}

C:\>javap La
Compiled from "La.scala"
public class La extends java.lang.Object implements scala.ScalaObject{
    public long[] La();
    public La();
}

答案 1 :(得分:2)

正如Runtime.freeMemory的文档所说,返回的值取决于最后一次gc的完成时间。所以错误很可能是你测量的方式。

答案 2 :(得分:1)

在Java中测量内存使用情况真的很难。你做的任何触及内存子系统的事情都会导致结果波动很大 - 即使你什么都不做,你也不能确定JVM是不是在创建对象以便自己运行。特别是,您应该使用while循环而不是for循环来填充数组(以避免在for中创建任何对象)。然后,创建数组的内存分配可能会触发垃圾回收。最好的办法是使用-verbose:gc运行jvm,以确保测量之间不会发生垃圾收集,例如

println("Starting")
// Measure free memory
// Create some stuff
// Measure free memory
println("Ending")

如果你看到GC介于开始和结束之间,请忽略该运行。