Компиляция и интерпретация кода: что это такое и в чем разница
Наши компьютеры — это переключатели, для которых мы пишем инструкции. При этом для их работы мы пишем тексты на английском (ну или русском, если мы говорим про 1С) языке. Рассказываем, как наши изощренные языковые инструкции превращаются в примитивный двоичный код, при этом абсолютно не теряя смысла.
Это адаптированный перевод статьи A Deeper Inspection Into Compilation And Interpretation от разработчика Vaidehi Joshi из компании Vimeo. Повествование ведется от имени автора.

Если у вас нет способа говорить с компьютером на человеческом языке, то вы вынуждены писать машинный код. При этом даже после появления первых компьютеров программирование как таковое появилось не сразу: тогда вычислительные устройства весили по 13 тонн, занимали комнату, стоили миллионы долларов, а годились только для выполнения арифметических операций.
Когда одна программистка из Гарварда научила компьютер понимать инструкции, которые похожи на человеческую речь, ее открытием просто никто не воспользовался — люди не понимали, зачем это нужно. Инженеры 50-х не могли даже представить себе мир, в котором компьютеры выполняют инструкции, а не считают формулы.
Чтобы понять упрямство людей того времени, пройдем вместе с ними этот тернистый путь, выстланный перфокартами.
Все объединяет идея языков
Машинный код в конечном итоге является языком, пусть и очень простым. Код, который пишут программисты, тоже написан на каком-то языке. Если смотреть на два этих кода — машинный и созданный разработчиками, как на два текста на разных языках, становится очевидным, что нам нужен переводчик.
Давайте на минуту представим такой переводчик. Он обязан сохранить смысл текста, но чтобы сделать это хорошо, он также должен:
- Проверить текст на ошибки
- Сделать лексический и синтаксический анализ
- Сохранить результат перевода.
Теперь становится понятно, почему инженерам прошлого, которые до этого видели только калькуляторы, сложно было представить себе переводчик между языками. К счастью для нас, эти трудности не напугали парочку бунтарей — Грейс Хоппер и Стива Рассела. Они работали в разных лабораториях, но оба пошли наперекор начальству и придумали те переводчики, которыми мы пользуемся каждый день.
Чтобы познакомиться с ними, а заодно и с магией перевода, перенесемся в США прошлого века.
От цифр к словам
Преспер Эккерт и Джон Мокли делали компьютеры для военных. Сначала они работали в родном университете, но потом тот стал присваивать патенты преподавателей. Эккерту и Мокли это не понравилось, они ушли и открыли собственную фирму по продаже компьютеров.
Так они получили первый заказ от Бюро переписи населения США, но для этого им пришлось соврать по мелочи — например, занизить цену в три раза, но зато компьютер в итоге получился отличный. Еще бы, ведь над ним работали лучшие инженеры того времени.
В том числе и Грейс Хоппер.
Однажды Хоппер предложила коллегам не мучиться с машинным кодом, а говорить с компьютером на английском языке. Например, сказать ему: «Вычти подоходный налог из зарплаты». Как отреагировали ее коллеги и начальство, вы уже знаете: «Они мягко объяснили мне, что компьютеры могут решать лишь арифметические задачи и что они никогда не смогут выполнять программы», — рассказывала Хоппер в своей биографии «Grace Hopper: Navy Admiral and Computer Pioneer».
Но Грейс Хоппер не так легко сбить с толку. Эта женщина пошла на фронт добровольцем, причем исключительно благодаря напористости — ее не хотели брать из-за дефицита веса. Она закончила обучение с лучшими оценками и стала лучшим инженером штаба.
Хоппер проявила упорство и на новой работе. Она в одиночку придумала первый в мире переводчик, который позволял говорить с компьютером на английском языке. Теперь программировать могли не только математики, а кто угодно! При этом сами программы теперь можно было сделать намного более сложными.
Первым переводчиком был компилятор
Хоппер показала коллегам свой переводчик в 1952 году, и ее проигнорировали. Три года технологией никто не пользовался, пока, наконец, проект не заметили в Министерстве обороны США.
Зачем военным понадобился компьютер, который заказали в Бюро переписи населения? Зачем им нужна была технология Хоппер, на которую махнули рукой ее более авторитетные коллеги?
Дело в устройстве первого переводчика (как говорят в программировании, транслятора). Вот как работал этот транслятор:
- Хоппер писала инструкцию на английском языке — «Вычти подоходный налог»
- Компилятор переводил инструкцию в машинный код — тогда это были цифры и буквы
- Компьютер выполнял машинный код, не зная ничего про инструкцию на английском.
Как вы видите, транслятор Хоппер делал весь перевод текста за один подход. Транслятор, который делает весь перевод за один раз, называется компилятором. Это важный момент, потому что мы познакомимся и с другим видом трансляторов, интерпретатором, но для этого нужно подробнее изучить именно работу компиляторов.

