Что такое виртуальная машина и зачем она нужна динамическим языкам? - PullRequest
22 голосов
/ 09 января 2011

Так, например, у Python и Java есть виртуальная машина, а у C и Haskell нет.(Поправьте меня, если я ошибаюсь)

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

Ответы [ 8 ]

27 голосов
/ 09 января 2011

Это не имеет ничего общего со статическим и динамическим.

Скорее, речь идет о независимости от базовой аппаратной платформы («построить один раз, запустить везде» - в теории ...)

На самом деле, это не имеет ничего общего с языком.Можно написать компилятор C, который генерирует байт-код для JVM.Можно написать компилятор Java, который генерирует машинный код x86.

18 голосов
/ 11 января 2011

Давайте на секунду забудем о виртуальных машинах (я обещаю, что вернемся к тем, что ниже) и начнем с этого важного факта:

C не имеет сборки мусора.

Для языка, обеспечивающего сборку мусора, должна быть какая-то "среда выполнения" / среда выполнения / вещь, которая будет выполнять это.

Вот почему Python, Java и Haskell требуют "runtime" , а C, который не делает этого, может просто скомпилировать нативный код.

Обратите внимание, что psyco был оптимизатором Python, который компилировал код Python в машинный код, однако большая часть этого машинного кода состояла из вызовов функций времени выполнения C-Python, таких как PyImport_AddModule, PyImport_GetModuleDict и т. д.

Haskell / GHC находится в лодке, похожей на психо-скомпилированный Python. Int добавляются как простые машинные инструкции, но более сложные вещи, которые распределяют объекты и т. Д., Вызывают среду выполнения.

Что еще?

C не имеет "исключений"

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

Если мы затем добавим также «замыкания», будет добавлено больше материала.

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

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

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

Вот идея (кстати, назовем эту идею «Виртуальная машина»).

Давайте представим ваш код Python, например:

def has_no_letters(text):
  return text.upper() == text.lower()

В качестве структуры данных в памяти, например:

{ 'func_name': 'has_no_letters',
  'num_args': 1,
  'kwargs': [],
  'codez': [
    ('get_attr', 'tmp_a', 'arg_0', 'upper'),  # tmp_a = arg_0.upper
    ('func_call', 'tmp_b', 'tmp_a', []),  # tmp_b = tmp_a() # tmp_b = arg_0.upper()
    ('get_attr', 'tmp_c', 'arg_0', 'lower'),
    ('func_call', 'tmp_d', 'tmp_c', []),
    ('get_global', 'tmp_e', '=='),
    ('func_call', 'tmp_f', 'tmp_e', ['tmp_b', 'tmp_d']),
    ('return', 'tmp_f'),
  ]
}

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

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

Преимущества виртуальных машин перед прямыми текстовыми интерпретаторами

  • Система VM выдает все синтаксические ошибки перед выполнением кода.
  • При оценке цикла система ВМ не анализирует исходный код при каждом запуске.
    • Создание виртуальной машины быстрее, чем прямой текстовый интерпретатор.
    • Таким образом, прямой интерпретатор работает медленнее с длинными именами переменных и быстрее с короткими именами переменных. Это побуждает людей писать дурацкий математический код, такой как wt(f, d(o, e), s) <= th(i, s) + cr(a, p * d + o)

Преимущества виртуальных машин перед компиляцией в машинный код

  • Структура данных в памяти, описывающая программу, или «код ВМ», вероятно, будет гораздо более компактной, чем машинный код, полный шаблонного кода, который снова и снова делает то же самое для каждой исходной строки кода. Это заставит систему виртуальной машины работать быстрее, так как из памяти потребуется меньше «инструкций».
  • Создание виртуальной машины гораздо проще, чем создание компилятора для машинного кода. Возможно, вы можете сделать это сейчас, даже не зная никакой сборки / машинного кода.
4 голосов
/ 09 января 2011

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

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

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

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

Это имеет некоторые преимущества:

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

Существует также фактор крутизны: Смотри, Ма явиртуальная машина :).

3 голосов
/ 09 января 2011

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

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

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

Интерпретатор (ВМ) и компилятор могут быть отдельными программами (например, java и javac), или они могут быть только одной программой (например, с Ruby или Python).

3 голосов
/ 09 января 2011

Из записи в википедии на Виртуальные машины :

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

Самым большим преимуществом виртуальных машин является теоретическая переносимость кода - " пиши один раз, беги куда угодно "

Вероятно, самый известный пример виртуальной машины - это JVM , изначально предназначенный для запуска кода Java, но теперь все чаще используется для языков, таких как Clojure и Scala.

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

2 голосов
/ 10 января 2011

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

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

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

Для финала добавьте JIT.

2 голосов
/ 09 января 2011

Java и python могут быть скомпилированы таким образом, чтобы поддерживать независимость от платформы.Это верно даже для C #.Преимущества состоят в том, что виртуальные машины могут преобразовывать этот в основном строго типизированный байт-код в очень хороший код, специфичный для платформы, с относительными низкими издержками.Поскольку Java предназначена для «сборки один раз - запускается где угодно», JVM была создана.

2 голосов
/ 09 января 2011

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

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

...