Вопрос

Я читал о плюсах и минусах интерпретируемых языков, и одним из наиболее распространенных минусов является медлительность, но почему программы на интерпретируемых языках медленные?

Это было полезно?

Решение

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

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

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

Обратите внимание, что то, что я описываю выше, предназначено для случаев, когда язык выполняется в интерпретаторе.Существуют интерпретаторы для многих языков, для которых также существуют собственные компоновщики, создающие собственные машинные инструкции.Уменьшение скорости (каким бы размером оно ни было) применяется только к интерпретируемому контексту.

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

C # не является интерпретируемым языком, даже несмотря на то, что он использует промежуточный язык (IL), он настраивается в собственные инструкции перед выполнением, поэтому он имеет некоторые с таким же снижением скорости, но не полностью, но я бы поспорил, что если бы вы создали полноценный интерпретатор для C # или C ++, он также работал бы медленнее.

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

Другие советы

Похоже, что во всех ответах здесь упускается по-настоящему важный момент.Это деталь того, как реализуется "интерпретируемый" код.

Интерпретируемые скриптовые языки работают медленнее, поскольку их модель пространства методов, объектов и глобальных переменных является динамической.На мой взгляд, это реальное определение скриптового языка, а не факт, что он интерпретируется.Это требует множества дополнительных поисков в хэш-таблице при каждом обращении к переменной или вызове метода.И это главная причина, по которой все они ужасны в многопоточности и использовании GIL (глобальная блокировка интерпретатора).На этот поиск тратится большая часть времени.Это болезненный случайный поиск в памяти, который действительно причиняет боль, когда вы получаете промах в кэше L1 / L2.

Javascript Core8 от Google работает очень быстро и ориентирован почти на скорость C для простой оптимизации:они принимают объектную модель данных как фиксированную и создают внутренний код для доступа к ней, подобный структуре данных собственной скомпилированной программы.Когда добавляется или удаляется новая переменная или метод, весь скомпилированный код отбрасывается и компилируется снова.

Этот метод хорошо объяснен в статье Дойча / Шиффмана "Эффективная реализация системы Smalltalk-80".

На вопрос, почему php, python и ruby этого не делают, ответить довольно просто:этот метод чрезвычайно сложен в реализации.

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

Думайте о interpeter как об эмуляторе для машины, которой у вас случайно нет

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

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

Очевидно, что это осложняется компиляторами JIT (Just In Time), которые есть в Java, C # и других.Теоретически они так же хороши, как компиляторы "AOT" ("За один раз"), но на практике эти языки работают медленнее и ограничены необходимостью использования компилятором памяти и времени во время выполнения программы.Но если вы скажете что-нибудь из этого здесь, на SO, будьте готовы привлечь ярых защитников JIT, которые настаивают на том, что теоретической разницы между JIT и AOT нет.Если вы спросите их, так ли быстры Java и C #, как C и C ++, то они начнут оправдываться и вроде как немного успокоятся.:-)

Таким образом, C ++ полностью правит в играх, где всегда можно использовать максимальный объем доступных вычислений.

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

Это хороший вопрос, но, на мой взгляд, его следует сформулировать немного иначе, например:"Почему интерпретируемые языки работают медленнее, чем скомпилированные языки?"

Я думаю, что это распространенное заблуждение, что интерпретируемые языки сами по себе медленные.Интерпретируемые языки - это не медленный, но, в зависимости от варианта использования, может быть медленнее чем скомпилированная версия.В большинстве случаев интерпретируемые языки на самом деле достаточно быстро!

"Достаточно быстро", плюс увеличение производительности от использования такого языка, как Python, по сравнению, например, с C, должно быть достаточным основанием для рассмотрения интерпретируемого языка.Кроме того, вы всегда можете заменить определенные части вашей интерпретируемой программы быстрой реализацией на языке Си, если вам действительно нужна скорость.Но опять же, сначала измерьте и определите, действительно ли проблема в скорости, а затем оптимизируйте.

Цикл выполняется 100 раз, содержимое цикла интерпретируется 100 раз в низкоуровневый код.

Не кэшируется, не используется повторно, не оптимизируется.

Проще говоря, компилятор интерпретирует один раз низкоуровневый код

Редактировать, после комментариев:

  • JIT - это скомпилированный код, не интерпретируется.Это просто скомпилировано позже, а не заранее
  • Я имею в виду классическое определение, а не современные практические реализации

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

Простой вопрос, без какого-либо реального простого ответа.Суть в том, что все компьютеры действительно "понимают" именно двоичные инструкции, в которые компилируются "быстрые" языки, такие как C .

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

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

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

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

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

От about.com:

Интерпретируемый язык обрабатывается во время выполнения.Каждая строка считывается, анализируется и выполняется.Необходимость каждый раз повторно обрабатывать строку в цикле вот что делает интерпретируемые языки такими медленными.Эти накладные расходы означают, что интерпретируемый код выполняется в 5-10 раз медленнее, чем скомпилированный код. Интерпретируемые языки, такие как Basic или JavaScript, являются самыми медленными.Их преимущество в том, что их не нужно перекомпилировать после внесения изменений, и это удобно, когда вы учитесь программировать.

Однако замедление в 5-10 раз не обязательно верно для таких языков, как Java и C #.Они интерпретируются, но компиляторы "точно в срок" может генерировать инструкции машинного языка для некоторых операций, значительно ускоряя процесс (в разы приближаясь к скорости скомпилированного языка).

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

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

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

Читать это Плюсы И Минусы интерпретируемых языков

Это идея, содержащаяся в этом посте, имеет отношение к вашей проблеме.

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

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

Обновить:нет, я не видел, чтобы мой ответ в какой-то степени совпадал с общепринятым ;-)

Да, интерпретируемые языки работают медленно...

Однако учтите следующее.Мне нужно было решить проблему.Мне потребовалось 4 минуты, чтобы решить проблему на Python, а запуск программы занял 0,15 секунды.Затем я попытался написать это на C, и я получил время выполнения 0,12 секунды, и мне потребовался 1 час, чтобы написать это.Все это потому, что практическим способом решения рассматриваемой проблемы было использование хэш-таблиц, а хэш-таблица в любом случае доминировала во время выполнения.

В Википедии говорится,

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

Обратитесь к этому Документ IBM,

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top