Чем отличается компилятор от интерпретатора

Чем отличается компилятор от интерпретатора

Интерпретатор и Компилятор играют очень важную роль в исполнении программ на компьютерном языке. Многие люди склонны думать, что оба они похожи друг на друга. Тем не менее, они оба различаются в разных контекстах.

Мы можем общаться только с компьютерами на их языке. Компьютеры понимают только двоичный язык 0 и 1. Однако большинство программ написаны на высоких языках и, следовательно, должны быть переведены в двоичном виде. Интерпретатор и компилятор — это программы, которые переводят язык программ на понятный компьютеру машинный язык. Вы можете подумать, что оба служат одной и той же цели, тогда как они оба отличаются друг от друга.

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

Компилятор создает объектный код перед созданием для него исполняемого файла. Скомпилированная программа напрямую выполняется с использованием объектного кода. С другой стороны, переводчик

выполняет исходный код, читая по одной строке за раз. Во время выполнения собственный код выполняется построчно. И компиляторы, и интерпретаторы написаны на языках программирования высокого уровня. Например, Java-интерпретатор может быть написан на Java, Pascal и т. Д. Оба имеют свои преимущества и недостатки. Оба подхода могут быть смешаны для достижения гибридного подхода. Например, на языке LISP разработка выполняется в интерпретируемой среде LISP. Полученные модули затем хорошо тестируются и могут быть скомпилированы компилятором LISP. Различия перечислены ниже в таблице:

составитель

переводчик

Высокий уровень обучения машинному языку

Инструкция высокого уровня в промежуточный код

Компилятор — это переводчик, который преобразует исходный язык (язык высокого уровня) в объектный язык (машинный язык). В отличие от компилятора, интерпретатор — это программа, которая имитирует выполнение программ, написанных на языке оригинала. Другое отличие между компилятором и интерпретатором заключается в том, что компилятор преобразует всю программу за один раз, с другой стороны, интерпретатор преобразует программу, занимая по одной строке за раз.

Очевидно, восприятие человека и электронного устройства, такого как компьютер, отличается. Люди могут понимать что угодно через естественные языки, но компьютер не понимает. Компьютер нуждается в переводчике для преобразования языков, написанных в читаемой человеком форме, в читаемую компьютером форму.

Компилятор и интерпретатор являются типами языкового переводчика. Что такое языковой переводчик? Этот вопрос может возникнуть у вас в голове.

Языковой переводчик — это программное обеспечение, которое переводит программы из исходного языка в удобочитаемой для человека форме в эквивалентную программу на объектном языке. Исходный язык обычно является языком программирования высокого уровня, а объектный язык обычно является машинным языком реального компьютера.

Сравнительная таблица

Основа для сравнения составитель переводчик
вход Это занимает всю программу за раз. Это занимает одну строку кода или инструкции за один раз.
Выход Он генерирует промежуточный объектный код. Он не производит никакого промежуточного объектного кода.
Рабочий механизм Компиляция выполняется перед выполнением. Компиляция и исполнение происходят одновременно.
скорость Сравнительно быстрее Помедленнее
объем памяти Требование к памяти больше из-за создания объектного кода. Это требует меньше памяти, поскольку не создает промежуточный объектный код.
ошибки Показать все ошибки после компиляции, все одновременно. Отображает ошибку каждой строки одну за другой.
Обнаружение ошибок Сложно Проще сравнительно
Относящиеся языки программирования C, C ++, C #, Scala, машинопись использует компилятор. Java, PHP, Perl, Python, Ruby использует интерпретатор.

Определение компилятора

Компилятор — это программа, которая читает программу, написанную на языке высокого уровня, преобразует ее в машинный или язык низкого уровня и сообщает об ошибках, присутствующих в программе. Он конвертирует весь исходный код за один раз или может сделать это за несколько проходов, но, наконец, пользователь получает скомпилированный код, который готов к выполнению.

