Рассмотрим следующий метод в классе Juicer
:
Juicer >> juiceOf: aString
| fruit juice |
fruit := self gather: aString.
juice := self extractJuiceFrom: fruit.
^juice withoutSeeds
Он генерирует следующие байт-коды
25 self ; 1
26 pushTemp: 0 ; 2
27 send: gather:
28 popIntoTemp: 1 ; 3
29 self ; 4
30 pushTemp: 1 ; 5
31 send: extractJuiceFrom:
32 popIntoTemp: 2 ; 6 <-
33 pushTemp: 2 ; 7 <-
34 send: withoutSeeds
35 returnTop
Теперь обратите внимание, что 32 и 33 отменят:
25 self ; 1
26 pushTemp: 0 ; 2
27 send: gather:
28 popIntoTemp: 1 ; 3 *
29 self ; 4 *
30 pushTemp: 1 ; 5 *
31 send: extractJuiceFrom:
32 storeIntoTemp: 2 ; 6 <-
33 send: withoutSeeds
34 returnTop
Далее рассмотрим 28, 29 и 30. Они вставляют self
ниже результата gather
. Такая же конфигурация стека могла быть достигнута путем нажатия self
перед отправкой первого сообщения:
25 self ; 1 <-
26 self ; 2
27 pushTemp: 0 ; 3
28 send: gather:
29 popIntoTemp: 1 ; 4 <-
30 pushTemp: 1 ; 5 <-
31 send: extractJuiceFrom:
32 storeIntoTemp: 2 ; 6
33 send: withoutSeeds
34 returnTop
Теперь отмените 29 и 30
25 self ; 1
26 self ; 2
27 pushTemp: 0 ; 3
28 send: gather:
29 storeIntoTemp: 1 ; 4 <-
30 send: extractJuiceFrom:
31 storeIntoTemp: 2 ; 5
32 send: withoutSeeds
33 returnTop
Времена 1 и 2 записываются, но не читаются. Таким образом, кроме случаев отладки, их можно было пропустить, чтобы:
25 self ; 1
26 self ; 2
27 pushTemp: 0 ; 3
28 send: gather:
29 send: extractJuiceFrom:
30 send: withoutSeeds
31 returnTop
Эта последняя версия, которая сохраняет 4 из 7 операций стека, соответствует менее выразительному и понятному источнику:
Juicer >> juiceOf: aString
^(self extractJuiceFrom: (self gather: aString)) withoutSeeds
Обратите также внимание на то, что существуют другие возможные оптимизации, которые Pharo (я не проверил Squeak) не реализует (например, цепочку переходов). Эти оптимизации будут побуждать программиста Smalltalk лучше выражать свои намерения, не оплачивая стоимость дополнительные вычисления.
Мой вопрос заключается в том, являются ли эти улучшения иллюзией или нет. Конкретно, оптимизация байт-кода отсутствует у Pharo/Squeak, поскольку они, как известно, мало релевантны или считаются полезными, но еще не были адресованы?
ИЗМЕНИТЬ
Интересное преимущество использования архитектуры register + stack [ср. Архитектурная модель виртуальной машины Smalltalk от Allen Wirfs-Brock и Pat Caudill] заключается в том, что дополнительное пространство, предоставляемое регистрами, облегчает манипулирование байт-кодами для ради оптимизации. Конечно, хотя эти виды оптимизации не так важны, как метод inline или полиморфные встроенные кэши, как указано в ответе ниже, их не следует игнорировать, особенно в сочетании с другими, реализованными JIT-компилятором. Еще одна интересная тема для анализа заключается в том, действительно ли необходима деструктивная оптимизация (т.е. Та, которая требует де-оптимизации для поддержки отладчика), или достаточное повышение производительности может быть достигнуто с помощью неразрушающих методов.