Что делает программа интерпретатор

Сейчас очень популярны интерпретируемые языки — Java, Python, php, JS. Рассмотрим, что из себя представляет интерпретатор на примере JVM (виртуальной машины Java), однако, описанное ниже справедливо и для других нормальных интерпретируемых языков. Это вводная статья, дальше отдельные компоненты будут рассмотрены более подробно. Эти знания могут помочь вам оптимизировать работу своих программ, например как эти ребята [1] — по ссылке описано как некий тяжелый проект на Java был успешно оптимизирован под слабое железо.

Основы

Начинающий программист представляет себе работу интерпретатора примерно так:

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

КАК РАБОТАЕТ ИНТЕРПРЕТАТОР PYTHON (CPython)

Чуть более опытный программист исследовал файлы, которые порождает JVM при исполнении программы и знает, что JVM исполняет не исходный код программы, а байт-код, представляющий собой аналог ассемблера для виртуального Java-процессора. Байт-код генерируется загрузчиком классов и помещается в файлы с расширением .class . Загрузка классов выполняется динамически, то есть когда виртуальная машина, сталкивается с неизвестным ей (не загруженным) классом — она обращается к загрузчику. Очень хорошо информация о байт-коде представлена в статье Java Bytecode Fundamentals [2].

Эффективность

Обычно программисту не нужно разбираться в байт-коде, да и с загрузчиком проблем особых не возникает. Однако надо знать, что интерпретатор Java очень медленный, имеет стековую архитектуру (сильно отличается от вашего центрального процессора) и это сильно ослабляет эффект от распараллеливания ваших программ. Почему при этом Java-программы работают достаточно быстро? — Эффективность обеспечивают компилятор времени исполнения (Just-In-Time, JIT) и динамический профилировщик.

JIT-компилятор принимает байт-код и генерирует машинный код, который исполняется не виртуальным процессором, а реальным. За счет JIT ваши программы на Java/Python могут (теоретически) выполняться также быстро, как написанные на С++. По сути, JIT выполняет ту же работу что и компилятор C++, но делает это прямо во время выполнения программы и не для всей программы, а для так называемого Common path (основного пути исполнения). Отсюда растут ноги многих статей, показывающих, что Java-программа работает также быстро как на С++.

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

В языках типа C++ профилирование кода тоже выполняется перед компиляцией, но делают это не все программисты. Для этого программа запускается на некоторых эталонных наборах данных и собирается статистика ее выполнения. Затем, эта статистика передается оптимизатору кода. Например, если небольшая функция вызывается внутри цикла — то ее есть смысл инлайнить (подставить тело функции вместо ее вызова), если же она почти никогда не вызывается — то смысла в этом нет.

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

  • программа на С++ не оптимизировалась вообще или не выполнялось профилирование. Так, например, инлайнить обычно надо не более 5% функций, однако чтобы найти эти функции — нужно выполнить профилирование. Многие из читающих эту статью программистов выполняют профилирование своего кода? — Думаю не более 1%.
  • программа на С++ профилировалась на одних данных, а работает — на совершенно других. В видео [3] рассказывается как с этим столкнулась и боролась команда Яндекс.Браузер (оказалось, что пользователи работают с браузером не так как планировали разработчики);
  • программа оптимизирована под одно железо, а запущена на совершенно другом.
Читайте также:
Как поменять цвет глаз программа

По приведенным выше причинам, программы на интерпретируемых языках могут иметь сносную (на фоне компилируемых) производительность. Если на этом этапе вам уже кажется что ничего такого в вашем любимом JavaScript/Python нету — посмотрите вот эту статью [4], также можно найти научные изыскания вплоть до автоматического распараллеливания программ на JS [5].

Программист может указать какой JIT использовать, например JVM HotSpot поставляется в двух вариантах — клиент и сервер, основное их отличие типе JIT-компилятора и наборе оптимизаций. При запуске виртуальной машины вы можете передать опцию -client или -server .

