Скорость компиляции Java против скорости компиляции Scala

101

Некоторое время я программировал на Scala, и мне это нравится, но меня раздражает время, необходимое для компиляции программ. Это кажется мелочью, но с Java я мог бы внести небольшие изменения в свою программу, щелкнуть кнопку запуска в netbeans и BOOM, он работает, и со временем компиляция в scala, похоже, занимает много времени. Я слышал, что для многих крупных проектов язык сценариев становится очень важным из-за времени, необходимого для компиляции, - потребности, которую я не замечал, когда использовал Java.

Но я пришел с Java, которая, как я понимаю, быстрее, чем любой другой компилируемый язык, и работает быстро по причинам, по которым я перешел на Scala (это очень простой язык).

Поэтому я хотел спросить, могу ли я сделать компиляцию Scala быстрее и будет ли когда-либо масштабироваться так же быстро, как javac.

user405163
источник
Похоже, что некоторые пользователи согласны с вами;) twitter.com/etorreborre/status/21286172202
VonC
Go компилируется быстрее, чем Java. Намного быстрее, что о чем-то говорит.
Дэниел С. Собрал
Ахаха, в моем случае для средней скалярной компиляции с несколькими Houndreds LOC требуется несколько минут, fsc немного быстрее.
Jeriho

Ответы:

57

Компилятор Scala более сложен, чем компилятор Java, обеспечивая вывод типов, неявное преобразование и гораздо более мощную систему типов. Эти функции не предоставляются бесплатно, поэтому я не ожидал, что scalac когда-либо будет так же быстр, как javac. Это отражает компромисс между программистом, выполняющим работу, и компилятором, выполняющим работу.

Тем не менее, время компиляции уже заметно улучшилось при переходе от Scala 2.7 к Scala 2.8, и я ожидаю, что улучшения продолжатся сейчас, когда пыль осела на 2.8. На этой странице описаны некоторые из текущих усилий и идей по повышению производительности компилятора Scala.

Мартин Одерский дает гораздо более подробный ответ.

Аарон Новструп
источник
1
Разве еще не эта страница ( lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded )?
VonC
Я переключился с netbeans на ant + jedit (я знаю, что знаю, что ant для пещерных людей, но я буду развиваться в свое время), так что я могу использовать fsc. Но мне было интересно, как скорость компиляции Clojure по сравнению со Scala? Кажется, что у него есть много функций в Scala, но я думаю, что синтаксис намного проще анализировать.
user405163
1
Здесь мы как бы не по теме, но компилятор Clojure невероятно быстр (намного быстрее, чем javac для эквивалентных источников). Вы правы в том, что это действительно простой язык, и в нем нет какой-либо системы статических типов, что немного помогает.
Даниэль Спивак
458

Есть два аспекта (недостатка) скорости компилятора Scala.

  1. Увеличение накладных расходов на запуск

    • Сам Scalac состоит из МНОГО классов, которые нужно загрузить и jit-скомпилировать.

    • Scalac должен искать в пути к классам все корневые пакеты и файлы. В зависимости от размера вашего пути к классам это может занять от одной до трех дополнительных секунд.

    В целом, ожидаемые накладные расходы на запуск scalac составят 4-8 секунд, и больше, если вы запустите его в первый раз, так что кеши дисков не будут заполнены.

    Ответ Scala на накладные расходы при запуске - либо использовать fsc, либо выполнять непрерывную сборку с помощью sbt. IntelliJ необходимо настроить для использования любого из этих вариантов, иначе его накладные расходы даже для небольших файлов будут неоправданно большими.

  2. Более низкая скорость компиляции. Scalac обрабатывает от 500 до 1000 строк в секунду. Javac справляется примерно в 10 раз больше. На это есть несколько причин.

    • Вывод типа стоит дорого, особенно если он включает неявный поиск.

    • Scalac дважды выполняет проверку типов; один раз по правилам Scala и второй раз после стирания по правилам Java.

    • Помимо проверки типов, для перехода от Scala к Java требуется около 15 шагов преобразования, которые требуют времени.

    • Scala обычно генерирует намного больше классов для заданного размера файла, чем Java, в частности, если функциональные идиомы широко используются. Генерация байт-кода и написание класса требует времени.

    С другой стороны, программа Scala на 1000 строк может соответствовать программе Java на 2-3 КБ, поэтому некоторая более низкая скорость при подсчете строк в секунду должна уравновешиваться большей функциональностью на строку.

    Мы работаем над улучшением скорости (например, путем параллельной генерации файлов классов), но чудес в этом плане ожидать не приходится. Scalac никогда не будет таким быстрым, как javac. Я считаю, что решение будет заключаться в серверах компиляции, таких как fsc, в сочетании с хорошим анализом зависимостей, чтобы перекомпилировать только минимальный набор файлов. Мы тоже над этим работаем.