Компилятор работает по фазам; Различные этапы можно сгруппировать в две части:

  • Этап анализа компилятора также называется внешним интерфейсом, в котором программа делится на фундаментальные составные части и проверяет грамматику, семантику и синтаксис кода, после чего генерируется промежуточный код. Этап анализа включает в себя лексический анализатор, семантический анализатор и синтаксический анализатор.
  • Этап синтеза компилятора также известен как серверная часть, в которой оптимизируется промежуточный код и генерируется целевой код. Этап синтеза включает в себя оптимизатор кода и генератор кода.

Фазы компилятора

Теперь давайте разберемся с работой каждого этапа в деталях.

  1. Лексический анализатор : он сканирует код в виде потока символов, группирует последовательность символов в лексемы и выводит последовательность токенов со ссылкой на язык программирования.
  2. Синтаксический анализатор : на этом этапе токены, сгенерированные на предыдущем этапе, проверяются на соответствие грамматике языка программирования, независимо от того, являются ли выражения синтаксически правильными или нет. Это делает разбор деревьев для этого.
  3. Семантический анализатор : он проверяет, соответствуют ли выражения и операторы, сгенерированные на предыдущем этапе, правилу языка программирования, и создает аннотированные деревья разбора.
  4. Генератор промежуточного кода : генерирует эквивалентный промежуточный код исходного кода. Существует много представлений промежуточного кода, но TAC (трехадресный код) используется наиболее широко.
  5. Оптимизатор кода : улучшает требования к времени и пространству программы. Для этого он устраняет избыточный код, присутствующий в программе.
  6. Генератор кода : это последняя фаза компилятора, в которой генерируется целевой код для конкретной машины. Он выполняет такие операции, как управление памятью, назначение регистров и оптимизация конкретных машин.

Таблица символов в некоторой степени представляет собой структуру данных, которая управляет идентификаторами вместе с соответствующими типами данных, которые она хранит. Обработчик ошибок обнаруживает, сообщает, исправляет ошибки, возникающие между различными фазами компилятора.

Определение переводчика

Интерпретатор является альтернативой для реализации языка программирования и выполняет ту же работу, что и компилятор. Интерпретатор выполняет лексирование, синтаксический анализ и проверку типов аналогично компилятору. Но интерпретатор обрабатывает синтаксическое дерево напрямую для доступа к выражениям и выполнения оператора, а не генерирует код из синтаксического дерева.

Интерпретатору может потребоваться обработка одного и того же синтаксического дерева более одного раза, поэтому интерпретация сравнительно медленнее, чем выполнение скомпилированной программы.

Компиляция и интерпретация, вероятно, объединены для реализации языка программирования. В котором компилятор генерирует код промежуточного уровня, тогда код интерпретируется, а не компилируется в машинный код.

Читайте также:  Zte fit что это

Использование переводчика выгодно при разработке программы, где наиболее важной частью является возможность быстрого тестирования модификации программы, а не ее эффективного выполнения.

Ключевые различия между компилятором и интерпретатором

Давайте посмотрим на основные различия между компилятором и интерпретатором.

  1. Компилятор берет программу целиком и переводит ее, а интерпретатор переводит оператор программы в оператор.
  2. Промежуточный код или целевой код генерируется в случае компилятора. В отличие от интерпретатора не создает промежуточный код.
  3. Компилятор сравнительно быстрее, чем Interpreter, поскольку компилятор берет всю программу за один раз, тогда как интерпретаторы компилируют каждую строку кода за другой.
  4. Компилятору требуется больше памяти, чем интерпретатору из-за генерации объектного кода.
  5. Компилятор представляет все ошибки одновременно, и трудно обнаружить ошибки в контрастном интерпретаторе, отображая ошибки каждого оператора одну за другой, и легче обнаружить ошибки.
  6. В компиляторе, когда в программе возникает ошибка, он останавливает ее перевод, и после устранения ошибки вся программа переводится снова. Напротив, когда в интерпретаторе возникает ошибка, она препятствует ее переводу, а после устранения ошибки перевод возобновляется.
  7. В компиляторе процесс требует двух шагов, в которых сначала выполняется перевод исходного кода в целевую программу, а затем выполнение. Находясь в интерпретаторе Это один шаг процесса, в котором исходный код компилируется и выполняется одновременно.
  8. Компилятор используется в таких языках программирования, как C, C ++, C #, Scala и т. Д. С другой стороны, Интерпретатор используется в таких языках, как Java, PHP, Ruby, Python и т. Д.