Работа с памятью

Почти все знают, что языки типа Java/Python очень удобные, т.к. автоматизируют сборку мусора. Это значит, что если вы выделите память под объект (например, массив), а затем этот объект станет вам не нужен — то виртуальная машина сама освободит память. Например, в следующей программе при вызове функции say создается новый объект text , который после завершения работы функции становится недоступен — это и есть мусор. В языке C++ такие объекты уничтожаются в момент выхода из функции, а в Java, Python и многих других интерпретируемых языках — они живут до тех пор, пока свободная память не кончится:

public class Main < public static void say(String name) < String text = «hello » + name; System.out.println(text); >public static void main(String[] args) < say(«Bob»); >>

Опытный программист знает что существуют различные типы сборщиков и запуская программу можно указать какой тип сборщика использовать.

Система управления памятью занимается не только сборкой мусора, но также:

  • выделением памяти — так, чтобы избежать фрагментации;
  • запросом новых страниц памяти у операционной системы и возвратом освобожденных;
  • обнаружением мусора (объектов, которые можно удалить). При этом используется анализ доступности (подсчет ссылок в многопоточной среде не работает).

Вся эта дополнительная работа выполняется неявно в момент выполнения вашей программы и, естественно, тормозит. Обычно для сборки памяти необходима полная остановка вашей программы (всех потоков), поэтому когда память кончится — программа «зависнет» пока не закончит сборку. Память требуется не только для объектов в вашей программе, но и для работы самой JVM, в частности, объектами являются и потребляют память: загруженные классы; код, скомпилированный с помощью JIT; оптимизированный код.

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

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

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

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

String bad = new String(«Slower»); String good = «Faster»;

Дополнительная литература по теме:

  1. Тюнинг JVM на примере одного проекта. URL: https://habr.com/en/company/luxoft/blog/174231/
  2. Java Bytecode Fundamentals. URL: https://habr.com/ru/post/111456/
  3. PGO: уход и кормление. URL: https://vk.com/for_programmer?w=wall-105242702_801
  4. Как работает JS: о внутреннем устройстве V8 и оптимизации кода. URL: https://habr.com/ru/company/ruvds/blog/337460/
  5. Martinsen, J. K., Grahn, H. (2010). An alternative optimization technique for JavaScript engines. Presented at the Third Swedish Workshop on Multi-Core Computing (MCC-10), Göteborg: Chalmers University of Technology. Retrieved from http://urn.kb.se/resolve?urn=urn:nbn:se:bth-7688
  6. Введение в технологии виртуализации.
Читайте также:
Программа для учета сервиса по ремонту автомобилей

Источник: pro-prof.com

Различия интерпретатора и компилятора: что выбрать

Программирование

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

Различия интерпретатора и компилятора: что выбрать

Существует огромное множество языков программирования, которые можно выбирать по целой группе параметров. Один из них – уровень. Именно с этим критерием будет связанна данная статья. Выделяют 2 типа языков программирования.

Низкоуровневые

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

Различия интерпретатора и компилятора: что выбрать

На таких ЯП пишут драйвера, операционные системы и всевозможные технические программы, необходимые для работы компьютера. Это, например, языки семейства Ассемблер и C. Из их свойств следуют преимущества и недостатки:

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

Высокоуровневые

Абстрактные языки, по своему строению похожи на человеческие.

На них разрабатывают разнообразные программы, начиная с игр и фоторедакторов, заканчивая нейросетями и обработчиками данных.

Различия интерпретатора и компилятора: что выбрать

Это всем знакомые Python, C++, C#, Java, PHP и многие другие ЯП. Они обладают как плюсами, так и минусами:

  • Объемность – программы на этих языках занимают много места в памяти, да и по скорости уступают предыдущим.
  • Портативность – работать с языками такого рода можно на почти любом компьютере. Написанные на них скрипты не связаны одной моделью процессора, и, зачастую, ограничены только операционной системой (Linux, macOS, Windows).
  • Понятность – высокоуровневые ЯП состоят из слов английского языка, их изучение намного проще.

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