Мартин Одерский
источник
1
О накладных расходах при запуске из-за загрузки класса: поможет ли предварительная компиляция в собственный код с использованием GCJ или Mono?
Механическая улитка
15
Что, если бы Scala переписали на C ++? : o)
Marcus
Будет ли польза от использования инструкции invokedynamic байт-кода?
Роб Грант
40

Вы должны знать, что компиляция Scala занимает как минимум на порядок больше времени, чем компиляция Java. Причины этого следующие:

  1. Соглашения об именах (файл XY.scalaфайла не обязательно должен содержать вызываемый класс XYи может содержать несколько классов верхнего уровня). Поэтому компилятору может потребоваться поиск в дополнительных исходных файлах, чтобы найти данный идентификатор класса / признака / объекта.
  2. Имплициты - частое использование имплицитов означает, что компилятору необходимо искать любое неявное преобразование в области видимости для данного метода и ранжировать их, чтобы найти «правильный». ( т.е. компилятор имеет значительно увеличенную область поиска при поиске метода. )
  3. Система типов - система типов Scala намного сложнее, чем в Java, и, следовательно, требует больше процессорного времени.
  4. Вывод типа - вывод типа javacтребует больших вычислительных ресурсов и работы, которую не нужно делать вообще
  5. scalacвключает в себя 8-битный симулятор полностью вооруженной и работающей боевой станции, которую можно просмотреть с помощью волшебной комбинации клавиш CTRL-ALT-F12 на этапе компиляции GenICode .
Oxbow_lakes
источник
3
@obox_lakes, ненавижу придирки, но Java действительно должна делать вывод типа для параметризованных методов, int a<T>(T a) {}а затем a(pls_infer_my_type). james-iry.blogspot.com/2009/04/…
Элазар Лейбович
13
@Elazar - да, я знаю. Но откровенно смехотворно после scala называть это «выводом типа»!
oxbow_lakes
19

Лучший способ сделать Scala - использовать IDEA и SBT. Настройте элементарный проект SBT (что он сделает за вас, если хотите) и запустите его в режиме автоматической компиляции (команда ~compile), и когда вы сохраните проект, SBT перекомпилирует его.

Вы также можете использовать подключаемый модуль SBT для IDEA и прикрепить действие SBT к каждой из ваших конфигураций запуска. Плагин SBT также предоставляет интерактивную консоль SBT в IDEA.

В любом случае (внешний запуск SBT или подключаемый модуль SBT) SBT продолжает работать, и, таким образом, все классы, используемые при построении вашего проекта, «разогреваются» и JIT-редактируются, а накладные расходы при запуске устраняются. Кроме того, SBT компилирует только те исходные файлы, которые в этом нуждаются. На сегодняшний день это наиболее эффективный способ создания программ Scala.

Рэндалл Шульц
источник
9

Последние версии Scala-IDE (Eclipse) намного лучше справляются с управлением инкрементной компиляцией.

См. « Какая лучшая система сборки Scala? » Для получения дополнительной информации.


Другое решение - интегрировать fsc - быстрый автономный компилятор для языка Scala 2 - (как показано в этом сообщении в блоге ) в качестве конструктора в вашей среде IDE.

альтернативный текст

Но не непосредственно в Eclipse, как упоминает Дэниел Спивак в комментариях:

Вы не должны использовать FSC напрямую в Eclipse хотя бы потому, что Eclipse уже использует FSC под поверхностью.
FSC - это, по сути, тонкий слой поверх резидентного компилятора, который является именно тем механизмом, который Eclipse использует для компиляции проектов Scala.


Наконец, как Джексон Дэвис напоминает мне в комментариях:

