开发者

Scala "primitive" optimisation

开发者 https://www.devze.com 2023-03-05 02:10 出处:网络
In several places I have seen a declaration similar to: \"The Scala compiler uses Java arrays, primitive types, and native arithmetic where possible in the compiled code\"

In several places I have seen a declaration similar to:

"The Scala compiler uses Java arrays, primitive types, and native arithmetic where possible in the compiled code" (Programming in Scala book). But in practise I am not seeing this, for example in the following code, the scala type is using more memory than the java type (which I calculated by using the totalMemory and freeMemory methods):

开发者_运维技巧
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):>> 28.811M

mem_used (scala long):>> 36.811M

I realise the scala Any type has additional overhead, but where is the optimisation happening?


Why bother with such a convoluted way of trying to find out what gets compiled to what? Just run javap on a class and you'll see exactly what it is.

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();
}


As the documentation of Runtime.freeMemory says, the value returned depends on when the last gc was done. So the error is likely in your way of measuring.


It's really hard to measure memory usage in Java. Anything you do that touches the memory subsystem will cause results to fluctuate wildly--and even if you do nothing, you can't be sure that the JVM isn't creating objects in order to run itself. In particular, you should use while loops not for loops in order to fill the arrays (to avoid any creation of objects in the for). Then again, the memory allocation that creates the array may trigger a garbage collection. Your best bet is to run the jvm with -verbose:gc to make sure no garbage collections happen between your measurements, e.g.

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

and if you see the GC come in between Starting and Ending, ignore that run.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号