Заключение

И компилятор, и интерпретатор предназначены для выполнения одной и той же работы, но различаются по операционной процедуре, компилятор получает исходный код агрегированным образом, тогда как интерпретатор принимает составные части исходного кода, то есть оператор за оператором.

Хотя и компилятор, и интерпретатор имеют определенные преимущества и недостатки, такие как интерпретируемые языки рассматриваются как кроссплатформенные, то есть код переносимый. Он также не должен компилировать инструкции ранее, в отличие от компилятора, который экономит время. Скомпилированные языки быстрее в отношении процесса компиляции.

Но прежде чем говорить о том, как это всё работает, давайте разберём один простой пример. Представим, что у нас есть новый язык программирования (придумайте любое название). Язык довольно прост:

  • каждая строка представляет собой выражение,
  • каждое выражение состоит из команды (оператора)
  • и любого количества значений (операндов), которыми оперирует команда.

Пример:

set a 1
set b 2
add a b c
print c

Это простой язык, так что мы можем без опаски предположить, что этот код всего лишь выводит на экран 3. Оператор set берёт переменную и присваивает ей число (совсем как $a=1 в PHP). Оператор add берёт две переменные для добавления и сохраняет результат в третьей. Оператор print выводит её на экран.

Теперь давайте напишем программу, которая считывает каждое «выражение», находит оператор и операнды, а затем что-то с ними делает, в зависимости от конкретного оператора. Это довольно просто реализовать на PHP, как вы можете видеть на примере листинга 1.

Это очень простая программа, и вам не придётся писать своё следующее веб-приложение на вашем новом языке. Но данный пример помогает понять, как легко можно создать новый язык и получить программу, которая способна считывать и выполнять этот язык. В нашем случае она построчно считывает исходный файл и выполняет код в зависимости от текущего оператора. Для запуска приложения нам не нужно преобразовывать его в ассемблер или двоичный код, оно и так прекрасно работает. Этот метод выполнения программ называется интерпретированием. Например, таким образом часто выполняются программы на Basic: каждое выражение считывается и сразу же выполняется в высокоуровневом режиме.

Но тут есть ряд проблем. Одна из них заключается в том, что написать подобный языковой процессор довольно легко, а вот выполняться новый язык будет очень медленно. Ведь нам придётся обрабатывать каждую строку и проверять:

  • Какой оператор нужно выполнить?
  • Это правильный оператор?
  • Есть ли у него нужное количество операндов?

А ведь нам нельзя забывать и о других задачах. Например, оператор set может присваивать переменным только числовые значения или строковые тоже? Или даже значения других переменных? Чтобы правильно обработать каждое выражение, нужно ответить на все эти вопросы. Что произойдёт, если написать set 1 4? Короче, таким образом практически невозможно создавать быстро работающие приложения.

Но, несмотря на неторопливость, у интерпретирования есть преимущества: мы можем сразу запускать программу после каждого внесённого изменения. Для внимательных: когда я что-то меняю в PHP-скрипте, я сразу могу его выполнить и увидеть изменения; означает ли это, что PHP — интерпретируемый язык? На данный момент будем считать, что да. PHP-скрипт интерпретируется подобно нашему гипотетическому простому языку. Но в следующих разделах мы ещё к этому вернёмся!

Как можно заставить нашу программу «работать быстро»? Это можно сделать разными способами. Один из них, разработанный в Facebook, называется HipHop (я имею в виду «старую» систему HipHop, а не используемую сегодня HHVM). HipHop преобразовывал один язык (PHP) в другой (С++). Результат преобразования можно было с помощью компилятора С++ превратить в двоичный код. Его компьютер способен понять и выполнить без дополнительной нагрузки в виде интерпретатора. В результате экономится ОГРОМНОЕ количество вычислительных ресурсов и приложение работает гораздо быстрее.