Для Хоппера было важно, что благодаря компилятору инструкции можно было писать на языке программирования, похожим на человеческий — это был прообраз COBOL. Военных интересовало другое: в результате работы компилятора пользователь мог пользоваться программой, но не мог прочитать ее исходный код.
Военные давно искали способ делиться программами так, чтобы никто не мог узнать их исходный код. В том числе по этой причине мы до сих пор пользуемся скомпилированными программами, тогда как во времена Хоппер были только перфокарты, но принцип остался тем же.

Люди в американском правительстве считали компилятор временным решением. Однако концепция трансляторов, как и принципы языка COBOL, прочно вошли в инженерные практики на многие годы.
Но когда вы пишете код, то можете запустить его, не компилируя. Вы построчно видите выполнение кода в консоли и работаете с ошибками «на лету». Это работа интерпретатора — другого вида трансляции в машинный код.
Этот транслятор придумал другой бунтарь: его тоже отвергали авторитеты, и он тоже определил черты индустрии на многие годы. История Хоппер повторилась, но в этот раз в другом штате.
Как интерпретатор делает построчную трансляцию
На дворе идет 1958 год, компиляторы давно и успешно используются — в том числе в Массачусетском технологическом университете, где стоит IBM 704. Эта гигантская дорогая штуковина занимает всю комнату. И на ней куется Lisp — язык, на котором 30 лет после этого писался весь код для разработок в области искусственного интеллекта.
Но сейчас, в октябре 58-го, один из местных разработчиков прохлаждается вместо того, чтобы кормить адскую машину перфокартами. Он углубился в чтение статьи своего профессора и по совместительству босса, Джона Маккарти. Бездельника звали Стив Рассел.
«Потом Стив подошел ко мне и сказал: "Слушай, а почему у нас нет функции eval?". Я посмеялся конечно, и отвечаю: "Слушай, не путай теорию и практику, хорошо? Eval — это теоретическое понятие"», — Джон Маккарти для симпозиума ACM 1984 года.
Маккарти хотел как лучше, отказывая Расселу в проекте. Подумайте сами: eval — это команда, которая превращает любую строку в функцию и потом еще выполняет ее. Это два действия за один перевод! Невыполнимый трюк для транслятора, который умеет отдавать процессору только одну инструкцию за раз.
Рассел нашел решение всего за пару месяцев: он создал транслятор, который запускает код построчно. Такой транслятор и называется интерпретатором. Кстати, вы используете его и на Хекслете: пишете код и тут же запускаете без компиляции, чтобы отловить ошибки.

Построчный запуск кода — непростая задача. Потребуется скомпилировать код вручную много-много раз, прежде чем вы сможете создать свой первый интерпретатор.
Но если вы просто будете отправлять инструкции процессору построчно, то у вас не будет интерпретатора. Он отправляет результат перевода не в процессор, а обратно в программу — это позволяет создавать интересные многоступенчатые команды вроде eval .
От транслятора зависит не только опыт программиста, но и опыт пользователя. Как запустить код на любой операционной системе? Какой транслятор работает быстрее? Ответ в следующем разделе статьи.
Транслятор влияет на опыт пользователя
Представьте, что вы проходите уроки по циклам и решаете там задачи. Однажды вам попадается интересный ответ другого студента, поэтому вы копируете его код в редактор и смотрите на вывод в консоли.
Вы, как пользователь кода, запустили программу через интерпретатор. Так как это программа от студента и для студента, то здорово, что код не скомпилирован в исполняемый файл: вы можете посмотреть и отредактировать его.

