Scala perf: почему это приложение Scala в 30 раз медленнее, чем эквивалентное приложение Java? - PullRequest
14 голосов
/ 21 марта 2012

Я очень опытный разработчик C #, но мне нужно начать писать код, который работает на JVM.Язык Java по сравнению с C # в настоящее время плохо работает, поэтому меня интересовали функции, которые предлагает Scala.

Однако, услышав, что в Scala все операторы являются просто методами, я стал подозревать, что производительность может повлиять на сложные математические вычисления (что важно для типов приложений, которые пишет моя команда)

Итак, я запустил несколько простых тестов на основе int и обнаружил, что Scala примерно в 30 раз медленнее, чем эквивалентный код Java.Нехорошо!Может кто-нибудь сказать мне, что я делаю не так?или как улучшить вычислительную производительность примера scala, чтобы он соответствовал Java?

UPDATE1: как указывалось в первых двух ответах, я был супер-нубом и выполнял это в IntelliJ IDE.Я не знаю, как запустить приложение Scala через командную строку Java, что может быть проблемой IntelliJ.Спасибо за помощь, ребята, мне нужно исследовать простое выполнение scala из командной строки, прежде чем я продолжу тестирование perf, поскольку приведенные результаты IDE явно слишком неточны.

ОБНОВЛЕНИЕ2: Луиджи в комментариях говорит в IntelliJ, что онполучает равные времена, так что кажется, что моя дикая разница не из-за IntelliJ?Любые другие идеи о том, что это может быть?Я попробую запустить его через командную строку и выложу обновление с моими результатами.

ОБНОВЛЕНИЕ3: после запуска через командную строку я получаю такую ​​же 30-кратную разницу в производительности.
Мой компьютер - 3-ядерный AMD x64 3,4 ГГц, работает J2SE 6 jdk 64-битная 1.6.0_31, Window7.

Вот мои среды выполнения: Java: 210 мс.
Scala: между 2000 и 7400 мс (обычно диапазон 7000)

так что, я полагаю, вопрос все еще открыт.почему на моей платформе так медленно работает scala?что-то с 64-битной средой исполнения Java или с версиями Java 6?

:

C:\Users\jason>java -showversion
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b05)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode)

C:\Users\jason>scala
Welcome to Scala version 2.9.1-1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_31).

ОБНОВЛЕНИЕ 4, в то время как мой первоначальный тест имеет разницу в 30 раз, увеличение числа итераций до 100000000 приводит к разнице впримерно до 33%, так что кажется, что на scala все еще преобладает какая-то неизвестная стоимость инициализации на моей машине.Я закрою это ответом с самым высоким рейтингом, так как не думаю, что мы обнаружим проблему с производительностью, потому что никто, кроме меня, не видит проблему: (

* ОБНОВЛЕНИЕ 5, РЕШЕНИЕ: на основе справки из двух ответов, которые я получил, я выяснил проблему, см. мой ответ ниже для получения более подробной информации (краткое описание: первый вызов System.nanoTime () занимает много времени) *

Вот мои примеры приложений:

//scala
object HelloWorld {
  //extends Application {
  def main(args: Array[String]) {
    println("hello scala")
    var total: Long = 0
    var i: Long = 0
    var x: Long=0;
    //warm up of the JVM to avoid timing of runtime initialization
    while (i < 100000)
    {
      x=i;
      x += x - 1;
      x -= x + 1;
      x += 1;
      x -= 1;
      total += x;
      i+=1;
    }
    //reset variables
    total = 0
    i = 0;
    //start timing
    var start: Long = System.nanoTime

    //run test
    while (i < 100000) {
      x=i;
      x += x - 1;
      x -= x + 1;
      x += 1;
      x -= 1;

      total += x;
      i+=1;
    }
    var end: Long = System.nanoTime
    System.out.println("ms, checksum = ")
    System.out.println((end - start) / 1000)
    System.out.println(total)
  }
}

и вот эквивалент Java, в 30 раз быстрее

//java
public class app {
    public static void main(String[] args)
    {
        String message = "hello, java";
        System.out.println(message);
        long total = 0;
        //warm up of the JVM to avoid timing of runtime initialization
        for(long i=0;i< 100000;i++)
        {
            long x=i;
            x+=x-1;
            x-=x+1;
            x++;
            x--;
            total+=x;
        }
        //reset variables
        total = 0;
        //start timing and run test
        long start = System.nanoTime();
        for(long i=0;i< 100000;i++)
        {
            long x=i;
            x+=x-1;
            x-=x+1;
            x++;
            x--;
            total+=x;
        }
        long end = System.nanoTime();
        System.out.println("ms, checksum = ");
        System.out.println((end-start)/1000);
        System.out.println(total);
    }
}

Ответы [ 3 ]

17 голосов
/ 21 марта 2012

Так что, я думаю, что сам разобрался с ответом.

Проблема в звонке на System.nanoTime. Это требует затрат на инициализацию (загрузку базовых библиотек Java и т. Д.), Которые намного дешевле загружать при вызове из среды выполнения Java, чем из среды выполнения Scala.

Я докажу это, изменив начальное значение итога, вместо этого установив его на

var total: Long = System.nanoTime()

Это добавляется перед первым циклом "прогрева", и теперь это делает обе версии приложения (Java и Scala) запущенными одновременно: около 2100 для 1000000 итераций.

Спасибо за помощь ваших парней, я бы не понял этого без вашей помощи.

ps: я оставлю «принятый ответ» как есть, потому что я бы не выследил это без его помощи.

10 голосов
/ 21 марта 2012

Я перезапустил ваш код (и увеличил число циклов x1000, чтобы придать смысл тесту).

Результаты:

Scala: 92 ms
Java: 59 ms

Вы можете видеть, что Javaна 30% быстрее.

Глядя на байт-код, я могу сказать, что две версии почти идентичны - так что разница действительно странная (список байт-кода довольно длинный, поэтому я не буду размещать его здесь).

Увеличение счетчика x10000 дает следующее:

Scala: 884 ms
Java: 588 ms

Поскольку результаты довольно стабильны, где-то должен быть некоторый постоянный фактор.Может быть, по некоторым параметрам, которые "scala" запускает в JVM?

РЕДАКТИРОВАТЬ:

Моя конфигурация:

$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)

$ scala -version
Scala code runner version 2.9.0.1 -- Copyright 2002-2011, LAMP/EPFL

$ inxi -SCD
System:    Host the-big-maker Kernel 2.6.35-22-generic x86_64 (64 bit) Distro Linux Mint 10 Julia
CPU:       Quad core AMD Phenom II X4 965 (-MCP-) cache 2048 KB flags (lm nx sse sse2 sse3 sse4a svm) 
           Clock Speeds: (1) 800.00 MHz (2) 800.00 MHz (3) 800.00 MHz (4) 800.00 MHz
Disks:     HDD Total Size: 750.2GB (5.8% used) 1: /dev/sda OCZ 90.0GB 
           2: /dev/sdb ST3500413AS 500.1GB 3: /dev/sdc ST3802110A 80.0GB 
           4: /dev/sdd Maxtor_6Y080M0 80.0GB 
8 голосов
/ 21 марта 2012
$ javac app.java
$ scalac app.scala 
$ scala HelloWorld
hello scala
ms, checksum = 
1051
-100000
$ java app
hello, java
ms, checksum = 
1044
-100000

Что я делаю не так?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...