Вызовы функций в производительности уничтожения виртуальной машины - PullRequest
4 голосов
/ 17 января 2011

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

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

Ответы [ 2 ]

5 голосов
/ 17 января 2011

Вот несколько вариантов уменьшения накладных расходов:

  1. Объявите функции как fastcall (или что-то подобное), чтобы уменьшить накладные расходы при передаче аргумента
  2. Используйте большой регистр переключателей вместо таблицы указателей функций (компилятор оптимизирует под таблицу переходов, и вы уберете лишние затраты на фактический вызов функции)
  3. Скопируйте весь код для процедуры VM в одно место, чтобы она могла выполняться последовательно, а не возвращаться к интерпретатору после каждой инструкции.

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

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

Есть много хороших техник, которые вы могли бы рассмотреть. Вот два из них, с которыми я знаком:

  1. Встроенное кэширование - По сути, поиск вызываемых объектов, переключение с поиска в vtable на простое добавление набора операторов if, которые отправляются в статически известное местоположение. Этот метод был очень полезен в языке Self и является одной из основных оптимизаций JVM.

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

Надеюсь, это поможет!

...