sbt (Simple build Tool) также включает в себя своего рода «инкрементную» компиляцию (через запускаемое выполнение ), хотя она и не идеальна , а улучшенная инкрементная компиляция находится в разработке для предстоящей версии 0.9 sbt.

VonC
источник
2
sbt также может выполнять инкрементные компиляции
Джексон Дэвис,
@Jackson: триггерная казнь, верно! Я включил это в свой ответ.
VonC
2
Вы не должны использовать FSC напрямую в Eclipse хотя бы потому, что Eclipse уже использует FSC под поверхностью. FSC - это, по сути, тонкий слой поверх резидентного компилятора, который является именно тем механизмом, который Eclipse использует для компиляции проектов Scala.
Даниэль Спивак
1
FSC означает Fast Scala Compiler - не Fast Java Compiler
Бен Макканн
@BenMcCann: ой. Правильно. Я зафиксировал ответ.
VonC
6

Используйте fsc - это быстрый компилятор Scala, который работает как фоновая задача и не требует постоянной загрузки. Он может повторно использовать предыдущий экземпляр компилятора.

Я не уверен, поддерживает ли плагин Scala Netbeans fsc (об этом говорится в документации), но я не мог заставить его работать. Попробуйте ночные сборки плагина.

Денис Тульский
источник
1
Плагин IntelliJ IDEA Scala также может использовать fsc
Аарон Новструп,
1
@anovstrup: да, но иногда вылетает.
Денис Тульский
4

Вы можете использовать плагин JRebel, который бесплатен для Scala. Таким образом, вы можете как бы «разработать в отладчике», и JRebel всегда будет перезагружать измененный класс на месте.

Я где-то читал заявление самого Мартина Одерски, в котором он говорит, что поиск имплицитов (компилятор должен убедиться, что существует не более одного неявного неявного преобразования для одного и того же преобразования, чтобы исключить двусмысленность) может занять компилятор. Так что, возможно, стоит осторожно обращаться с неявными последствиями.

Если это не обязательно должна быть 100% Scala, но есть что-то подобное, вы можете попробовать Kotlin .

- Оливер

OlliP
источник
2

Я уверен, что это будет отвергнуто, но чрезвычайно быстрая отдача не всегда способствует повышению качества или производительности.

Найдите время, чтобы подумать более тщательно и выполнить меньше микроциклов разработки. Хороший код Scala плотнее и важнее (т. Е. Лишен случайных деталей и сложности). Это требует больше размышлений и времени (по крайней мере, сначала). Вы можете успешно развиваться с меньшим количеством циклов кода / тестирования / отладки, которые по отдельности немного длиннее, но при этом повышают вашу продуктивность и качество вашей работы.

Вкратце: ищите оптимальную схему работы, лучше подходящую для Scala.

Рэндалл Шульц
источник
3
Я согласен с тем, что не обязательно иметь быстрый цикл восстановления. Но ведь это же не больно?
Элазар Лейбович
27
Я не собираюсь голосовать против, но говорю, что вам следует скорректировать свой рабочий шаблон в соответствии с ограничениями вашего инструмента (низкая скорость компилятора), а не пытаться улучшить инструмент, не является хорошим аргументом. Особенно очень ценна возможность выполнять быстрые циклы тестирования (хотя она не отменяет необходимости глубоко размышлять, что, вероятно, лучше всего делать вдали от клавиатуры, она прекрасно ее дополняет).
Тило
9
Я думаю, что большая часть моей продуктивности на самом деле потеряна из-за чрезмерного обдумывания перед бегом. Я часто замечаю, что долго смотрю на какое-то уравнение, пытаясь определить, какая потенциальная ловушка поджидает меня, и все это время я думаю: «Просто запустите!» в затылке. И, конечно же, когда я запускаю программу, я узнаю намного больше, чем я, вероятно, узнал бы еще через час или два медитации. Медитация - это хорошо, но я считаю, что очень оптимально использовал инкрементную компиляцию / медитацию с помощью java.
user405163
2
Это также похоже на предложение Шекспиру не использовать проверку орфографии, а вместо этого больше думать о том, что он хочет сказать. Автоматическая проверка орфографии помогает с совершенно другим набором проблем.
Тило