Этот метод называется source-to-source компилированием, или транскомпилированием, или даже транспилированием (transpiling). На самом деле происходит не компилирование в двоичный код, а преобразование в то, что может быть скомпилировано в машинный код существующими компиляторами.

Транскомпилирование позволяет напрямую выполнять двоичный код, что повышает производительность. Однако у этого метода есть и обратная сторона: прежде чем выполнить код, нам сначала нужно провести транскомпилирование, а затем настоящее компилирование. Но это нужно делать только тогда, когда в приложение вносятся изменения, т. е. только во время разработки.

Транскомпилирование также используется для того, чтобы сделать «жёсткие» языки более простыми и динамичными. Например, браузеры не понимают код, написанный на LESS, SASS и SCSS. Но зато его можно транспилировать в CSS, который браузеры понимают. Поддерживать CSS проще, но приходится дополнительно транскомпилировать.

Чтобы всё работало ещё быстрее, нужно избавиться от стадии транскомпилирования. То есть компилировать наш язык сразу в двоичный код, который мог бы тут же выполняться, без дополнительной нагрузки в виде интерпретирования или транскомпилирования.

Читайте также:  Обход ограничений yota hosts

К сожалению, написание компилятора — одна из труднейших задач в информатике. Например, при компилировании в двоичный код нужно учитывать, на каком компьютере он будет выполняться: на 32-битной Linux, или 64-битной Windows, или вообще на OS X. Зато интерпретируемый скрипт может легко выполняться где угодно. Как и в PHP, нам не нужно переживать о том, где выполняется наш скрипт. Хотя может встречаться и код, предназначенный для конкретной ОС, что сделает невозможным выполнение скрипта на других системах, но это не вина интерпретатора.

Но даже если мы избавимся от стадии транскомпилирования, нам никуда не деться от компилирования. Например, большие программы, написанные на С (компилируемый язык), могут компилироваться чуть ли не час. Представьте, что вы написали приложение на PHP и вам нужно ждать ещё десять минут, прежде чем увидеть, работают ли внесённые изменения.

Если интерпретирование подразумевает медленное выполнение, а компилирование сложно в реализации и требует больше времени при разработке, то как работают языки вроде PHP, Python или Ruby? Они довольно быстрые!

Это потому, что они используют и интерпретирование, и компилирование. Давайте посмотрим, как это получается.

Что, если бы мы могли преобразовывать наш выдуманный язык не напрямую в двоичный код, а в нечто, очень на него похожее (это называется «байт-код»)? И если бы этот байт-код был так близок к тому, как работает компьютер, что его интерпретирование выполнялось бы очень быстро (например, миллионы байт-кодов в секунду)? Это сделало бы наше приложение почти таким же быстрым, как и компилируемое, при этом сохранились бы все преимущества интерпретируемых языков. Самое главное, нам не пришлось бы компилировать скрипты при каждом изменении.

Выглядит очень заманчиво. По сути, подобным образом работают многие языки — PHP, Ruby, Python и даже Java. Вместо считывания и поочерёдного интерпретирования строк исходного кода, в этих языках используется другой подход:

  • Шаг 1. Считать скрипт (PHP) целиком в память.
  • Шаг 2. Целиком преобразовать/компилировать скрипт в байт-код.
  • Шаг 3. Выполнить байт-код посредством интерпретатора (PHP).

На самом деле шагов больше, и в реальности весь процесс гораздо сложнее. Но в целом трёх описанных шагов достаточно для запуска скрипта из командной строки или для выполнения запроса через ваш веб-сервер.

Процесс можно легко оптимизировать: предположим, что мы запустили веб-сервер и каждый запрос выполняет скрипт index.php . Зачем каждый раз грузить его в память? Лучше закешировать файл, чтобы можно было быстро преобразовывать его при каждом запросе.

