Scala "примитивная" оптимизация - PullRequest
2 голосов
/ 09 мая 2011

В некоторых местах я видел объявление, похожее на:

«Компилятор 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): >> 28.811M

mem_used (scala long): >> 36.811M

Я понимаю, что scala У любого типа есть дополнительные издержки, но где происходит оптимизация?

Ответы [ 3 ]

9 голосов
/ 09 мая 2011

Зачем беспокоиться о таком сложном способе выяснить, что к чему компилируется? Просто запустите 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();
}
2 голосов
/ 09 мая 2011

Как сказано в документации Runtime.freeMemory, возвращаемое значение зависит от того, когда был сделан последний gc. Так что ошибка, скорее всего, в вашем способе измерения.

1 голос
/ 09 мая 2011

Действительно сложно измерить использование памяти в Java.Все, что вы делаете, затрагивающее подсистему памяти, будет вызывать резкие колебания результатов - и даже если вы ничего не делаете, вы не можете быть уверены, что JVM не создает объекты для запуска самой себя.В частности, вы должны использовать циклы while, а не for, чтобы заполнить массивы (чтобы избежать создания объектов в for).С другой стороны, выделение памяти, которое создает массив, может инициировать сборку мусора.Лучше всего запустить jvm с -verbose:gc, чтобы убедиться, что между вашими измерениями не происходит сборка мусора, например

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

, и если вы видите, что GC находится между началом и окончанием, игнорируйте этот запуск.

...