Еще нам неважно, что у другого студента MacOS, а у вас — Windows: интерпретатор берет всю работу по совместимости на себя, для работы кода важно, чтобы у всех стоял интерпретатор.
Интерпретация идеальна для распространения небольших программ, но для больших проектов не подойдет.
Для крупных проектов выбирают компиляцию: компиляция быстрее и безопаснее, хотя времени на этот процесс может уйти очень много. Только вот придется озаботиться проблемами совместимости, хотя мы уже привыкли устанавливать только подходящие нашему железу и софту программы.

Компилятор и интерпретатор делают одну и ту же работу, так почему компилятор быстрее?
Компиляция работает быстрее интерпретации, потому что компилятор запускается только один раз: делает перевод и отдает его процессору. Интерпретатор же запускается на каждой строке кода и нужен при каждом запуске программы. Кроме того, программный код в компиляторе уже переведен в машинный, поэтому требуется намного меньше времени для его исполнения.
За последние десять минут мы прошли путь, который занял у программистов двенадцать лет, но оно стоило того: мы научили машины говорить с нами на одном языке.
Никогда не останавливайтесь: В программировании говорят, что нужно постоянно учиться даже для того, чтобы просто находиться на месте. Развивайтесь с нами — на Хекслете есть сотни курсов по разработке на разных языках и технологиях
Компилятор VS интерпретатор: ключевые отличия
Интерпретаторы и компиляторы отвечают за преобразование языка программирования или сценариев (язык высокого уровня) в машинный код. Но если обе программы делают одно и то же, чем они различаются? Давайте разберемся.
Компилятор
Что такое компилятор?
Компилятор — это компьютерная программа, которая переводит компьютерный код с одного языка программирования на другой. Компилятор берет программу целиком и преобразует ее в исполняемый компьютерный код. Для этого требуется целая программа, так как компьютер понимает только то, что написано двоичным кодом. Задача компилятора — преобразовать исполняемую программу в машинный код, который и распознается компьютером. Примерами скомпилированных языков программирования являются C и C++.
Компилятор в основном используется для программ, которые переводят исходный код с языка программирования высокого уровня на язык программирования более низкого уровня.
Компилятор способен выполнять многие или даже все операции: предварительную обработку данных, парсинг, семантический анализ, преобразование входных программ в промежуточное представление, оптимизацию и генерацию кода.
Интерпретатор
Что такое интерпретатор?
Интерпретатор — это компьютерная программа, которая преобразует каждый программный оператор высокого уровня в машинный код. Сюда входят исходный код, предварительно скомпилированный код и сценарии.
Интерпретатор представляет собой машинную программу, которая непосредственно выполняет набор инструкций без их компиляции. Примерами интерпретируемых языков являются Perl, Python и Matlab.
- И компилятор, и интерпретатор выполняют одну и ту же работу — преобразовывают язык программирования высокого уровня в машинный код. Однако компилятор преобразовывает исходный материал в машинный код перед запуском программы. Интерпретатор выполняет эту функцию при ее запуске.
Как это работает?
Сначала компилятор создает программу. Он анализирует все операторы языка, чтобы проверить, правильны они или нет. Если компилятор найдет какую-нибудь ошибку, он выдаст соответствующее сообщение. Если же он не обнаружит никаких ошибок, то преобразует исходный код в машинный. Компилятор связывает различные кодовые файлы в программы, которые можно запустить (например, формата .exe). После этого запускается программа.
Интерпретатор создает программу. Он не связывает файлы и не генерирует машинный код. Происходит построчное выполнение исходных операторов во время исполнения программы.
Какая разница между Интерпретацией и Компиляцией в обработке?
В чём суть разницы этих подходов?
Про интерпретацию читал, что это мгновенное выполнение, без превращения её в машинный код, но она же должна обработаться процесером, который понимает только машинный код? Как она тогда работает?
А Компиляция уже более понятно к логике, что преобразует код в машинный, а там уже процессор мутит свои дела и мы получаем результат.
По логике что выходит, на каком языке у нас получится продуктивнее сервер, Java или php?
- Вопрос задан более трёх лет назад
- 3414 просмотров
- Вконтакте