Ещё одна оптимизация: после генерирования байт-кода мы можем использовать его при всех последующих запросах. Так что можно закешировать и его (главное, убедитесь, что при изменении исходного файла байт-код будет перекомпилироваться). Именно это делают кеши кода операций (opcode caches), вроде расширения OPCache в PHP: кешируют скомпилированные скрипты, чтобы их можно было быстро выполнить при последующих запросах без избыточных загрузок и компилирования в байт-код.

Наконец, последний шаг к высокой скорости — выполнение байт-кода нашим PHP-интерпретатором. В следующей части мы сравним это с обычными интерпретаторами. Во избежание путаницы: подобный интерпретатор байт-кода часто называется «виртуальной машиной», потому что в определённой степени он копирует работу машины (компьютера). Не надо путать это с виртуальными машинами, запускаемыми на компьютерах, вроде VirtualBox или VMware. Речь идёт о таких вещах, как JVM (Java Virtual Machine) в мире Java и HHVM (HipHop Virtual Machine) в мире PHP. Свои виртуальные машины есть у Python и Ruby. В некотором роде все они являются высокоспециализированными и производительными интерпретаторами байт-кода.

Каждая ВМ выполняет собственный байт-код, генерируемый конкретным языком, и они несовместимы между собой. Вы не можете выполнять байт-код PHP на ВМ Python, и наоборот. Однако теоретически возможно создать программу, компилирующую PHP-скрипты в байт-код, который будет понятен ВМ Python. Так что в теории вы можете запускать PHP-скрипты в Python (серьёзный вызов!).

Как выглядит и работает байт-код? Рассмотрим два примера. Возьмём PHP-код:

Посмотреть его байт-код можно с помощью 3v4l.org или установив расширение VLD. Получим следующее:

Теперь возьмём аналогичный пример на Python:

Python может напрямую сгенерировать коды операций ©python:

У нас есть два простых скрипта и их байт-коды. Обратите внимание, что байт-коды похожи на язык, который мы «создали» в начале статьи: каждая строка представляет собой оператор с любым количеством операндов. В байт-коде PHP к переменным добавляется префикс !, поэтому !0 означает переменную 0. Байт-коду не важно, что вы используете переменную $a: в ходе компилирования имена переменных теряют значение и преобразуются в числа. Это облегчает и ускоряет их обработку виртуальной машиной. Большинство необходимых «проверок» выполняются на стадии компилирования, что также снимает нагрузку с виртуальной машины и увеличивает скорость её работы.

Поскольку байт-код состоит из простых инструкций, интерпретирование проходит очень быстро. Вместо тысяч двоичных инструкций, которые нужно обработать для каждого выражения интерпретируемого языка, в байт-коде на каждое выражение приходится по несколько сотен инструкций (иногда и того меньше). Поэтому виртуальные машины работают гораздо быстрее интерпретируемых языков.

Иными словами, виртуалки взяли всё лучшее от двух миров. Хотя нам по-прежнему нужно компилировать из исходного кода в байт-код, этот процесс становится быстрым и прозрачным. А после получения байт-кода виртуальная машина быстро и эффективно интерпретирует его без излишних накладных расходов. И в результате мы имеем высокопроизводительное приложение.

Теперь, когда мы умеем эффективно выполнять сгенерированный байт-код, остаётся задача компилирования исходного кода в этот байт-код.

Рассмотрим следующие PHP-выражения:

Все они одинаково верны и должны быть преобразованы в одинаковые байт-коды. Но как мы их считываем? Ведь в нашем собственном интерпретаторе мы парсим команды, разделяя их пробелами. Это означает, что программист должен писать код в одном стиле, в отличие от PHP, где вы можете в одной строке использовать отступления или пробелы, скобки в одной строке или переносить на вторую строку и т. д. В первую очередь компилятор попытается преобразовать ваш исходный код в токены. Этот процесс называется лексингом (lexing) или токенизацией.

