Скорость компиляции Java против скорости компиляции Scala
Я давно программирую на Scala, и мне это нравится, но меня раздражает одна вещь - время, необходимое для компиляции программ. Это кажется мелочью, но с Java я мог бы внести небольшие изменения в свою программу, щелкнуть кнопку запуска в NetBeans, и BOOM, он работает, и со временем компиляция в Scala, похоже, отнимает много времени. Я слышал, что во многих крупных проектах язык сценариев становится очень важным из-за того, что на компиляцию уходит много времени, что не возникало, когда я использовал Java.
Но я пришел из Java, которая, насколько я понимаю, быстрее, чем любой другой скомпилированный язык, и работает быстро по причинам, по которым я переключился на Scala (это очень простой язык).
Поэтому я хотел спросить, могу ли я сделать компиляцию Scala быстрее и будет ли Scala c такой же быстрой, как Javac.
8 ответов
Компилятор Scala более сложен, чем Java, обеспечивая вывод типов, неявное преобразование и гораздо более мощную систему типов. Эти функции не предоставляются бесплатно, поэтому я бы не ожидал, что Scalac будет настолько же быстрым, как Javac. Это отражает компромисс между программистом, выполняющим работу, и компилятором, выполняющим работу.
Тем не менее, время компиляции уже заметно улучшилось с Scala 2.7 до Scala 2.8, и я ожидаю, что улучшения продолжатся и сейчас, когда пыль осела на 2.8. На этой странице описаны некоторые текущие усилия и идеи по улучшению производительности компилятора Scala.
Мартин Одерский приводит гораздо больше деталей в своем ответе.
У компилятора Scala (отсутствие) скорости есть два аспекта.
Большие затраты на запуск
Сам Scala c состоит из множества классов, которые должны быть загружены и скомпилированы
Scala c должен найти путь к классам для всех корневых пакетов и файлов. В зависимости от размера вашего classpath это может занять от одной до трех дополнительных секунд.
В целом ожидайте, что издержки запуска скаляка будут 4-8 секунд, дольше, если вы запустите его в первый раз, чтобы дисковые кеши не были заполнены.
Ответ Scala на издержки запуска - либо использовать fsc, либо создавать непрерывные сборки с помощью sbt. IntelliJ должен быть настроен на использование любого из этих вариантов, в противном случае его издержки даже для небольших файлов неоправданно велики.
Более медленная скорость компиляции. Скалак обрабатывает от 500 до 1000 строк / сек. Javac справляется примерно в 10 раз. На это есть несколько причин.
Вывод типа является дорогостоящим, особенно если он включает в себя неявный поиск.
Скалак должен сделать проверку типов дважды; один раз в соответствии с правилами Scala и второй раз после стирания в соответствии с правилами Java.
Помимо проверки типов, существует около 15 шагов преобразования из Scala в Java, которые все требуют времени.
Scala обычно генерирует намного больше классов для каждого размера файла, чем Java, особенно если интенсивно используются функциональные идиомы. Генерация байт-кода и запись класса требует времени.
С другой стороны, 1000-строчная Scala-программа может соответствовать Java-программе на 2-3 Кбайта, поэтому некоторая медленная скорость при подсчете в строках в секунду должна быть сбалансирована с большей функциональностью на строку.
Мы работаем над улучшением скорости (например, параллельно генерируя файлы классов), но на этом фронте нельзя ожидать чудес. Скалак никогда не будет так же быстр, как Джавак. Я считаю, что решение будет лежать на серверах компиляции, таких как fsc, в сочетании с хорошим анализом зависимостей, так что нужно будет перекомпилировать только минимальный набор файлов. Мы тоже над этим работаем.
Вы должны знать, что компиляция Scala занимает как минимум на порядок больше, чем Java. Причины этого следующие:
- Соглашения об именах (файл
XY.scala
файл не должен содержать класс с именемXY
и может содержать несколько классов верхнего уровня). Поэтому компилятору, возможно, придется искать больше исходных файлов, чтобы найти заданный идентификатор класса / признака / объекта. - Имплициты - интенсивное использование имплицитов означает, что компилятору нужно искать любое неявное неконвертируемое преобразование для данного метода и ранжировать их, чтобы найти "правильный". (т.е. при поиске метода у компилятора значительно увеличивается область поиска.)
- Система типов - система типов scala намного сложнее, чем Java, и, следовательно, занимает больше процессорного времени.
- Вывод типа - вывод типа является вычислительно дорогим и работа, которая
javac
не нужно делать вообще scalac
включает в себя 8-битный симулятор полностью вооруженной и оперативной боевой станции, которую можно просмотреть с помощью комбинации магических клавиш CTRL-ALT-F12 на этапе компиляции GenICode.
Лучший способ сделать Scala - это IDEA и SBT. Настройте элементарный проект SBT (который он сделает для вас, если хотите) и запустите его в режиме автоматической компиляции (команда ~compile
) и когда вы сохраните свой проект, SBT перекомпилирует его.
Вы также можете использовать плагин SBT для IDEA и прикрепить действие SBT к каждой из ваших конфигураций запуска. Плагин SBT также предоставляет интерактивную консоль SBT в IDEA.
В любом случае (SBT работает извне или подключаемый модуль SBT), SBT продолжает работать, и, таким образом, все классы, используемые при создании вашего проекта, "разогреваются" и подвергаются JIT-обработке, а накладные расходы на запуск устраняются. Кроме того, SBT компилирует только те исходные файлы, которые в этом нуждаются. На сегодняшний день это самый эффективный способ создания программ Scala.
Последние версии Scala-IDE (Eclipse) намного лучше справляются с инкрементальной компиляцией.
Смотрите " Какая самая лучшая система сборки Scala? ", Чтобы узнать больше.
Другое решение заключается в интеграции fsc - быстрого автономного компилятора для языка Scala 2 - (как показано в этом сообщении в блоге) в качестве компоновщика в вашей среде IDE.
Но не в "Затмении", как упоминает Daniel Spiewak в комментариях:
Вы не должны использовать FSC в Eclipse напрямую, хотя бы потому, что Eclipse уже использует FSC под поверхностью.
FSC представляет собой тонкий слой поверх резидентного компилятора, который является именно тем механизмом, который используется Eclipse для компиляции проектов Scala.
Наконец, как Jackson Davis напоминает мне в комментариях:
sbt (Simple build Tool) также включает в себя некоторую "инкрементную" компиляцию (с помощью запуска по триггеру), хотя она и не идеальна, а улучшенная инкрементная компиляция работает для будущей версии 0.9 sbt.
Используйте fsc - это быстрый компилятор scala, который используется в качестве фоновой задачи и не требует постоянной загрузки. Он может повторно использовать предыдущий экземпляр компилятора.
Я не уверен, что плагин Netbeans Scala поддерживает fsc (так написано в документации), но я не смог заставить его работать. Попробуйте ночные сборки плагина.
Вы можете использовать плагин JRebel, который бесплатен для Scala. Таким образом, вы можете "развиваться в отладчике", и JRebel всегда перезагрузит измененный класс на месте.
Я где-то читал какое-то утверждение самого Мартина Одерского, где он говорит, что поиск имплицитов (компилятор должен убедиться, что для одного и того же преобразования не более одного неявного преобразования, чтобы исключить неоднозначности) может удерживать компилятор занятым. Так что это может быть хорошей идеей, чтобы обрабатывать последствия с осторожностью.
Если это не обязательно 100% Scala, но и нечто подобное, вы можете попробовать Kotlin.
- Оливер
Я уверен, что за это проголосуют, но чрезвычайно быстрый оборот не всегда способствует качеству или производительности.
Потратьте время, чтобы подумать более тщательно и выполнить меньше микро-циклов разработки. Хороший код Scala является более плотным и более важным (то есть свободным от случайных деталей и сложности). Это требует больше размышлений, и это требует времени (по крайней мере, на первый взгляд). Вы можете прогрессировать с меньшим количеством циклов кода / тестирования / отладки, которые по отдельности немного длиннее и все же улучшают вашу производительность и качество вашей работы.
Вкратце: ищите оптимальный рабочий режим, лучше подходящий для Scala.