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 Компилятор, и все они настроены по умолчанию.
UPDATE: я только что попробовал обмен в библиотеке 2.9.0.1 Scala, чтобы она использовала ту же самую версию, что и в командной строке, и она не имела никакого значения для времени выполнения.
Я также попытался запустить файл из командной строки со всеми параметрами -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% ответа, поэтому я дам его самому себе:
Я использую 64-разрядную версию Windows 7.
В командной строке используется среда 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)