Что такое компилятор в программировании

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

Различия интерпретатора и компилятора: что выбрать

Структура

Работа первых компиляторов обычно состояла из двух этапов:

  • Компиляция – сам транслятор кода;
  • Компоновка – процесс собирания переведенного кода в исполняемый файл.

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

Результат работы

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

Байт код

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

Различия интерпретатора и компилятора: что выбрать

Такой подход помогает создать много платформенный компилятор. Так, например, если результатом работы является машинный код, то для каждой операционной системы или семейства процессоров нужен новый транслятор. В то время как байт код можно запустить на разных платформах, или же в виртуальной машине, которая предусмотрена для того или иного языка. Но у этого есть свой недостаток – потеря скорости и производительности.

Читайте также:
Не работает программа maxima

Интерпретатор

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

Типы

Обычный

Механизм его работы был описан выше. Он просто переводит и сразу выполняет команды по строкам и продолжает, если нет ошибок или каких-либо помех.

Компилирующего типа

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

Различия интерпретатора и компилятора: что выбрать

Чем же всё-таки различаются компиляторы и интерпретаторы?

Перед началом сравнения стоит более подробно изучить объекты, которые мы будет сравнивать.

Сильные и слабые стороны:

Преимущества компилятора:

  • Быстрота – пожалуй, самый основной плюс. Сначала код переводится в понятный машине вид, а уже после ее можно выполнить. Также прибавку к скорости дает тот факт, что перед исполнением вся программа проходит проверку на ошибки, и соответственно, программист не будет ждать пол часа, чтобы обнаружить пропущенную запятую в середине программы.
  • Надёжность – результат работы компилятора не зависит от исходного скрипта, поэтому у неаккуратного пользователя будет меньше шансов его испортить. Да и работа злоумышленников в таком случае значительно затруднена.
  • Кроссплатформенность – после компиляции можно получить выполняемую программу, например exe файл, распространение которого между операционными системами не составит труда.

Недостатки компилятора:

  • Объем — во время компиляции переводится вся программа, поэтому выходной файл выходит большим.
  • Точность – для того, чтобы компилировать программу, в ней не должно быть ошибок, что может быть проблематично, если вы хотите проверить только ее часть.

Преимущества интерпретатора:

  • Простота отладки – интерпретатор позволяет довольно легко устранять ошибки из скрипта. Ведь он выполняет код по строкам, и остановится, если в проверяемой строке ошибка, тем самым указав на нее.
  • Компактность – интерпретатор занимает намного меньше места в памяти компьютера.

Недостатки интерпретатора:

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

Компилятор и интерпретатор отличия

Различия интерпретатора и компилятора: что выбрать

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

Интерпретируемые:

Компилируемые:

Компилируемые в байт код:

Также важен уровень мастерства программиста. Для новичка скорее подойдет интерпретатор, ведь на нем намного легче искать ошибки. Для профессионала же важнее скорость, поэтому ему лучше выбрать компилятор.

Похожие записи:

  1. Что такое язык программирования: виды и востребованность в 2023 году
  2. Программирование на Андроид в 2023 году: как используется, приложения, какой язык выбрать
  3. Что такое компилируемые и интерпретируемые языки
  4. Тимлид: кто это, как им стать в 2023 году, обязанности, достоинства и недостатки, зарплата
  5. Фреймворк в 2023 году: что это такое, как работает, особенности
  6. DevOps инженер в 2023 году: кто такой, обязанности, как стать с нуля
  7. Игры для программистов в 2023 году – Топ 15 лучших
  8. Что такое frontend- и backend-разработка и как стать специалистом в этой области
  9. Хакатоны в 2023 году: что это такое, зачем нужны, бонусы, как готовиться
  10. Кто такой Тестировщик программного обеспечения в 2023 году – QA специалист и как им стать

Источник: itstan.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru