Как можно интерпретировать код даже мало эффективен? (теоретический)

StackOverflow https://stackoverflow.com/questions/3630867

Вопрос

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

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

Давайте вернемся к дням, когда не было компиляторов джита. У Java есть виртуальная машина, которая в основном это оборудование. Вы пишете код, чем он скомпилирован в Bytecode для принятия хотя бы некоторой работы с виртуальной машины, это нормально. Но учитывая, насколько сложным даже набор инструкций RISC может находиться в оборудовании, я даже не могу думать о способе сделать это на программном обеспечении оборудования.

У меня нет опыта, написав виртуальные машины, поэтому я не знаю, как это сделано на самом эффектельном уровне, но я не могу придумать ничего более эффектно, чем тестирование каждой инструкции для матча ADN, чем подходящие действия. Вы знаете, что-то вроде: if(instruction=="something") { (do it) } else if(instruction=="something_diffrent"){ (do it) }и т.д....

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

И еще даже целые платформы основаны на Java. Например, Android. И первые версицы Android не имели JIT Compiter. Они были интерпретированы. Но не должно быть Android ужасно медленным? И все же это не так. Я знаю, когда вы называете некоторую функцию API, с библиотеки Android, они написаны в машинном коде, поэтому они эффективны, так что это много помогает.

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

А теперь некоторые примеры, как я обещал. Так как я в основном работаю с MCU, я нашел JVM для ATMEL AVR MCU. Состояние Thay, что 8 МГц MCU может сделать 20K Java Optcodes в секунду. Но поскольку AVR может выполнять большинство инструкций в один или два цикла, позволяет сказать 6000000 инструкции в среднем. Это дает нам, что JVM без JIT Compiler в 300 раз медленнее в машинном коде. Так зачем стать Java так популярным без JIT Compiler? Не так слишком плохой потери производительности? Я просто не могу понять это. Спасибо.

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

Решение

У нас был код байта в течение длительного времени. На старом Apple II P-System USCD была очень популярна, что скомпилировало Pascal в байтовый код, который будет интерпретировать 8-битный 6502, который может работать на 2 МГц. Эти программы работали достаточно быстро.

Переводчик байткода, как правило, основан на столе прыжка, а не цепочка if/then/else заявления. В C или C ++, это будет включать в себя switch утверждение. Принципиально переводчик будет иметь эквивалент массива кода обработки и использовать OPCode в инструкции по байтому коду как индекс массива.

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

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

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

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

Но не должно быть, андроид ужасно медленным?

Определите «ужасно медленно». Это телефон. Он должен обрабатывать «наберите первую цифру», прежде чем набрать вторую цифру.

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

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

Помните, когда был введен Java, он был продан в качестве языка веб-апплета (замена и теперь заменены JavaScript - который также интерпретируется). Это было только после составления JIT Compilation, что он стал популярным на серверах.

Переводчики к байтекоде могут быть быстрее, что линия IF () S с помощью таблицы прыжка:

 void (*jmp_tbl)[256] = ...;  /* array of function pointers */
 byte op = *program_counter++;
 jmp_tbl[op]();

Есть два разных способа подойти к этому вопросу.

(i) "Почему это нормально запустить медленный код"

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

(ii) «Почему интерпретируемый код INNEFICE»

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

Но вы можете оптимизировать, что: например, вместо того, чтобы смотреть на единую инструкцию JVM, вы можете посмотреть на их последовательность и искать шаблоны, для которых у вас есть более эффективные интерпретации. Sun's JVM на самом деле делает некоторые из этих оптимизаций в самом переводчике. В предыдущей работе парень потребовал некоторое время для оптимизации интерпретатора, и интерпретировал Java Bytecode заметно быстрее после его изменений.

Но в современных JVMS, которые содержат JIT Compiler, переводчик - это просто ступенька, пока Jit не делает свою работу, поэтому люди действительно не тратят столько времени оптимизации переводчика.

12 МГц будет навязчивым, который является 8-битным микропроцессором. Это означает (например), что нативное «добавить» инструкцию может добавлять только два 8-битных числа вместе, чтобы получить 9-битный результат. JVM в основном является виртуальным 32-битным процессором. Это означает, что его командная инструкция добавляет два 32- Битовые номера вместе, чтобы получить 33-битный результат.

Таким образом, когда вы сравниваете ставки по эксплуатации, вы должны ожидать сокращения эксплуатации 4: 1 в качестве абсолютного минимума. На самом деле, хотя легко имитировать 32-битное добавление с 4 8-битными добавлениями (с помощью носителей), некоторые вещи не масштабируются вполне такие. Просто например, согласно собственной атмосфере Приложение Примечание, умножение 16x16, создаваемое 32-битным результатом, выполняется в ~ 218 часов. Такое же приложение примечание показывает 16/16 битовое разделение (создание 8-битного результата), работающего в 255 циклах.

Предполагая, что эти масштабы линейно, мы можем ожидать, что 32-разрядные версии умножения, чтобы взять ~ 425-450 часов часов, а циклы разделения ~ 510. На самом деле, мы, вероятно, должны ожидать немного накладных расходов, что еще больше уменьшит скорость, добавив не менее 10% к тем оценкам, вероятно, делает их более реалистичными.

Итог: Когда вы сравниваете яблоки к яблокам, становится очевидно, что в целом много разницы скорости, которую вы разговариваете, вообще не реально (или в любом случае не относятся к устройству JVM).

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