Почему любая программа Java/Clojure замедляется при запуске из Лейнингена?

При тестировании приложения Clojure и попытке определить проблемы с производительностью я заметил это странное поведение: даже когда вся программа написана на Java, при запуске из Лейнингена она, кажется, испытывает значительное замедление.

Скажем, у меня есть эта программа Java:

public class Foo {
    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10; i++)
             run();
    }

    public static void run() {
        final long start = System.nanoTime();

        Random r = new Random();
        double x = 0;
        for(int i=0; i<50000000; i++)
            x += r.nextDouble();

        final long time = TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS);
        System.out.println("time (ms): " + time + " total: " + x);
    }
}

Когда я просто запускаю программу, я получаю время выполнения (на run) около 1 с. Однако, когда я запускаю его из лейнингена, вот так:

lein run -m Foo

Я получаю время работы около 2 с! Как Clojure/Leiningen удается так сильно замедлять полную Java-программу? Что я делаю неправильно?

Я пытался изучить свойства системы в обоих прогонах и не нашел ничего особенного (например, разные настройки JIT). В обоих случаях я использую Java 7 с серверным компилятором.

РЕДАКТИРОВАТЬ: я не знаю, почему этот вопрос был отклонен. Я не против Clojure. Наоборот, я люблю Clojure и собираюсь его использовать. У меня просто есть серьезная проблема с производительностью, которую я обязательно должен решить.

ОБНОВЛЕНИЕ: Запуск lein trampoline решает проблему! (хотя я понятия не имею, почему) я обновил вопрос, чтобы отразить, что это действительно проблема Leiningen, а не проблема Clojure.

Еще одно обновление: это происходит и с любым кодом Clojure. Бег без батута замедляет код до 5 раз.


person pron    schedule 18.04.2013    source источник
comment
Совет: lein help trampoline   -  person noahlz    schedule 28.04.2013


Ответы (3)


Создатели leiningen знают об этом и дают обстоятельное объяснение, почему это так и что с этим можно сделать.

https://github.com/technomancy/leiningen/wiki/Faster

Связанный вопрос: Почему leiningen настолько медленный, когда он начинается?

person tixel    schedule 17.03.2015

Вероятно, это связано с другим поведением JIT.

На производительность скомпилированного JIT может повлиять ряд факторов, в том числе:

  • Какой код запуска вызывается, что повлияет на статистику JIT
  • Какие другие классы были загружены (например, другие подклассы Random), которые могут повлиять на оптимизацию компилятором диспетчеризации вызовов методов
person mikera    schedule 18.04.2013
comment
Я пробовал оба с -XX:+PrintCompilation. В обоих случаях run() компилируется (единственная интересная функция здесь). Впрочем, смотрите обновление. Так или иначе, это leiningen вызывает это. - person pron; 18.04.2013

leiningen занимает около секунды, чтобы начать.

person Joost Diepenmaat    schedule 18.04.2013
comment
Очевидно, я не считаю время запуска лейна. Посмотрите на программу. Я смотрю на тайминги в методе запуска. - person pron; 18.04.2013
comment
Ты прав. Я предполагаю, что там происходит что-то странное. Вы уверены, что у вас есть то же самое в пути к классам? - person Joost Diepenmaat; 18.04.2013
comment
Кроме того: у вас могут быть разные ограничения памяти, поэтому программе, запущенной lein, возможно, придется выполнять больше сбора мусора. Проблему трудно диагностировать без точных настроек/свойств системы. - person Joost Diepenmaat; 18.04.2013
comment
Мусор вообще не собирается во время работы программы (проверено с помощью -verbose:gc). Чтобы собрать мусор, его нужно сначала создать, и я не думаю, что Clojure/lein может каким-то образом заставить алгоритм производить больше мусора. - person pron; 18.04.2013