Краткая версия: в мире без какой-либо оптимизации времени выполнения (специализация типа, JIT и т. Д.) Время будет соответствовать вашим ожиданиям.Времена здесь зависят от того, насколько хорошо оптимизатор работает с каждым примером.
Прежде всего, интересно запускать код без какой-либо оптимизации во время выполнения.На моей (довольно медленной) виртуальной машине на коробке, на которой я сейчас работаю, вставка MVM_SPESH_DISABLE=1
в среду приводит к следующим временным интервалам:
13.92366942
16.235372
14.4329288
Это имеет своего рода интуитивный смысл:
- В первом случае у нас есть простая лексическая переменная, объявленная во внешней области видимости блока
- Во втором случае мы должны выделить, а затем собрать мусор, дополнительное
Scalar
выделениекаждый раз вокруг цикла, который учитывает дополнительное время - В третьем случае мы используем переменную
state
.Переменная state
сохраняется в объекте кода замыкания, а затем копируется в кадр вызова во время входа.Это дешевле, чем выделять новый Scalar
каждый раз, но все же немного больше работы, чем вообще не выполнять эту операцию.
Далее, давайте запустим 3 программы с включенным оптимизатором, каждаяНапример, в своей собственной изолированной программе.
- Первый из них получается с
0.86298831
, с коэффициентом 16 быстрее.Иди оптимизатор!Он имеет встроенное тело цикла. - Второе значение получается на
1.2288566
, то есть в 1030 * 13 раз быстрее.Не слишком потертый либо.Он снова встроил тело цикла.(Этот случай также станет довольно дешевым в будущем, как только анализатор побега станет достаточно умным, чтобы исключить распределение Scalar
.) - Третий выходит на
2.0695035
, с коэффициентом 7. быстрее.Это сравнительно не впечатляет (даже если все еще является довольно значительным улучшением), и главная причина в том, что он не имеет встроенного тела цикла.Зачем?Потому что он еще не знает, как встроить код, который использует переменные состояния.(Как это увидеть: запустите с MVM_SPESH_INLINE_LOG=1
в среде, и среди выходных данных будет: Can NOT inline (1) with bytecode size 78 into (3): cannot inline code that declares a state variable
.)
Короче говоря, доминирующим фактором здесь является встраивание тела цикла,и с переменными состояния, которые в настоящее время невозможны.
Не сразу понятно, почему оптимизатор работает хуже в случае с внешним объявлением $var
, когда это не первый цикл в программе;это больше похоже на ошибку, чем на разумный случай «эта функция еще не оптимизирована».В своей слабой защите ему все же удается добиться значительных улучшений, даже если они не настолько велики, как хотелось бы!