Токенизация (лексинг) заключается в преобразовании исходного PHP-кода — без понимания его значения — в длинный список токенов. Это сложный процесс, но в PHP вы можете довольно легко сделать нечто подобное. Представленный в листинге 2 код выдаёт следующий результат:

Строковое значение преобразуется в токены:

    public abstract final final private class foo() <> может быть корректным, но не имеет смысла с точки зрения PHP. Токенизация и парсинг — хитрые процессы, и зачастую для их выполнения берут сторонние приложения. Нередко используются инструменты вроде flex и bison (в PHP тоже). Их можно рассматривать и в качестве транскомпиляторов: они преобразуют ваши правила в С-код, который будет автоматически компилироваться, когда вы компилируете PHP.
Читайте также:  Конвектор doc в fb2

Парсеры и токенизаторы полезны и в других сферах. Например, они используются для парсинга SQL-выражений в базах данных, и на PHP также написано немало парсеров и токенизаторов. У объектно-реляционного маппера Doctrine есть свой парсер для DQL-выражений, а также «транскомпилятор» для преобразования DQL в SQL. Многие движки шаблонов, в том числе Twig, используют собственные токенизаторы и парсеры для «компилирования» файлов шаблонов обратно в PHP-скрипты. По сути, эти движки тоже транскомпиляторы!

После токенизации и парсинга нашего языка мы можем генерировать байт-код. Вплоть до PHP 5.6 он генерировался во время парсинга. Но привычнее было бы добавить в процесс отдельную стадию: пусть парсер генерирует не байт-код, а так называемое абстрактное синтаксическое дерево (Abstract Syntax Tree, AST). Это древовидная структура, в которой абстрактно представлена вся программа. AST не только упрощает генерирование байт-кода, но и позволяет нам вносить изменения в дерево, прежде чем оно будет преобразовано. Дерево всегда генерируется особым образом. Узел дерева, представляющий собой выражение if, обязательно имеет под собой три элемента:

  • первый содержит условие (вроде $a == true );
  • второй содержит выражения, которые должны быть выполнены, если соблюдается условие true ;
  • третий содержит выражения, которые должны быть выполнены, если соблюдается условие false (выражение else ).

Даже если else отсутствует, элемента три, просто третий будет пустым.

В результате мы можем «переписать» программу до того, как она будет преобразована в байт-код. Иногда это используется для оптимизации кода. Если мы обнаружим, что разработчик раз за разом перевычислял переменную внутри цикла, и мы знаем, что переменная всегда имеет одно и то же значение, то оптимизатор может переписать AST так, чтобы создать временную переменную, которую не нужно каждый раз вычислять заново. Дерево можно использовать для небольшой реорганизации кода, чтобы он работал быстрее: удалить ненужные переменные и т. п. Это не всегда возможно, но когда у нас есть дерево всей программы, то такие проверки и оптимизации выполнять куда легче. Внутри AST можно посмотреть, объявляются ли переменные до их использования или используется ли присваивание в условном блоке ( if ($a = 1) <> ). И при обнаружении потенциально ошибочных структур выдать предупреждение. С помощью дерева можно даже анализировать код с точки зрения информационной безопасности и предупреждать пользователей во время выполнения скрипта.

Всё это называется статическим анализом — он позволяет создавать новые возможности, оптимизации и системы валидации, помогающие разработчикам писать гармоничный, безопасный и быстрый код.

В PHP 7.0 появился новый движок парсинга (Zend 3.0), который тоже генерирует AST во время парсинга. Поскольку он достаточно свежий, с его помощью можно сделать не так много. Но сам факт его наличия означает, что мы можем ожидать появления в ближайшем будущем самых разных возможностей. Функция token_get_all() уже принимает новую, недокументированную константу TOKEN_PARSE, которая в будущем может использоваться для возвращения не только токенов, но и отпарсенного AST. Сторонние расширения вроде php-ast позволяют просматривать и редактировать дерево прямо в PHP. Полная переработка движка Zend и реализации AST откроет PHP для самых разных новых задач.

