компиляция и интерпретация программного кода достоинства и недостатки
Что такое компиляция в программировании?
Компилируется ли язык программирования или интерпретируется, на самом деле это не зависит от природы языка программирования. Любой язык программирования может интерпретироваться так называемым интерпретатором или компилироваться с помощью так называемого компилятора.
Рабочий цикл программы
При использовании любого языка программирования существует определенный рабочий цикл создания кода. Вы пишете его, запускаете, находите ошибки и отлаживаете. Таким образом, вы переписываете и дописываете программу, проверяете ее. То, о чем пойдет речь в этой статье, это « запускаемая » часть программы.
Когда пишете программу, вы хотите, чтобы ее инструкции работали на компьютере. Компьютер обрабатывает информацию с помощью процессора, который поэтапно выполняет инструкции, закодированные в двоичном формате. Как из выражения « a = 3; » получить закодированные инструкции, которые процессор может понять?
Мы делаем это с помощью компиляции. Существует специальные приложения, известные как компиляторы. Они принимают программу, которую вы написали. Затем анализируют и разбирают каждую часть программы и строят машинный код для процессора. Часто его также называют объектным кодом.
На одном из этапов процесса обработки задействуется компоновщик, принимающий части программы, которые отдельно были преобразованы в объектный код, и связывает их в один исполняемый файл. Вот схема, описывающая данный процесс:
Конечным элементом этого процесса является исполняемый файл. Когда вы запускаете или сообщаете компьютеру, что это исполняемый файл, он берет первую же инструкцию из него, не фильтрует, не преобразует, а сразу запускает программу и выполняет ее без какого-либо дополнительного преобразования. Это ключевая характеристика процесса компиляции — его результат должен быть исполняемым файлом, не требующим дополнительного перевода, чтобы процессор мог начать выполнять первую инструкцию и все следующие за ней.
Первые компиляторы были написаны непосредственно через машинный код или с использованием ассемблеров. Но цель компилятора очевидна: перевести программу в исполняемый машинный код для конкретного процессора.
Не все языки программирования учитывают это в своей концепции. Например, Java предназначался для запуска в « интерпретирующей » среде, а Python всегда должен интерпретироваться.
Интерпретация программы
Альтернативой компиляции является интерпретация. Чем отличаются компиляторы и интерпретаторы? Основная разница между компилятором и интерпретатором заключается в том, как они работают. Компилятор берет всю программу и преобразует ее в машинный код, который понимает процессор.
Интерпретатор — это исполняемый файл, который поэтапно читает программу, а затем обрабатывает, сразу выполняя ее инструкции.
Другими словами, программа-интерпретатор выполняет программу поэтапно как часть собственного исполняемого файла. Объектный код не передается процессору, интерпретатор сам является объектным кодом, построенным таким образом, чтобы его можно было вызвать в определенное время.
Это ломает рабочий цикл, который был приведен на диаграмме выше. Теперь у нас есть новая диаграмма:
На ней мы видим, что в отличии от компилятора, интерпретатор всегда должен быть под рукой, чтобы мы могли вызвать его и запустить нашу программу. В некотором смысле интерпретатор становится процессором. Программы, написанные для интерпретации, называются « скриптами », потому что они являются сценариями действий для другой программы, а не прямым машинным кодом.
Природа интерпретатора
Интерпретаторы могут создаваться по-разному. Существуют интерпретаторы, которые читают исходную программу и не выполняют дополнительной обработки. Они просто берут определенное количество строк кода за раз и выполняют его.
Некоторые интерпретаторы выполняют собственную компиляцию, но обычно преобразуют программу байтовый код, который имеет смысл только для интерпретатора. Это своего рода псевдо машинный язык, который понимает только интерпретатор.
Такой код быстрее обрабатывается, и его проще написать для исполнителя ( части интерпретатора, которая исполняет ), который считывает байтовый код, а не код источника.
Есть интерпретаторы, для которых этот вид байтового кода имеет более важное значение. Например, язык программирования Java « запускается » на так называемой виртуальной машине. Она является исполняемым кодом или частью программы, которая считывает конкретный байтовый код и эмулирует работу процессора. Обрабатывая байтовый код так, как если бы процессор компьютера был виртуальным процессором.
За и против
Основным аргументом за использование процесса компиляции является скорость. Возможность компилировать любой программный код в машинный, который может понять процессор ПК, исключает использование промежуточного кода. Можно запускать программы без дополнительных шагов, тем самым увеличивая скорость обработки кода.
Но наибольшим недостатком компиляции является специфичность. Когда компилируете программу для работы на конкретном процессоре, вы создаете объектный код, который будет работать только на этом процессоре. Если хотите, чтобы программа запускалась на другой машине, вам придется перекомпилировать программу под этот процессор. А перекомпиляция может быть довольно сложной, если процессор имеет ограничения или особенности, не присущие первому. А также может вызывать ошибки компиляции.
Основное преимущество интерпретации — гибкость. Можно не только запускать интерпретируемую программу на любом процессоре или платформе, для которых интерпретатор был скомпилирован. Написанный интерпретатор может предложить дополнительную гибкость. В определенном смысле интерпретаторы проще понять и написать, чем компиляторы.
С помощью интерпретатора проще добавить дополнительные функции, реализовать такие элементы, как сборщики мусора, а не расширять язык.
Другим преимуществом интерпретаторов является то, что их проще переписать или перекомпилировать для новых платформ.
Написание компилятора для процессора требует добавления множества функций, или полной переработки. Но как только компилятор написан, можно скомпилировать кучу интерпретаторов и на выходе мы имеем перспективный язык. Не нужно повторно внедрять интерпретатор на базовом уровне для другого процессора.
Самым большим недостатком интерпретаторов является скорость. Для каждой программы выполняется так много переводов, фильтраций, что это приводит к замедлению работы и мешает выполнению программного кода.
Это проблема для конкретных real-time приложений, таких как игры с высоким разрешением и симуляцией. Некоторые интерпретаторы содержат компоненты, которые называются just-in-time компиляторами ( JIT ). Они компилируют программу непосредственно перед ее исполнением. Это специальные программы, вынесенные за рамки интерпретатора. Но поскольку процессоры становятся все более мощными, данная проблема становится менее актуальной.
Заключение
Для меня не имеет значения, скомпилировано что-то или интерпретировано, если оно может выполнить задачу эффективно.
Сообщите мне, что бы вы предпочли: интерпретацию или компиляцию? Спасибо за уделенное время!
Пожалуйста, оставьте ваши комментарии по текущей теме статьи. Мы крайне благодарны вам за ваши комментарии, дизлайки, подписки, отклики, лайки!
My JAVA
пятница, 3 августа 2012 г.
Компиляция/Интерпретация
Компиляция
Компиляция — трансляция программы, написанной на языке высокого уровня, в эквивалентную программу на языке низкого уровня, близком к машинному коду.
Компилятор только преобразует исходный код в машинный. Исполняет программу (уже преобразованную компилятором) центральный процессор (т.е. ОС).
EX — Ada, Basic, C, Fortran (прим., разделение условно, практически для любого языка может быть создан и компилятор, и интерпретатор)
Интерпретация
Интерпретация — пооператорный анализ, обработка и исполнение программы или запроса.
Некоторые языки, например, Java и C#, находятся между компилируемыми и интерпретируемыми. А именно, программа компилируется не в машинный язык, а в машинно-независимый код низкого уровня, байт-код. Далее байт-код выполняется виртуальной машиной.
Для выполнения байт-кода обычно используется интерпретация, хотя отдельные его части для ускорения работы программы могут быть транслированы в машинный код непосредственно во время выполнения программы по технологии компиляции «на лету» (Just-in-time compilation, JIT). Для Java байт-код исполняется виртуальной машиной Java (Java Virtual Machine, JVM), для C# — Common Language Runtime.
Подобный подход в некотором смысле позволяет использовать плюсы как интерпретаторов, так и компиляторов.
Компиляция и интерпретация
Вы будете перенаправлены на Автор24
Компиляция и интерпретация — это переформирование программы, которая выполнена на каком-либо программном языке, в машинные исполняемые коды, и проработка программы по одной команде без предварительного компилирования.
Главной характеристикой, например, языка программирования РНР, считается его интерпретируемость. Вместе с тем, программные языки, аналогичные Си, проектировались специально как компилируемые. Здесь следует заметить, что фактически сами языки программирования не определяют компиляция им требуется или интерпретация. Практически все программные языки могут подвергаться интерпретации или компиляции посредством соответствующих программ.
Компиляция программы
В любом языке программирования есть некоторые рабочие процедуры формирования кода. Программист пишет программу, запускает её, ищет ошибки и устраняет их, то есть выполняет отладку программы, исправляя и добавляя некоторые коды. Это и есть исполняемая программная часть. Цель программиста, составить так программу, чтобы все её операции успешно исполнялись компьютером.
Компьютер выполняет обработку команд исполняемой программы при помощи процессора, поочерёдно выполняющем процедуры, представленные в двоичных кодах. То есть необходимо сначала преобразовать, к примеру, выражение «Х=5», в кодовые последовательности, понятные процессору. Эту задачу выполняет процесс компиляции при помощи специальных программных приложений, именуемых компиляторами. Компилятор получает, написанную программистом на выбранном им языке, программу, выполняет её подробный анализ и разборку всех участков программы. И затем уже, на основании анализа, формирует программу в машинных кодах процессора.
Часто такую сформированную программу именуют «объектный код».
На каком-то шаге компиляции в работу подключается компоновщик, который принимает уже преобразованные ранее в машинные коды участки программы, и собирает их в единый файл, подлежащий в дальнейшем исполнению, то есть это и будет исполняемый файл. Когда программист запускает этот файл на компьютере, процессор выбирает из него начальную инструкцию и теперь просто её исполняет без всяких добавочных преобразований. Это и есть основное свойство операции компиляции, то есть её итогом является выдача исполняемого файла, который не требует больше никаких дополнительных действий и преобразований. Процессор понимает его коды, принимает их, и поочерёдно исполняет заложенные в них инструкции.
Готовые работы на аналогичную тему
Первые программы компиляции писались прямо в машинных кодах или на языке ассемблера. Но цель была именно такая, преобразовать прикладную программу в набор исполняемых машинных кодов, понятных конкретному процессору. Отдельные программные языки изначально проектировались под дальнейшую процедуру компиляции. Язык Си, к примеру, был спроектирован для предоставления возможности программисту легко осуществлять задуманные операции. Но при этом проектировщики языка Си предусмотрели облегчение перевода программного приложения в машинные коды. Следует заметить, что далеко не все программные языки закладывают такой подход в свою базу. К примеру, Python подлежит только интерпретации, а язык Java был предназначен для использования в среде интерпретации.
Интерпретация программы
Альтернативным компиляции, считается метод интерпретации. Главное отличие между компиляцией и интерпретацией заложено в принципе их работы. При компиляции загружается всё программное приложение, и оно проходит процедуру преобразования в машинные коды, понятные процессору. Программа интерпретации является исполняемым файлом, который последовательно считывает символику команд программного приложения и немедленно осуществляет исполнение, зашифрованных в них инструкций. То есть, фактически, интерпретатор исполняет программу, разработанную программистом, как участок своего исполняемого файла. Машинные коды не пересылаются процессору, поскольку программа интерпретации сама уже написана в машинных кодах и построена так, что её возможно вызывать в нужное время. Если компилятор одноразово преобразует программу и на этом его функции заканчиваются, то интерпретатор работает при каждом запуске программного приложения.
Основные принципы программирования: компилируемые и интерпретируемые языки
Основные принципы программирования: компилируемые и интерпретируемые языки
Как и в предыдущей статье этого цикла, я хочу обратить ваше внимание на ключевые принципы программирования, которые влияют на всё то, что мы делаем, но с которыми мы редко сталкиваемся напрямую и поэтому не до конца их понимаем. Тема сегодняшней статьи — компилируемые и интерпретируемые языки.
Будучи разработчиками, мы часто сталкиваемся с такими понятиями, как компилятор и интерпретатор, но я считаю, что многие не совсем понимают, что они означают. Между тем, компиляция и интерпретация — это основы работы всех языков программирования. Давайте взглянем на то, как на самом деле устроены эти понятия.
Вступление
Мы полагаемся на такие инструменты, как компиляция и интерпретация, чтобы преобразовать наш код в форму, понятную компьютеру. Код может быть исполнен нативно, в операционной системе после конвертации в машинный (путём компиляции) или же исполняться построчно другой программой, которая делает это вместо ОС (интерпретатор).
Компилируемый язык — это такой язык, что программа, будучи скомпилированной, содержит инструкции целевой машины; этот машинный код непонятен людям. Интерпретируемый же язык — это такой, в котором инструкции не исполняются целевой машиной, а считываются и исполняются другой программой (которая обычно написана на языке целевой машины). Как у компиляции, так и у интерпретации есть свои плюсы и минусы, и именно это мы и обсудим.
Прежде чем мы продолжим, стоит отметить, что многие языки программирования имеют как компилируемую, так и интерпретируемую версии, поэтому классифицировать их затруднительно. Тем не менее, чтобы не усложнять, в дальнейшем я буду разделять компилируемые и интерпретируемые языки.
Компилируемые языки
Главное преимущество компилируемых языков — это скорость исполнения. Поскольку они конвертируются в машинный код, они работают гораздо быстрее и эффективнее, нежели интерпретируемые, особенно если учесть сложность утверждений некоторых современных скриптовых интерпретируемых языков.
Низкоуровневые языки как правило являются компилируемыми, поскольку эффективность обычно ставится выше кроссплатформенности. Кроме того, компилируемые языки дают разработчику гораздо больше возможностей в плане контроля аппаратного обеспечения, например, управления памятью и использованием процессора. Примерами компилируемых языков являются C, C++, Erlang, Haskell и более современные языки, такие как Rust и Go.
Проблемы компилируемых языков, в общем-то, очевидны. Для запуска программы, написаной на компилируемом языке, её сперва нужно скомпилировать. Это не только лишний шаг, но и значительное усложнение отладки, ведь для тестирования любого изменения программу нужно компилировать заново. Кроме того, компилируемые языки являются платформо-зависимыми, поскольку машинный код зависит от машины, на которой компилируется и исполняется программа.
Интерпретируемые языки
В отличие от компилируемых языков, интерпретируемым для исполнения программы не нужен машинный код; вместо этого программу построчно исполнят интерпретаторы. Раньше процесс интерпретации занимал очень много времени, но с приходом таких технологий, как JIT-компиляция, разрыв между компилируемыми и интерпретируемыми языками сокращается. Примерами интерпретируемых языков являются PHP, Perl, Ruby и Python. Вот некоторые из концептов, которые стали проще благодаря интерпретируемым языкам:
Основным недостатком интерпретируемых языком является их невысокая скорость исполнения. Тем не менее, JIT-компиляция позволяет ускорить процесс благодаря переводу часто используемых последовательностей инструкции в машинный код.
Бонус: байткод-языки
В байткод-языке сперва происходит компиляция программы из человекочитаемого языка в байткод. Байткод — это набор инструкций, созданный для эффективного исполнения интерпретатором и состоящий из компактных числовых кодов, констант и ссылок на память. С этого момента байткод передаётся в виртуальную машину, которая затем интерпретирует код также, как и обычный интерпретатор.
При компиляции кода в байткод происходит задержка, но дальнейшая скорость исполнения значительно возрастает в силу оптимизации байткода. Кроме того, байткод-языки являются платформо-независимыми, превосходя при этом по скорости интерпретируемые. Для них также доступна JIT-компиляция.
Заключение
Многие языки в наши дни имеют как компилируемые, так и интерпретируемые реализации, сводя разницу между ними на нет. У каждого вида исполнения кода есть преимущества и недостатки.
Вкратце, компилируемые языки являются самыми эффективными, поскольку они исполняются как машинный код и позволяют использовать аппаратное обеспечение системы. Однако это вводит дополнительные ограничение на написание кода и делает его платформо-зависимым. Интерпретируемые же языки не зависят от платформы и позволяют использовать такие техники динамического программирования, как метапрограммирование. Тем не менее, в скорости исполнения они значительно уступают компилируемым языкам.
Байткод-языки, в свою очередь, пытаются использовать сильные стороны обоих видов языков, и у них это неплохо получается.
Языки программирования
3.2. Компиляция против интерпретации
Базисные схемы
Вместо компиляции программы можно ее интерпретировать. Рисунок ниже иллюстрирует разницу подходов, игнорируя роль входных данных.
И компилятор, и интерпретатор являются программами, на вход которых подаются программы, написанные на языке программирования. Компилятор транслирует переданную ему программу в целевую форму – машинный код, который уже может быть непосредственно выполнен на компьютере, создавая выходные результаты вычислений. Обработка той же исходной программы интерпретатором не создает целевой программы, но непосредственно выполняет ее, получая выходные результаты.
Компилятор будет генерировать машинный код, создающий тот же эффект, используя команды компьютера и адреса памяти (а не структуру более высокого уровня, такую как таблица).
Если рассматривать язык программирования как машинный код для абстрактной машины, можно сказать, что интерпретатор – это программа, моделирующая вычисление на этой машине. Машинная память в этом случае также абстрактна и представляет структуры данных в виде таблиц интерпретатора «переменные – значения».
На следующем рисунке процессы компиляции и интерпретации дополнены вводом данных:
Рисунок демонстрирует еще одну разницу между компилятором и интерпретатором. У интерпретатора два источника ввода – исходная программа и входные данные; а компилятору подается только программа. В последующем обсуждении этому различию придадим математическую форму.
Компилировать или интерпретировать? Эта проблема – предмет широко рассмотрения в компьютерных науках. Что лучше: непосредственно обрабатывать исходную информацию в том виде, как она есть, или предварительно привести ее к более удобной форме? Этот вопрос стоит не только при обработке программ, мы будем сталкиваться с ним и при изучении алгоритмов.
У компиляторов и интерпретаторов имеются свои достоинства. Возможны различные критерии. По производительности – времени выполнения программы – компиляторы побеждают.
Все меняется, если в качестве критерия выбрать удобство и скорость разработки. Компилятор стоит между вами и реализацией вашей последней идеи: прежде чем увидеть результаты последнего изменения в программе, необходимо ждать результата компиляции (и связывания, о чем ниже пойдет речь). При интерпретации выполнение начинается незамедлительно.
В принципе, интерпретатор также способен выполнять некоторые из проверок перед выполнением программы. Фактически, чистые интерпретаторы не применяются, они представляют собой всегда некоторую смесь компиляции и интерпретации.
Комбинирование компиляции и интерпретации
Схемы чистой компиляции и чистой интерпретации являются предельными вариантами: большинство практических решений является смесью. Это верно и для процесса компиляции в EiffelStudio, который будет рассмотрен позже в этой лекции.
Заметим, что 100% схема интерпретации имеет мало смысла: каждый раз, когда интерпретатор выполнял очередной оператор, например, оператор цикла, он должен был бы возвращаться многократно к фактической последовательности символов и осуществлять ее разбор. Любое реалистическое решение не могло бы согласиться с такой неразумной тратой ресурсов. Так что фактически интерпретатор также начинает с преобразования входа в форму, приемлемую для интерпретации, например, строя абстрактное синтаксическое дерево. В ходе этого процесса, как отмечалось, возможен контроль проверки типов. Так что даже тогда, когда можно прочесть, что используется интерпретатор языка, частичная компиляция подразумевается.
Комбинирование интерпретации и компиляции идет значительно дальше рассмотренной основной идеи. Выход компилятора не должен быть непосредственным машинным кодом, он может быть субъектом дальнейшего процесса обработки.
Виртуальные машины, байт-код и JIT (Just In Time) компиляторы
Для выполнения апплета пользователям необходим только интерпретатор байт-кода. Они даже не должны знать, что такой интерпретатор существует, если он встроен в их Web-браузер, Поскольку при таком подходе возникают потенциальные риски, связанные с безопасностью, – жульнические или некорректные апплеты могут повредить ваш компьютер, – по этой причине для апплетов необходим интепретатор, который будет строго контролировать операции, разрешенные для апплетов.
Для улучшения эффективности времени выполнения байт-кода применяются JIT (Just In Time) компиляторы, называемые джитерами, – осуществляющие компиляцию по требованию. Основная идея состоит в том, что машинный код для некоторого модуля создается «на лету», в тот момент, когда он первый раз вызывается на выполнение (не следует путать любителя джаза –jitterbug, с ошибками такого компилятора – jitter bug ). Внесем соответствующие дополнения в предыдущий рисунок, который теперь выглядит так:
Обычно, как показано на рисунке, наряду с компиляцией «на лету» (джитингом) остается и возможность интерпретации байт-кода. Компиляция «на лету» обычно имеет место при первом использовании модуля (метода или всего класса), так что она будет нужна только для кода, фактически используемого в этом сеансе выполнения. В сравнении с традиционным компилятором, который компилирует всю программу, такой подход позволяет создавать более компактный код, сокращает время компиляции, но, что более важно, делает компиляцию частью процесса выполнения. Последнее является серьезным недостатком, поскольку к времени выполнения добавляются расходы на компиляцию, так что само время выполнения становится менее предсказуемым.
Стратегия компиляции в EiffelStudio также включает байт-код, но, как мы увидим, она использует различные способы комбинирования интерпретации и компиляции.