Время выполнения Scala в Eclipse

Когда я запускаю программы Scala из Eclipse, происходит что-то подозрительное. Я запускаю объект App, и его запуск занимает 7,8 с (фактическое время выполнения рассчитывается с помощью System.nanoTime в объекте). Когда я запускаю тот же файл.class из командной строки, это занимает 2,5 с.

Я замечаю над окном консоли это говорит

<terminated> Run(1)[Scala Application] C:\Program Files\Java\jre6\bin\javaw.exe

Интересно, имеет ли это какое-то отношение ко времени. Кроме того, вот мои настройки eclipse.ini, которые я установил в соответствии с рекомендациями на страницах Scala IDE:

-vm
C:\Program Files\Java\jre6\bin
-startup
plugins/org.eclipse.equinox.launcher_1.1.0.v20100507.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.1.R36x_v20100810
-product
org.eclipse.epp.package.java.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms256m
-Xmx2048m
-XX:PermSize=64m
-Xss1M
-server
-XX:+DoEscapeAnalysis
-XX:+UseConcMarkSweepGC
-XX:+UseCompressedOops

Я на 99% уверен, что этот код занимал 0,7 с для запуска в Eclipse пару дней назад. Я попытался вставить код в новый проект и запустить его оттуда, но это не меняет времени выполнения. В проекте используются глобальные настройки компилятора Scala, и все они установлены по умолчанию.

ОБНОВЛЕНИЕ: Я только что попытался поменять местами библиотеку Scala 2.9.0.1, чтобы она использовала ту же самую версию, что и командная строка, и не имело никакого значения во время выполнения.

Я также попытался запустить файл из командной строки со всеми параметрами -vmargs выше, и это не имеет значения.

Любые идеи, что происходит, или какие-либо настройки мне нужно проверить? Благодарю.


ОБНОВЛЕНИЕ 2: я сам наполовину ответил на вопрос - я выполнял код по-разному; но вот проблема:

Версия 1, расширяющая приложение:

object P005_V2 extends App { 
  def isDivis(x:Int, i:Int):Boolean = {
    if(i > 20) true
    else if(x % i != 0) false
    else isDivis(x, i+1)
  }
  def find(n:Int):Int = if (isDivis(n, 2)) n else find (n+2)

  val t = System.nanoTime;
  println (find (2))
  println(System.nanoTime - t)
}

Занимает 0,7 с в Eclipse, 2,3 с из командной строки

Версия 2, создание экземпляра из другого объекта

object P005_V2 { 
  def isDivis(x:Int, i:Int):Boolean = {
    if(i > 20) true
    else if(x % i != 0) false
    else isDivis(x, i+1)
  }
  def find(n:Int):Int = if (isDivis(n, 2)) n else find (n+2)

  val t = System.nanoTime;
  println (find (2))
  println(System.nanoTime - t)
}

object Run extends App {
  P005_V2
}

Занимает 7,6 с в Eclipse, 2,5 с из командной строки

Итак, я понимаю, что приложение было разработано так, что вы можете делать вещи в конструкторе, и они будут оптимизированы, в отличие от устаревших Application, Кажется, что здесь происходит, потому что я звоню println(find(2)) от конструктора, версия которого не расширяется Appне будет оптимизирован и займет больше времени.

Но остается вопрос, почему огромные различия в скорости между выполнением через Eclipse и командной строкой?

Действительно, обе версии командной строки работают медленно, потому что версия Java в командной строке занимает 0,7 с, а версия Scala должна быть настолько быстрой (насколько это возможно, что продемонстрировано версией 1, запущенной в Eclipse).

1 ответ

Решение

После некоторых экспериментов у меня есть 95% ответа, поэтому я дам его сам:

Я использую Windows 7 64-bit.

Командная строка использует 32-битную среду JDK, как указано в переменной JAVA_HOME.

Eclipse использует 64-битную среду JRE, указанную через Window | Preferences | Java | Installed JREs и Системная библиотека проекта.

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

java из командной строки будет использовать 64-битную JVM, когда она доступна, независимо от того, что указано в JAVA_HOME, в отличие от scala, что может привести к путанице в сравнении Scala/Java.

Разница во времени выполнения между версиями 1 и 2, описанными выше, заключается в том, что, как отмечалось, версия 2 выполняет дорогостоящие вычисления в конструкторе объекта (а не метод delayedInt, когда App используется в версии 1). Версия 2 очень неправильная, так как вы не должны делать дорогостоящие вычисления и ввод / вывод в конструкторе. Если вы позвоните find метод непосредственно из Run объект, то аномалия скорости уходит.

Заключение:

Время выполнения зависит от того, используете ли вы 32-разрядную или 64-разрядную JVM, и это указывается в Eclipse независимо от настроек среды. Если вы используете 64-битную версию, вы должны быть особенно осторожны, чтобы не выполнять тяжелую обработку внутри конструктора.

Продолжительность (секунды):

                   Java                          Scala                         Scala - within constructor
                   JRE 64-bit     JDK 32-bit     JRE 64-bit     JDK 32-bit     JRE 64-bit     JDK 32-bit
Windows 7 64-bit   0.7            2.4            0.7            2.5            7.6            2.5
Windows XP 32-bit  n/a            13.4           n/a            14             n/a            13.1
(slower machine)
Другие вопросы по тегам