Компиляция — это один раз преобразуем наш код в машинный и пользуем потом всегда.
Интерпретация — каждый раз преобразуем код в машинный, там просто цепочка длиннее.
Конечно скомпилированные программы обычно быстрее работают, но раньше компиляция долго шла сама по себе, например 30 минут. Сейчас появлением, например, golang программа может и компилироваться за секунду, это позволяет вносить изменения в большой проект очень часто.
- Вконтакте

Вы никогда не писали калькулятор с простейшим парсингом арифметических выражений?
Это ведь уже простейший интерпретатор, хоть в нем и нет нормальной реализации ни лексического, ни синтаксического анализатора, но даже такого г..нокода достаточно, чтобы понимать, как работает интерпретатор, и как так получается, что если во входной строке знак «+» то в итоге процессор складывает значения, а если «-» то вычитает.
А вы, видимо, даже до такого г..нокода не можете додуматься, а хотите делать какие-то глобальные выводы про продуктивность Java и PHP.
Не нужно вам лезть в такие дебри, теория без практики — мертва, она превращается в лженауку.
Лучше попробуйте написать сайт на PHP, а затем на Java, пользы будет в десятки раз больше, чем от пространных рассуждений «хелловорлдщика».
- Вконтакте


Ingernirated: Ошибаетесь. Могу. А вот вы не можете понять ответ, и вообще в голове каша, поскольку нет практического опыта, а лишь обрывки теории.
Я прокомментировал вот этот абзац:
Я объяснил, как работает интерпретация, привел исходный код простейшего интерпретатора.
Было еще два абзаца — «какая разница между интерпретацией и компиляцией», и про продуктивность Java vs PHP.
Но понимание разницы автоматически вытекает из понимания интерпретации, а насчет продуктивности, я и ответил, что это бред, связывать ее с тем, интерпретируемый ли ЯП или JIT-компилируемый. С таким же успехом можно по форме черепа создателя ЯП определять его продуктивность, и задавать вопросы, основанные на этом ложном тезисе.
Основные принципы программирования: компилируемые и интерпретируемые языки
Как и в предыдущей статье этого цикла, я хочу обратить ваше внимание на ключевые принципы программирования, которые влияют на всё то, что мы делаем, но с которыми мы редко сталкиваемся напрямую и поэтому не до конца их понимаем. Тема сегодняшней статьи — компилируемые и интерпретируемые языки.
Будучи разработчиками, мы часто сталкиваемся с такими понятиями, как компилятор и интерпретатор, но я считаю, что многие не совсем понимают, что они означают. Между тем, компиляция и интерпретация — это основы работы всех языков программирования. Давайте взглянем на то, как на самом деле устроены эти понятия.
Вступление
Мы полагаемся на такие инструменты, как компиляция и интерпретация, чтобы преобразовать наш код в форму, понятную компьютеру. Код может быть исполнен нативно, в операционной системе после конвертации в машинный (путём компиляции) или же исполняться построчно другой программой, которая делает это вместо ОС (интерпретатор).
Компилируемый язык — это такой язык, что программа, будучи скомпилированной, содержит инструкции целевой машины; этот машинный код непонятен людям. Интерпретируемый же язык — это такой, в котором инструкции не исполняются целевой машиной, а считываются и исполняются другой программой (которая обычно написана на языке целевой машины). Как у компиляции, так и у интерпретации есть свои плюсы и минусы, и именно это мы и обсудим.
Прежде чем мы продолжим, стоит отметить, что многие языки программирования имеют как компилируемую, так и интерпретируемую версии, поэтому классифицировать их затруднительно. Тем не менее, чтобы не усложнять, в дальнейшем я буду разделять компилируемые и интерпретируемые языки.
Компилируемые языки
Главное преимущество компилируемых языков — это скорость исполнения. Поскольку они конвертируются в машинный код, они работают гораздо быстрее и эффективнее, нежели интерпретируемые, особенно если учесть сложность утверждений некоторых современных скриптовых интерпретируемых языков.
Низкоуровневые языки как правило являются компилируемыми, поскольку эффективность обычно ставится выше кроссплатформенности. Кроме того, компилируемые языки дают разработчику гораздо больше возможностей в плане контроля аппаратного обеспечения, например, управления памятью и использованием процессора. Примерами компилируемых языков являются C, C++, Erlang, Haskell и более современные языки, такие как Rust и Go.
Проблемы компилируемых языков, в общем-то, очевидны. Для запуска программы, написаной на компилируемом языке, её сперва нужно скомпилировать. Это не только лишний шаг, но и значительное усложнение отладки, ведь для тестирования любого изменения программу нужно компилировать заново. Кроме того, компилируемые языки являются платформо-зависимыми, поскольку машинный код зависит от машины, на которой компилируется и исполняется программа.
Интерпретируемые языки
В отличие от компилируемых языков, интерпретируемым для исполнения программы не нужен машинный код; вместо этого программу построчно исполнят интерпретаторы. Раньше процесс интерпретации занимал очень много времени, но с приходом таких технологий, как JIT-компиляция, разрыв между компилируемыми и интерпретируемыми языками сокращается. Примерами интерпретируемых языков являются PHP, Perl, Ruby и Python. Вот некоторые из концептов, которые стали проще благодаря интерпретируемым языкам:
- Независимость от платформы; ; ;
- Меньший размер исполняемых файлов: .
Основным недостатком интерпретируемых языком является их невысокая скорость исполнения. Тем не менее, JIT-компиляция позволяет ускорить процесс благодаря переводу часто используемых последовательностей инструкции в машинный код.
Бонус: байткод-языки
Байткод-языки — это такие языки, которые используют для исполнения кода как компиляцию, так и интерпретацию. Java и фреймворк .NET — это типичные примеры байткод-языков. На самом деле, Java Virtual Machine (JVM) — это настолько популярная виртуальная машина для интерпретации байткода, что на ней работают реализации нескольких языков. Кстати, недавно стало известно, что в новой версии Java будет также поддерживаться и статическая компиляция.
В байткод-языке сперва происходит компиляция программы из человекочитаемого языка в байткод. Байткод — это набор инструкций, созданный для эффективного исполнения интерпретатором и состоящий из компактных числовых кодов, констант и ссылок на память. С этого момента байткод передаётся в виртуальную машину, которая затем интерпретирует код также, как и обычный интерпретатор.
При компиляции кода в байткод происходит задержка, но дальнейшая скорость исполнения значительно возрастает в силу оптимизации байткода. Кроме того, байткод-языки являются платформо-независимыми, превосходя при этом по скорости интерпретируемые. Для них также доступна JIT-компиляция.
Заключение
Многие языки в наши дни имеют как компилируемые, так и интерпретируемые реализации, сводя разницу между ними на нет. У каждого вида исполнения кода есть преимущества и недостатки.
Вкратце, компилируемые языки являются самыми эффективными, поскольку они исполняются как машинный код и позволяют использовать аппаратное обеспечение системы. Однако это вводит дополнительные ограничение на написание кода и делает его платформо-зависимым. Интерпретируемые же языки не зависят от платформы и позволяют использовать такие техники динамического программирования, как метапрограммирование. Тем не менее, в скорости исполнения они значительно уступают компилируемым языкам.
Байткод-языки, в свою очередь, пытаются использовать сильные стороны обоих видов языков, и у них это неплохо получается.