Что быстрее и чище: генерировать AST и повторять его или генерировать код?

Я написал интерпретатор на JavaScript для небольшого языка, используя jison, который является JS-портом bison. Язык используется для оценки выражений и условий. Сейчас оценка смешана с разбором.

Я пытаюсь его оптимизировать, а узким местом является лексер и парсер. Поэтому я решил разобрать его заранее и оценить только во время выполнения.

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


person Farid Nouri Neshat    schedule 27.11.2012    source источник
comment
eval = вызов компилятора = дорого.   -  person John Dvorak    schedule 27.11.2012
comment
Похоже, вы, по сути, задаетесь вопросом, быстрее ли скомпилированный или интерпретированный код. Скомпилированный код почти всегда будет быстрее, но он может вызвать больше головной боли, чем интерпретируемый.   -  person Bubbles    schedule 27.11.2012
comment
@JanDvorak Ну, во-первых, все это происходит на одном nodejs, поэтому у меня много времени для запуска. Я вызываю eval перед тем, как проанализировать его при запуске, а затем запускаю полученную функцию во время выполнения.   -  person Farid Nouri Neshat    schedule 27.11.2012
comment
@Bubbles Я пытаюсь сэкономить как головную боль, так и циклы процессора. Но обратите внимание, что я генерирую javascript, а не машинный код.   -  person Farid Nouri Neshat    schedule 27.11.2012
comment
Я бы не беспокоился о каких-либо задержках, которые случаются только один раз на сервере.   -  person John Dvorak    schedule 27.11.2012


Ответы (1)


В общем*, быстрее всегда будет генерировать что-то, что ближе всего к машинному коду. В вашем случае создание javascript будет быстрее.

Сгенерированный код javascript будет выполняться непосредственно базовым интерпретатором C/C++ (а в некоторых случаях скомпилирован JIT в машинный код). Напротив, написание собственной виртуальной машины на javascript для выполнения AST будет работать на дополнительном уровне виртуальной машины — javascript.

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

person slebetman    schedule 27.11.2012
comment
Если ваше время компиляции велико, интерпретатор может быть быстрее, даже если он закодирован наивным образом. Компромисс прост: время компиляции + время выполнения (скомпилированная программа) против времени интерпретации. Выберите тот, который чаще всего выигрывает в ваших обстоятельствах, если у вас есть энергия для создания компилятора. - person Ira Baxter; 27.11.2012
comment
@IraBaxter: время компиляции происходит один раз. Так что даже если это дольше, это победа. Кроме того, независимо от того, интерпретируется он или нет, в этом случае он компилируется (ОП упомянул, что он компилирует в AST). Самое сложное — это получить AST. Генерация инструкций из AST тривиальна (на самом деле, это достаточно быстро, чтобы обычно можно было напрямую интерпретировать AST без создания каких-либо исполняемых выходных данных). - person slebetman; 27.11.2012