Ответ 1
Современные интерпретируемые языки обычно компилируют код для некоторого представления для более быстрого выполнения... он не может быть записан на диск, но, конечно же, нет гарантии, что программа представлена в более компактной форме. Некоторые переводчики отправляются на все свиньи и генерируют машинный код в любом случае (например, Java JIT). Тогда там сам интерпретатор сидит в памяти, которая может быть большой.
Несколько точек:
- Чем сложнее команды в исходном коде, тем больше операций машинного кода может потребоваться для их выполнения. Таким образом, языковые функции более высокого уровня имеют более высокий коэффициент скомпилированного кода и исходного кода. Это не обязательно плохо: подумайте об этом как о "Мне нужно лишь немного рассказать о том, что я хочу сделать, и он раскрывает все эти необходимые шаги". Задача в программировании - обеспечить их необходимость - для этого требуется хорошая библиотека и дизайн программы.
- Компилятор часто преднамеренно решает обменять некоторый размер исполняемого файла для более быстрой ожидаемой скорости выполнения: встроенный и внекорректный код является частью этого компромисса, хотя для небольших функций они не могут быть последовательно более компактными.
- Более сложные среды выполнения (например, добавление поддержки исключений С++) могут включать в себя немного дополнительного кода, который запускается, когда программа сначала начинает создавать необходимую среду для этой языковой функции.
- Функция библиотек может быть несовместимой. Помимо типа дополнительных библиотек, которые вы, скорее всего, должны были отследить себя и быть в курсе использования (например, XML, разбора PDF файлов, OpenGL), языки часто спокойно используют вспомогательные библиотеки для того, что похоже на языковые функции и функций. Любое из них может быть удивительно большим.
- Например, многие интерпретаторы просто выставляют оператор C-библиотеки
printf()
или что-то подобное, в то время как для форматирования вывода С++ имеетostream
- более сложную, расширяемую и безопасную по типу систему с (для лучшего или худшего) постоянным состоянием через вызовы функций, процедуры для запроса и установки этого состояния, дополнительный уровень настраиваемой буферизации, настраиваемые типы символов и локализацию и, как правило, множество небольших встроенных функций, которые могут привести к меньшим или большим программам в зависимости от точных настроек использования и компилятора. Что лучше всего зависит от ваших целей приложения и памяти и производительности.
- Например, многие интерпретаторы просто выставляют оператор C-библиотеки
- Операторы встроенного языка могут быть скомпилированы по-разному: a
switch
в целочисленном выражении и 100 случайных меток распределены случайным образом между 1 и 1000: один компилятор/языки могут решить "упаковать" 100 случаев и выполнить двоичный поиск для совпадение, другое - использовать малонаселенный массив из 1000 элементов и делать прямую индексацию (что тратит пространство в исполняемом файле, но обычно делает для более быстрого кода). Поэтому трудно сделать выводы на основе размера исполняемого файла.
Как правило, использование памяти и скорость выполнения становятся все более важными, поскольку программа становится все более сложной и сложной. Вы не видите такие системы, как операционные системы, корпоративные веб-серверы или полнофункциональные коммерческие текстовые процессоры, написанные на интерпретируемых языках, потому что они не имеют масштабируемости.