Помимо виртуальных машин, выполняющих высокооптимизированный байт-код, сгенерированный из AST, есть и другая методика повышения скорости. Но это одна из самых сложных в реализации вещей.

Как выполняется приложение? Много времени тратится на его настройку: например, нужно запустить фреймворк, отпарсить маршруты, обработать переменные среды и т. д. По завершении всех этих процедур программа обычно всё ещё не запущена. По сути, куча времени потрачена лишь на функционирование какой-то части вашего приложения. А что, если мы выявим те части, которые могут часто запускаться и способны преобразовывать маленькие куски кода (допустим, всего несколько методов) в двоичный код? Конечно, на это компилирование может уходить относительно много времени, но всё равно метод компилируется куда быстрее, чем всё приложение. Возможно, при первом вызове функции вы столкнётесь с маленькой задержкой, но все последующие вызовы будут выполняться молниеносно, минуя виртуальную машину, и сразу в виде двоичного кода.

Мы получаем скорость компилируемого кода и наслаждаемся преимуществами кода интерпретируемого. Подобные системы могут работать быстрее обычного интерпретируемого байт-кода, иногда гораздо быстрее. Речь идёт о JIT-компиляторах (just-in-time, точно в срок). Название подходит как нельзя лучше. Система обнаруживает, какие части байт-кода могут быть хорошими кандидатами на компилирование в двоичный код, и делает это в тот момент, когда нужно выполнять эти самые части. То есть — точно в срок. Программа может стартовать немедленно, не нужно ждать завершения компилирования. В двоичный код преобразуются только самые эффективные части кода, так что процесс компилирования автоматизируется и ускоряется.

Хотя не все JIT-компиляторы работают таким образом. Некоторые компилируют все методы на лету; другие пытаются только определить, какие функции нужно скомпилировать на ранней стадии; третьи будут компилировать функции, если они вызываются два и больше раза. Но все JIT’ы используют один принцип: компилировать маленькие куски кода, когда они действительно нужны.

Ещё одно преимущество JIT’ов по сравнению с обычным компилированием заключается в том, что они способны лучше прогнозировать и оптимизировать на основании текущего состояния приложения. JIT’ы могут динамически анализировать код во время runtime и делать предположения, на которые неспособны обычные компиляторы. Ведь во время компиляции у нас нет информации о текущем состоянии программы, а JIT’ы компилируют на стадии выполнения.

Если вам доводилось работать с HHVM, то вы уже использовали JIT-компилятор: PHP-код (и надмножественный язык Hack) преобразуется в байт-код, запускаемый на виртуальной машине HHVM. Машина обнаруживает блоки, которые могут быть безопасно преобразованы в двоичный код; если это ещё не было сделано, она это делает и запускает их. По окончании запуска ВМ переходит к следующим байт-кодам, которые могут быть преобразованы в двоичный код.

PHP 7 не выполняется на JIT-компиляторе, но зато его новая система превосходит все предыдущие релизы. Сейчас во всех его компонентах проводятся эксперименты со статическим анализом, динамической оптимизацией, и даже есть простые JIT-системы. Так что не исключено, что однажды даже PHP 7 окажется позади!

Ссылка на основную публикацию
Чем мобильное приложение лучше сайта
Согласно последним данным, ежегодный прирост мобильной экономики составляет 10%, и уже около 20% всех продаж через ПК осуществляются после клика...
Футбольный менеджер без интернета
Да, уже четыре года назад Испания выиграла Евро 2012. С того времени много воды утекло и теперь у других команд...
Футбольный менеджер с реальными командами
Бесплатная онлайн игра. Только в нашем футбольном менеджере игры проходят в реальном времени и можно менять тактику непосредственно во время...
Чем можно заменить майл агент
Альтернативы Mail.Ru Агент Обзоры и новости о Mail.Ru Агент 2015. Mail.Ru Агент уступит место ICQ Оба популярных российских мессенджера Mail.ru...
Adblock detector