Компилятор интерпретатор: Введение в компиляторы, интерпретаторы и JIT’ы / Блог компании Mail.ru Group / Хабр
6.10. Что такое транслятор, компилятор, интерпретатор?
Транслятор (англ. translator
— переводчик) — это программа-переводчик. Она преобразует программу,
написанную на одном из языков высокого уровня, в программу, состоящую
из машинных команд.
Трансляторы реализуются в виде
компиляторов или интерпретаторов. С точки зрения выполнения работы
компилятор и интерпретатор существенно различаются.
Компилятор (англ. compiler — составитель, собиратель) читает всю программу целиком, делает ее перевод и создает законченный вариант программы на машинном языке, который затем и выполняется.
Интерпретатор (англ. interpreter — истолкователь, устный переводчик) переводит и выполняет программу строка за строкой.
После того, как программа
откомпилирована, ни сама исходная программа, ни компилятор более не
нужны. В то же время программа, обрабатываемая интерпретатором, должна
заново переводиться на машинный язык при каждом очередном запуске программы.
Откомпилированные программы работают быстрее, но интерпретируемые проще исправлять и изменять. |
Каждый
конкретный язык ориентирован либо на компиляцию, либо на интерпретацию
— в зависимости от того, для каких целей он создавался. Например, Паскаль
обычно используется для решения довольно сложных задач, в которых важна
скорость работы программ. Поэтому данный язык обычно реализуется с
помощью компилятора.
С другой стороны, Бейсик создавался как язык для начинающих программистов, для которых построчное выполнение программы имеет неоспоримые преимущества.
Иногда для одного языка имеется и компилятор, и интерпретатор.
В этом случае для разработки и тестирования программы можно
воспользоваться интерпретатором, а затем откомпилировать отлаженную
программу, чтобы повысить скорость ее выполнения.
Компиляторы, интерпретаторы и байт-код | Computerworld Россия
Определение
Компиляторы — это программы, которые преобразуют исходные тексты программ, написанные на языке программирования высокого уровня, в программу на машинном языке, «понятную» компьютеру. Полученный код, называемый исполняемой программой, можно устанавливать и запускать на нужном компьютере без дополнительных преобразований. Интерпретаторы выполняют аналогичную функцию, но делают это построчно всякий раз во время исполнения программы. Байт-код — это промежуточный подход, при котором программа преобразуется в промежуточный двоичный вид, интерпретируемый некой «виртуальной машиной» во время исполнения.
Причиной вновь вспыхнувшего интереса к компиляторам стало появление быстрых и сложных 64-разрядных микропроцессоров, типичным представителем которых можно считать Intel Itanium. Все усовершенствования в архитектуре процессоров, такие как распараллеливание и предсказание ветвления, а также возможность резкого увеличения производительности, окажутся бесполезны до тех пор, пока программисты не начнут их реально использовать.
Забота о создании кода, ориентированного на эффективную параллельную обработку, серьезно усложняет и без того непростую задачу современного программирования. В итоге ответственность за увеличение производительности, на которое потенциально способны будущие 64-разрядные процессоры, ложится на компиляторы нового поколения.
Компиляторы, которым предстоит обеспечить значительное увеличение скорости вычислений, уже создаются в исследовательских лабораториях ряда компаний — Hewlett-Packard, Intel, MetaWare, Microsoft и других. В феврале прошлого года компания Silicon Graphics объявила о том, что ее оптимизированные компиляторы позволяют увеличить на 30-100% по сравнению с существующими продуктами производительность программ, работающих на компьютерах с процессорами Itanium и операционной системой Linux.
Как и их предшественники, оптимизированные компиляторы преобразуют программы на высокоуровневом языке в машинный код. Однако помимо этого они гарантируют максимально эффективное использование памяти (и в первую очередь процессорного кэша и механизма распараллеливания).
Например, процессоры Itanium предназначены для того, чтобы одновременно обрабатывать до шести команд на каждый такт процессора. Но для этого компилятор должен поддерживать стабильную передачу данных через конвейер команд.
Одна из возможных методик состоит в объединении часто используемых команд в группы, которые процессор может обрабатывать одновременно. Оптимизированные компиляторы также максимально используют свободные такты процессора за счет предсказания ветвления, пытаясь заранее определить результат команд наподобие GOTO и тем самым уберечь процессор от необходимости искать требуемые данные по всей программе. Метод спекулятивных вычислений предполагает, что оптимизированный компилятор загружает команды с некоторым упреждением.
Другие пути
Интерпретаторы также преобразуют код, написанный на языке программирования высокого уровня, но они делают это построчно всякий раз, когда программа запускается на выполнение. Для того чтобы программа была «понятна» компьютеру, на котором предполагается исполнять высокоуровневый код непосредственно, на нем также должна работать программа интерпретации. Интерпретаторы полезны для тестирования нового или модифицированного кода или при обучении программированию.
Заранее скомпилированное программное обеспечение работает быстрее, чем интерпретируемые программы, поэтому скомпилированные программы предпочтительны для крупных и устоявшихся приложений. За это приходится расплачиваться зависимостью исполняемого кода от конкретной аппаратной платформы. Но такой подход не всегда оправдывает себя в случае с Internet-апплетами, для которых нельзя сказать априори, в какой именно среде они будут работать.
Идеология Java опирается на третий, своего рода компромиссный подход — байт-код. При использовании байт-кода высокоуровневые программы преобразуются в промежуточный вид, способный исполняться на различных аппаратных платформах. Байт-код Java преобразуется в машинный код с помощью специального интерпретатора, называемого виртуальной машиной Java (Java Virtual Machine — JVM). JVM формирует выделенное пространство в памяти, которое отделено от памяти основной системы, для хранения байт-кода и порождаемых структур.
Использование динамических (just-in-time, JIT — «точно в срок») компиляторов увеличивает производительность Java-приложений. В этом случае не JVM исполняет байт-код, а JIT-компилятор преобразует его в «родной» для данной машины код. Таким образом, с одной стороны, повышается производительность скомпилированного кода, а с другой — сохраняется переносимость, свойственная Java.
Hewlett-Packard придерживается аналогичной тактики со своим TurboChai — средой Java для встроенных приложений. В TurboChai производительность увеличивается за счет преобразования наиболее часто используемого кода в данном встроенном приложении. С помощью выборочной компиляции в HP стараются оптимальным образом управлять использованием памяти, в то же время достигая скоростей, сравнимых с теми, которых позволяют добиться JIT-компиляторы. TurboChai использует байт-код Java в качестве входной информации и генерирует исходные тексты ANSI C, а затем использует любой компилятор для языка Си для получения оптимизированного «родного» машинного кода.
В прошлом году Microsoft анонсировала C#, объектно-ориентированный язык программирования, согласованный с XML. Корпорация подает новый язык как логическое продолжение Си и C++ для Web-приложений. Ключевыми модулями станут Common Language Runtime для C# и специальный компилятор, который преобразует текст, написанный на традиционных языках Кобол, Perl, Фортран или других, в промежуточный язык, который будет работать на новой платформе Microsoft .Net.
Конечные пользователи вряд ли будут уделять много внимания компиляторам. Тем не менее может появиться новое поколение компиляторов, позволяющих увеличить производительность до уровня, позволяющего убедить профессионалов в необходимости использовать 64-разрядные аппаратные архитектуры.
Инструментарий | Что нового | Цели |
Оптимизированные компиляторы | Обеспечивают высокую производительность процессорной обработки за счет распараллеливания, предсказания ветвлений и спекулятивных вычислений | Помогают реализовать потенциал 64-разрядных процессоров |
JIT-компиляторы | В реальном времени компилируют код | Увеличивают производительность интерпретируемых языков, таких как Java |
«Выборочные» компиляторы | Компилируют только часто используемый код | Увеличивают производительность, не тратя понапрасну дорогостоящие ресурсы памяти |
Поделитесь материалом с коллегами и друзьями
Компиляторы против интерпретаторов | Программирование на C и C++
Термины компилятор и интерпретатор описывают способ, с помощью которого выполняется программа. Теоретически любой язык программирования может быть или компилятором, или интерпретатором, но некоторые языки обычно являются либо компиляторами, либо интерпретаторами. Например, Бейсик — обычно интерпретатор, а С — обычно компилятор. Способ, с помощью которого программа выполняется, не определяется языком программирования, на котором она написана. Интерпретаторы и компиляторы — это просто сложные программы, оперирующие с исходным кодом.
Интерпретатор построчно читает исходный код программы и выполняет инструкции, содержащиеся в текущей строке, потом переходит к следующей строке. Компилятор читает всю программу и преобразует ее в объектный код, который является такой формой кода, которая может напрямую выполняться компьютером. Объектный код также называется двоичным кодом или машинным кодом. Если программа скомпилирована, то сам исходный код больше не влияет на дальнейшую работу программы.
Когда используется интерпретатор, он должен присутствовать все время для выполнения программы. Например, в традиционном Бейсике необходимо запустить интерпретатор Бейсика, затем загрузить программу и набрать RUN для запуска. Интерпретатор построчно проверит на правильность и выполнит программу. Этот медленный процесс возникает каждый раз при запуске программы. В противоположность этому, компилятор преобразует программу в объектный код, который может напрямую выполняться компьютером. Поскольку компилятор переводит программу только один раз, то все, что необходимо сделать, — это запустить программу, обычно путем простого набора имени. Таким образом, компиляция кода Должна выполняться только один раз, в то время как интерпретация — каждый раз при запуске программы.
Два термина, которые будут часто встречаться, — это время компиляции, которое соответствует событиям, возникающим в процессе компиляции, и время выполнения, которое соответствует событиям, возникающим при выполнении программы. Обычно данные термины встречаются при обсуждении ошибок в фразах «ошибки времени компиляции» и «ошибки времени выполнения».
Компиляторы – Из исходного кода в машинный / Хабр
Месяц назад я попытался сосчитать, сколько разных инструкций поддерживается современными процессорами, и насчитал 945 в Ice Lake. Комментаторы затронули интересный вопрос: какая часть всего этого разнообразия реально используется компиляторами? Например, некто Pepijn de Vos в 2016 подсчитал, сколько разных инструкций задействовано в бинарниках у него в /usr/bin, и насчитал 411 — т.е. примерно треть всех инструкций x86_64, существовавших на тот момент, не использовались ни в одной из стандартных программ в его ОС. Другая любопытная его находка — что код для x86_64 на треть состоит из инструкций mov
. (В общем-то известно, что одних инструкций mov
достаточно, чтобы написать любую программу.)
Я решил развить исследование de Vos, взяв в качестве «эталонного кода» компилятор LLVM/Clang. У него сразу несколько преимуществ перед содержимым /usr/bin неназванной версии неназванной ОС:
- С ним удобно работать: это один огромный бинарник, по размеру сопоставимый со всем содержимым /usr/bin среднестатистического линукса;
- Он позволяет сравнить разные ISA: на releases.llvm.org/download.html доступны официальные бинарники для x86, ARM, SPARC, MIPS и PowerPC;
- Он позволяет отследить исторические тренды: официальные бинарники доступны для всех релизов начиная с 2003;
- Наконец, в исследовании компиляторов логично использовать компилятор и в качестве подопытного объекта 🙂
Начну со статистики по мартовскому релизу LLVM 10.0:
В прошлом топике комментаторы упомянули, что самый компактный код у них получается для SPARC. Здесь же видим, что бинарник для AArch64 оказывается на треть меньше что по размеру, что по общему числу инструкций.
А вот распределение по числу инструкций:
Разница между компилятором и интерпретатором
Разница между компилятором и интерпретатором
№ | Компилятор | Переводчик |
---|---|---|
1 | принимает всю программу в качестве входных данных | Интерпретатор принимает Одиночная инструкция в качестве входных данных. |
2 | Промежуточный код объекта: Создано | Нет Код промежуточного объекта: Создан |
3 | Условные операторы управления выполняются быстрее | Условные операторы управления выполняются на медленнее |
4 | Требования к памяти : Еще (поскольку создается код объекта) | Требования к памяти — это Минус |
5 | Программу не нужно компилировать каждый раз | Каждый раз, когда программа более высокого уровня преобразуется в программу более низкого уровня |
6 | Ошибки отображаются после проверки всей программы | Ошибки отображаются для каждая инструкция интерпретируется (если есть) |
7 | Пример : Компилятор C | Пример : BASIC |
Объяснение: компилятор против интерпретатора
Просто поймите концепцию компилятора и интерпретатора —
- Мы передаем полную программу в качестве входных данных компилятору.Наша программа написана в удобочитаемом формате.
- Человеко-читаемый формат проходит много этапов компиляции и, наконец, конвертируется в машиночитаемый формат.
- Однако интерпретатор принимает на входе одну строку кода за раз и выполняет эту строку. Он прекратит выполнение кода, как только обнаружит ошибку.
- Требование к памяти меньше в случае интерпретатора, поскольку в случае интерпретатора объектный код не создается.
Следующее видео расскажет гораздо больше о компиляторе —
Пояснение к видео:
.
Компилятор и интерпретатор
Узнайте об основных различиях между компилятором и интерпретатором. В этой статье рассказывается, как исходный код преобразуется в машинный код и байт-код. И компилятор, и интерпретатор используют разные подходы к этому преобразованию.
«В чем разница между компилятором и интерпретатором?» , это был один из часто задаваемых вопросов на моих курсах информатики. Если вы изучаете программирование, вам определенно понадобится сравнить компилятор иинтерпретатор и узнайте разницу. К сожалению, большинство студентов, изучающих информатику, склонны просто подбирать ответ, не понимая сути концепции. Даже некоторые учителя не знают концепции компилятора и интерпретатора настолько хорошо, чтобы учить своих учеников!
Этим утром, разговаривая с одним из членов моей команды, я снова вспомнил это классическое сравнение компилятора и интерпретатора, и я сразу же решил написать об этом небольшой фрагмент. Эта статья будет полезна всем желающим программистам.
Что такое компилятор?
Прежде всего вам нужно понять, что компьютеры и люди говорят на разных языках. Хотя люди говорят на таких языках, как английский, французский, хинди, испанский, китайский, японский, арабский и т. Д .; компьютеры говорят только на одном языке, то есть на двоичном. Алфавит компьютеров состоит всего из двух букв, а именно ноль и один . Компьютеры — это машины, и для них намного проще работать, используя более простое кодирование нулей и единиц.
Мы, люди, чувствуем себя наиболее комфортно, если можем давать инструкции, написав программы для компьютеров на простом английском или хинди.
Проблема в том, что нам неудобно работать с двоичным кодом, а компьютеры находят наши языки слишком сложными для понимания. Чтобы обойти эту проблему, используется промежуточный язык для передачи человеческих команд компьютерам. Этот промежуточный язык называется — , язык программирования .
Язык программирования — это не простой английский. По сути, это предопределенный синтаксис написания логических компьютерных инструкций, которые также могут понять люди.
Нам также нужно что-то для преобразования языка программирования в двоичный язык для использования компьютером.Здесь на сцену выходит компилятор.
Компилятор — это программное обеспечение, которое проверяет компьютерную программу (называемую исходным кодом , ) и перечисляет все обнаруженные ошибки. Когда люди удаляют все эти ошибки, компилятор преобразует программу в двоичный код (также известный как машинный код или объектный код ). Компьютеры могут понимать двоичный код и поэтому могут выполнять инструкции, написанные людьми с использованием языка программирования.
Исходный код и код сборки.
Следующее видео еще больше поможет вам понять концепцию и работу компилятора:
Компилятор против интерпретатора
Теперь мы уже знаем, что делает компилятор. Задача переводчика примерно такая же, но интерпретатор работает иначе. Разница между функционированием компилятора и интерпретатора будет очевидна из приведенной ниже таблицы сравнения:
# | Компилятор | Интерпретатор |
---|---|---|
1 | Компилятор работает сразу со всей программой.В качестве входных данных принимает всю программу . | Программа переводчика работает построчно. В качестве входных данных требуется по одному оператору за раз . |
2 | Компилятор генерирует промежуточный код, называемый объектным кодом или машинным кодом. | Интерпретатор не генерирует промежуточный объектный код или машинный код. |
3 | Компилятор выполняет условные операторы управления (например, if-else и switch-case) и логические конструкции на быстрее, чем интерпретатор. | Интерпретатор выполняет условные операторы управления с гораздо меньшей скоростью . |
4 | Скомпилированные программы занимают больше памяти , потому что весь объектный код должен находиться в памяти. | Интерпретатор не генерирует промежуточный объектный код. В результате интерпретируемых программ более эффективно используют память. |
5 | Скомпилировать один раз и запускать в любое время.Скомпилированную программу не нужно каждый раз компилировать. | Интерпретируемые программы интерпретируются построчно при каждом запуске. |
6 | Об ошибках сообщается после проверки всей программы на наличие синтаксических и других ошибок. | Сообщение об ошибке появляется, как только обнаруживается первая ошибка. Остальная часть программы не будет проверяться, пока существующая ошибка не будет устранена. |
7 | Отладка скомпилированного языка сложнее. | Отладка проста, поскольку интерпретатор останавливается и сообщает об ошибках по мере их обнаружения. |
8 | Компилятор не разрешает запуск программы до тех пор, пока она полностью не избавится от ошибок. | Интерпретатор запускает программу с первой строки и останавливает выполнение только в случае обнаружения ошибки. |
9 | Скомпилированные языки более эффективны, но их сложно отлаживать. | Интерпретируемые языки менее эффективны, но их легче отлаживать.Это делает такие языки идеальным выбором для новых студентов. |
10 | Примеры языков программирования, использующих компиляторы: C, C ++, COBOL | Примеры языков программирования, использующих интерпретаторы: BASIC, Visual Basic, Python, Ruby, PHP, Perl, MATLAB , Lisp |
На следующем изображении показано, как компилируются или интерпретируются разные языки:
Разница между компилятором и интерпретатором.
Разница между компилятором и интерпретатором
Итак, что мы поняли из приведенной выше таблицы сравнения? Теперь мы знаем, что причина, по которой скомпилированный код выполняется быстрее, потому что он конвертируется в машинный код сразу . Компьютер легко понимает машинный код и, следовательно, может быстро запустить всю программу. Но это также означает, что весь скомпилированный код должен находиться в памяти — и, таким образом, компилируемым программам требуется больше памяти.В настоящее время, когда память доступна в изобилии, это больше не проблема. Но в ранние дни программирования, когда память была дорогостоящим ресурсом, размер программы вплоть до каждого бита и байта имел значение.
Для сравнения, интерпретатор — более удобная для человека программа . Это работает очень похоже на работу людей. Он начинает выполнение программы прямо с первой строки и будет продолжать показывать вам результат программы, пока не обнаружит ошибочную строку кода. В результате для программиста намного легче найти ошибку и понять природу ошибки .Однако переводчик работает медленно. Интерпретируемые программы интерпретируются каждый раз при запуске.
Java — это компилируемый и интерпретируемый язык
Ах! Java — потрясающий язык программирования. Первоначально разработанный Джеймсом Гослингом, этот язык включает в себя несколько инновационных функций. Одна из таких функций — виртуальная машина Java (JVM). Кроме того, Java является компилируемым и интерпретируемым языком. Когда вы пишете программу на Java, компилятор javac преобразует вашу программу в нечто, называемое байт-кодом , .Все программы Java запускаются внутри JVM (это секрет кроссплатформенности Java). Байт-код, скомпилированный javac , попадает в память JVM и там интерпретируется другой программой под названием java . Эта программа java построчно интерпретирует байт-код и преобразует его в машинный код для запуска JVM. На следующей блок-схеме показано, как выполняется программа Java.
Выполнение программы на Java. Java — это компилируемый и интерпретируемый язык.
Я надеюсь, что эта статья помогла вам понять концепции компилятора и интерпретатора. Если у вас есть дополнительные вопросы о различиях между компилятором и интерпретатором, не стесняйтесь комментировать и спрашивать меня. Я обязательно постараюсь вам помочь. Спасибо за использование TechWelkin!
.