Я рассматриваю разработку языка программирования, и мне бы хотелось, чтобы он запускался с такой же скоростью, как CPython или Perl. Чтобы сделать правильный выбор дизайна на моем языке для достижения этого требования, я смотрю на существующие динамические языки, чтобы увидеть, как их выбор дизайна влияет на время их запуска. У многих языковых реализаций на основе JVM или CLR намного больше времени запуска, чем CPython или Perl. Это говорит о том, что в дизайне JVM и/или CLR был сделан выбор дизайна, который вызывает это. Каким был этот выбор и почему так оно было сделано?
Это трехчастный вопрос:
- Является ли медленный запуск динамических реализаций языка JVM/CLR основной проблемой дизайна вообще или просто незначительной проблемой, которая может быть исправлена путем улучшения языковых реализаций?
- Если это проблема дизайна, то , которые выбирают дизайн JVM и какие варианты дизайна этих языков заставляют эти языки иметь более длительную задержку запуска, чем CPython и Perl?
- Что получается в обмен на медленное начало? То есть, какие преимущества имеют динамические языки JVM/CLR, которые не имеют CPython и Perl из-за выбора дизайна, описанного в (2)?
Обратите внимание, что другие вопросы SO уже касаются "Почему JVM медленно запускается?" и почему разные языки JVM работают медленно. Этот вопрос отличается от этого вопросом, потому что этот вопрос касается проектного компромисса; что получается в обмен на это длительное время запуска?
Другие вопросы SO задают вопрос о том, как пользователь может запускать различные языки JVM (и часто приходится иметь какой-то демон, который предварительно загружает JVM), но это не то, что я прошу здесь; Я спрашиваю, как вы разрабатываете язык (и/или виртуальную машину), который позволяет быстро запускать (без предварительной загрузки) и что вы теряете взамен этого.
Фоновые исследования
Скорость выполнения различных языков
Я тестировал CPython и Perl в неформальных тестах Hello World на моей машине GNU/Linux и обнаружил, что они начинаются менее чем за 0,05 секунды. В остальной части этого сообщения я буду говорить "быстро", чтобы означать "время запуска, которое не намного дольше, чем CPython или Perl", а "медленное" означает иначе.
Легко найти мнения о том, что сам JVM и/или Java не запускаются (3, 4, 5, 6), а также конкретные номера порядка 1 секунды или более (7, 27) и контрольных показателей (8). Однако два теста Hello World JVM начались всего за 0,04 секунды (в GNU/Linux) (9, 10).
Clojure было время запуска около 0,6-1 секунды (1, 2); это примерно в 20 раз медленнее, чем моя цель 0,05 секунды. ClojureCLR еще медленнее (1). Clojure Тесты времени запуска и обсуждения можно найти в сообщениях блога Clojure bootstrapping (Kariniemi), Почему Clojure slow (Trojer).
Один контролер времени запуска сказал, что Clojure и JRuby были "значительно медленнее, чем все остальное" (25); они также были проверены только на двух динамических языках, основанных на JVM. Другой (очень старый) тест показывает, что Jython также очень медленно запускается (26). Мы фокусируемся на динамических языках в этом вопросе, однако может быть уместным, что Scala также невероятно быстро (1). Существует схема JVM, называемая Kawa (23). Сообщалось, что время запуска Kawa около 0,4 (24), которое быстрее, чем Clojure, но все же порядка величины выше моей цели.
Каковы реализации, выполняемые при запуске?
Оба (1, 2) заключают, что Clojure проводит время загрузки классов загрузки и инициализирует пространство имен clojure.core. Ответ на вопрос SO "Clojure производительность запуска приложения", похоже, говорит о том, что различие между временем запуска Java и временем запуска Clojure связано с тем, что Java лениво загружает свои стандартная библиотека, тогда как Clojure загружает ее с нетерпением. Ответы на вопрос SO "Может ли какая-либо реализация Clojure запускаться быстро?" включить "это просто проблема с реализацией, которая может быть исправлена, а не фундаментальный выбор дизайна" (перефразировать) и "Одно из ограничений JVM заключается в том, что объекты должны быть скопированы при инициализации," вы не можете вставлять какие-либо составные константы в байтовом коде. Даже массивы. "").
В одном объяснении, почему некоторые JVM или Java-программы запускаются медленно, это ввод/вывод загрузки во многих файлах классов из стандартной библиотеки (11). Эта гипотеза подтверждается результатами тестов, которые показывают резкое улучшение времени запуска JVM для "теплых запусков", где, по-видимому, содержимое стандартных файлов классов библиотеки уже загружено в кэш операционной системы. Некоторые говорят, что большая часть времени запуска связана с чтением ввода-вывода в файлах классов, но не из-за огромного объема данных, а из-за субоптимальной организации этих данных на диске (15, 16).
JVM верификатор байтов, вероятно, не является существенным фактором времени запуска, потому что ускорение на 40% верификатора переводится только на 5% -ное ускорение большого времени запуска программы (14).
Какие варианты дизайна (не) приводят к медленному запуску?
В (22), Kariniemi приходит к выводу, что запуск Clojure по своей сути медленно начинается из-за выбора дизайна, включая динамические функции. Тем не менее, я сомневаюсь в этом, потому что CPython и Perl добиваются гораздо более быстрого запуска, сохраняя при этом динамизм.
Использование байт-кода не может быть причиной, потому что CPython также использует байт-код.
Поскольку ввод/вывод файлов классов загрузки, похоже, виноват, можно предположить, что основной выбор дизайна - предоставление большой стандартной библиотеки. Однако это не может быть причиной, потому что CPython также предоставляет большую стандартную библиотеку и не запускается медленно. Кроме того, хотя медленность Java находится под сомнением, стоит отметить, что Java должен загружать rt.jar при запуске, но Hello World быстро запускается на Java в соответствии с некоторыми критериями.