Confidential - © All rights reserved. Zend Technologies, Inc.1
Copyright - © All rights reserved. Zend Technologies, Inc.
Развитие PHP 7.*
Dmitry Stogov
DevConf 2016, Москва
Principal Engineer at Zend Technologies
Copyright - © All rights reserved. Zend Technologies, Inc.2
Кто Я?
●
Работаю в ИТ с 1991
●
Первое знакомство с PHP в 2002
●
Автор Turck MMCache (eAccelerator)
●
Работаю в Zend Technologies с 2004
●
Сейчас ведущий инженер
●
Автор ext/soap и pecl/perl
●
Один из ведущих разработчиков Open Source PHP
●
Майнтейнер Zend OPcache
●
Лидер проекта PHPNG легшего в основу PHP 7
Copyright - © All rights reserved. Zend Technologies, Inc.3
Производительность PHP на синтетических тестах
0 2 4 6 8 10 12 14
12.68
12.54
4.68
4.2
2.91
2.18
2.03
1.92
0.78
0.56
0.38
bench.php [sec]
4.4
5.0 - Jul 2004
5.1 - Nov 2005
5.2 - Nov 2006
5.3 - Nov 2009
5.4 - Mar 2012
5.5 - Jun 2013
5.6 - Aug 2014
7.0.0 - Dec 2015
7.1 Jun 2016
HHVM-3.13.2
sec
PHP-7.1 еще на 25% быстрее PHP-7.0 но все еще медленнее HHVM
Copyright - © All rights reserved. Zend Technologies, Inc.4
Производительность PHP на реальных приложениях
0 50 100 150 200 250
54
51
56
67
76
91
93
101
232
235
206
WordPress-3.6.0 Home Page [req/sec]
4.4
5.0 - Jul 2004
5.1 - Nov 2005
5.2 - Nov 2006
5.3 - Nov 2009
5.4 - Mar 2012
5.5 - Jun 2013
5.6 - Aug 2014
7.0.0 - Dec 2015
7.1 Jun 2016
HHVM-3.13.2
req/sec
На реальных приложениях PHP-7.1 пока не дает существенного выигрыша!
Copyright - © All rights reserved. Zend Technologies, Inc.5
PHPNG (New Generation)
●
Проект получил свое развитие после попыток создания JIT для PHP
●
Рефакторинг (ни каких нововведений, 100% совместимость с PHP 5)
●
Основная цель — достичь нового уровня производительности и
заложить базу для будущих улучшений
●
Отделился от основной ветки PHP в январе 2014
●
Две недели ушло на то что-бы просто скомпилировать ядро
●
Еще через две недели заработал bench.php
●
Полтора месяца для обеспечения совместимости с Wordpress
●
Еще через месяц (к 9 Мая) мы открыли проект
●
В августе 2014 принят как основа для будущего PHP 7
Copyright - © All rights reserved. Zend Technologies, Inc.6
PHP 7.0
●
Было решено выпускать PHP 7 после PHP 5, пропустив PHP 6
●
GA релиз состоялся в декабре 2015
●
Сейчас доступен PHP-7.0.7
●
Возможность определять скалярные типы аргументов функций и
возвращаемых значений
●
Исключения вместо фатальных ошибок
●
Анонимный классы
●
Zero-cost assert()
●
Новые операторы и функции (<=>, ??)
●
Чистка неконсистентностей
Copyright - © All rights reserved. Zend Technologies, Inc.7
Badoo перешли на PHP 7.0 и сэкономили $1M
Copyright - © All rights reserved. Zend Technologies, Inc.8
Что дальше?
●
PHP 7.0
●
Оптимизация структур данных
●
PHP 7.1
●
Анализатор потоков данных
●
Вывод типов
●
Глобальный оптимизатор для байт-кода PHP
●
Оптимизация и Специализация интерпретатора
Copyright - © All rights reserved. Zend Technologies, Inc.9
zval
type_flags
value
type reserved
● IS_UNDEF
● IS_NULL
● IS_FALSE
● IS_TRUE
● IS_LONG
● IS_DOUBLE
● IS_STRING
● IS_ARRAY
● IS_OBJECT
● IS_RESOURCE
● IS_REFERENCE
● IS_INDIRECT
● IS_PTR
● IS_TYPE_CONSTANT
● IS_TYPE_REFCOUNTED
● IS_TYPE_COLLECTABLE
● IS_TYPE_COPYABLE
● IS_TYPE_IMMUTABLE
0 7 8 31 32 63
new type
old IS_BOOL
scalars
refcounted
new type
Copyright - © All rights reserved. Zend Technologies, Inc.10
zval (refcounted)
● IS_STRING
● IS_ARRAY
● IS_OBJECT
● IS_RESOURCE
● IS_REFERENCE
type_flags
value
type reserved
...
typerefcount flags gc_info
0 7 8 31 32 63
Copyright - © All rights reserved. Zend Technologies, Inc.11
zval (string)
● IS_STR_PERSISTENT
● IS_STR_INTERNED
● IS_STR_PERMANENTflags
value
type reserved
hash_value
typerefcount flags gc_info
len
val
...
0 7 8 31 32 63
Copyright - © All rights reserved. Zend Technologies, Inc.12
zval (array)
flags
value
type reserved
typerefcount flags gc_info
HashTable
● IS_ARRAY_IMMUTABLE
0 7 8 31 32 63
Copyright - © All rights reserved. Zend Technologies, Inc.13
zval (array) / HashTable
flags
value
type reserved
0 7 8 31 32 63
Bucket index N
...
Bucket index 0
key
hash_val
Bucket 0
val
...
key
hash_val
Bucket N
val
string, rc=1
«hello»
typerefcount flags gc_info
flags
arData
nTableMask
nNumUsed nNumOfElem
nNextFreeElement
nInternalPtrnTableSize
pDestructor
Copyright - © All rights reserved. Zend Technologies, Inc.14
HashTable (PHP 5.*)
nKeyLenght
hash_val
Bucket
pData
pDataPtr
pListNext
pListPrev
pNext
pPrev
arKey
pInternalPointer
nTableSize
nNextFreeElement
nTableMask
nNumOfElem
pListHead
pListTail
arBuckets
pDestructor
HashTable
nKeyLenght
hash_val
Bucket
pData
pDataPtr
pListNext
pListPrev
pNext
pPrev
arKey
type
value
zval
Bucket*
Bucket*
...
Bucket*
«hello»
Copyright - © All rights reserved. Zend Technologies, Inc.15
PHP 5.6 PHP 7
Memory Usage 428 MB 34 MB
Time 0.49 sec 0.06 sec
$a = array();
for ($i = 0; $i < 1000000; $i++) $a[$i] = array("hello");
echo memory_get_usage(true);
if (in array($color, array(“red”, “yellow”, “green”)) {
...
}
Immutable Arrays (Неизменяемые массивы)
Copyright - © All rights reserved. Zend Technologies, Inc.16
zval (object/PHP 7)
● IS_OBJ_DTOR_CALLED
● IS_OBJ_FREE_CALLED
● IS_OBJ_USE_GUARDS
● IS_OBJ_HAS_GUARDS
flags
value
type reserved
zend_class_entry *ce
typerefcount flags gc_info
zend_object_handlers *handlers
HashTable *properies
...
zval property_N
zval property1
HashTable *guards (optional)
0 7 8 31 32 63
Copyright - © All rights reserved. Zend Technologies, Inc.17
zval (reference)
flags
value
type reserved
typerefcount flags gc_info
zval val
0 7 8 31 32 63
Copyright - © All rights reserved. Zend Technologies, Inc.18
Компиляция PHP 7
<?php
$name = $_GET['name'];
echo “hello $namen”;
Lexer
Parser
Compiler
filename
zend_op_array
vars
scope
name
hello.php
opcodes
...
literals
arg_info
FETCH_R C0, V1
zend_op
ROPE_INIT C2,T1
ASSIGN $0,V2
FETCH_DIM_R V1,C1,V2
ROPE_ADD $0,T1
ECHO T1
ROPE_END C3,T1
RETURN C4
$name
zend_string
“_GET”
zval
“n”
“hello “
“name”
int(1)
AST
tokens
Copyright - © All rights reserved. Zend Technologies, Inc.19
Структуры Данных PHP 7 Времени Исполнения
current_execute_data
zend_executor_globals
scope (removed in 7.1)
..
func
zend_execute_data
called_scope (removed in 7.1)
zval* return_value
call
opline
symbol_table
prev_execute_data
run_time_cache
literals
zval This
...
zend_op_array
opcodes
...
literals
FETCH_R
zend_op
ROPE_INIT
ASSIGN
FETCH_DIM_R
ROPE_ADD
ECHO
ROPE_END
RETURN
“_GET”
zval
“name”
literals
$name
V2
V1 / T1
Copyright - © All rights reserved. Zend Technologies, Inc.20
Интерпретация PHP 7
register zend_execute_data *exexute_data
__asm__(«%r14»);
register zend_op *opline
__asm__(«%r15»);
void execute_ex(zend_execute_data *ex)
{
exexute_data = ex;
opline = exexcute_data->opline;
do {
opline->handler();
} while (opline);
}
ZEND_VM_HANDLER(1, ZEND_ADD,
CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
zval *op1, *op2, *result;
op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (Z_TYPE_P(op1)== IS_LONG) {
if (Z_TYPE_P(op2) == IS_LONG) {
result = EX_VAR(opline->result.var);
fast_long_add_function(result, op1, op2);
} else if (Z_TYPE_P(op2) == IS_DOUBLE) {
...
} else{
…
}
opline++;
}
Copyright - © All rights reserved. Zend Technologies, Inc.21
Интерпретация PHP 7
register zend_execute_data *exexute_data
__asm__(«%r14»);
register zend_op *opline
__asm__(«%r15»);
void execute_ex(zend_execute_data *ex)
{
exexute_data = ex;
opline = exexcute_data->opline;
do {
opline->handler();
} while (opline);
}
static void ZEND_ADD_SPEC_TMPVAR_CONST(void)
{
zval *op1, *op2, *result;
op1 = ZEND_CALL_VAR(execute_data, opline->op1.var);
op2 = execute_data->literals[opline->op2.num];
if (Z_TYPE_P(op1)== IS_LONG) {
if (Z_TYPE_P(op2) == IS_LONG) {
result = EX_VAR(opline->result.var);
fast_long_add_function(result, op1, op2);
} else if (Z_TYPE_P(op2) == IS_DOUBLE) {
...
} else{
…
}
opline++;
}
Copyright - © All rights reserved. Zend Technologies, Inc.22
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (zvals)
...SEND_VAL 3
SEND_VAL 5
DO_FCALL
RETURN null
INIT_FCALL “foo”/2
CALL FRAME
call
opline
prev_execute_data
current_execute_data
Copyright - © All rights reserved. Zend Technologies, Inc.23
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
...
...
...
SEND_VAL 3
SEND_VAL 5
DO_FCALL
RETURN null
INIT_FCALL “foo”/2
Arg1:
Arg2:
VM STACK (zvals)
CALL FRAME
opline
prev_execute_data
current_execute_data
CALL FRAME
call
prev_execute_data
call
opline
Copyright - © All rights reserved. Zend Technologies, Inc.24
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
SEND_VAL 3
SEND_VAL 5
DO_FCALL
RETURN null
INIT_FCALL “foo”/2
VM STACK (zvals)
CALL FRAME
call
opline
prev_execute_data
current_execute_data
int(3)
...
...
Arg1:
Arg2:
CALL FRAME
call
opline
prev_execute_data
Copyright - © All rights reserved. Zend Technologies, Inc.25
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
SEND_VAL 3
SEND_VAL 5
DO_FCALL
RETURN null
INIT_FCALL “foo”/2
int(5)
...
Arg1:
Arg2:
VM STACK (zvals)
CALL FRAME
call
opline
prev_execute_data
current_execute_data
CALL FRAME
call
opline
prev_execute_data
int(3)
Copyright - © All rights reserved. Zend Technologies, Inc.26
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
SEND_VAL 3
SEND_VAL 5
DO_FCALL
RETURN null
INIT_FCALL “foo”/2
skip first 2 instructions
local variables already in-place
VM STACK (zvals)
CALL FRAME
opline
prev_execute_data
int(3)
...
CALL FRAME
call
opline
Arg2 $b:
Arg1 $a:
int(5)
call
prev_execute_data
current_execute_data
Copyright - © All rights reserved. Zend Technologies, Inc.27
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
SEND_VAL 3
SEND_VAL 5
DO_FCALL
RETURN null
INIT_FCALL “foo”/2
VM STACK (zvals)
CALL FRAME
call
opline
prev_execute_data
current_execute_data
VM STACK (zvals)
CALL FRAME
call
opline
prev_execute_data
current_execute_data
int(3)
CALL FRAME
call
opline
prev_execute_data
int(5)
int(8)
Arg2 $b:
Arg1 $a:
Copyright - © All rights reserved. Zend Technologies, Inc.28
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
SEND_VAL 3
SEND_VAL 5
DO_FCALL
RETURN null
INIT_FCALL “foo”/2
VM STACK (zvals)
CALL FRAME
call
opline
prev_execute_data
current_execute_data
int(3)
int(5)
int(8)
CALL FRAME
prev_execute_data
call
opline
Arg2 $b:
Arg1 $a:
Copyright - © All rights reserved. Zend Technologies, Inc.29
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
...SEND_VAL 3
SEND_VAL 5
DO_FCALL
RETURN null
INIT_FCALL “foo”/2
VM STACK (zvals)
CALL FRAME
call
opline
prev_execute_data
current_execute_data
Copyright - © All rights reserved. Zend Technologies, Inc.30
Что дальше?
●
PHP 7.0
●
Оптимизация структур данных
●
PHP 7.1
●
Анализатор потоков данных
●
Вывод типов
●
Глобальный оптимизатор для байт-кода PHP
●
Оптимизация и Специализация интерпретатора
Copyright - © All rights reserved. Zend Technologies, Inc.31
PHP 7.1
●
Первый Alpha релиз в июне 2016
●
Feature Freeze в июле
●
GA релиз запланирован на ноябрь 2016
●
Nullable types - function foo(?Node $x): ?Node;
●
Void return type - function foo(): void;
●
Keys in list() - foreach ($points as list(«x»=>$x, «y»=>$y))
●
Class constants visibility - private const X = 42;
●
Negative string offsets - $a = “abcd”; var_dump($a[-2]);
●
Invalid numeric strings - 5 * “orange”
●
Closure::fromCallable()
Copyright - © All rights reserved. Zend Technologies, Inc.32
PHP 7.1 Optimizer (script)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.33
PHP 7.1 Optimizer (bytecode)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ADD $sum, $i -> T2
ASSIGN $sum, T2
POST_INC $i -> T4
FREE T4
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
RETUTN null
Copyright - © All rights reserved. Zend Technologies, Inc.34
PHP 7.1 Optimizer (trivial optimization)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ADD $sum, $i -> T2
ASSIGN $sum, T2
POST_INC $i -> T4
FREE T4
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
RETUTN null
Copyright - © All rights reserved. Zend Technologies, Inc.35
PHP 7.1 Optimizer (trivial optimization)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum += $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ASSIGN_ADD $sum, $i
POST_INC $i -> T4
FREE T4
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
RETUTN null
Copyright - © All rights reserved. Zend Technologies, Inc.36
PHP 7.1 Optimizer (trivial optimization)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ASSIGN_ADD $sum, $i
POST_INC $i -> T4
FREE T4
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
RETUTN null
Copyright - © All rights reserved. Zend Technologies, Inc.37
PHP 7.1 Optimizer (trivial optimization)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; ++$i) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ASSIGN_ADD $sum, $i
PRE_INC $i
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
RETUTN null
Copyright - © All rights reserved. Zend Technologies, Inc.38
PHP 7.1 Optimizer (trivial optimization)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ASSIGN_ADD $sum, $i
PRE_INC $i
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
RETUTN null
Copyright - © All rights reserved. Zend Technologies, Inc.39
PHP 7.1 Optimizer (trivial optimization)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ASSIGN_ADD $sum, $i
PRE_INC $i
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
Copyright - © All rights reserved. Zend Technologies, Inc.40
PHP 7.1 Optimizer (Control Flow Graph)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ASSIGN_ADD $sum, $i
PRE_INC $i
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
Copyright - © All rights reserved. Zend Technologies, Inc.41
PHP 7.1 Optimizer (Control Flow Graph)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ASSIGN_ADD $sum, $i
PRE_INC $i
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
Copyright - © All rights reserved. Zend Technologies, Inc.42
PHP 7.1 Optimizer (Control Flow Graph)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ASSIGN_ADD $sum, $i
PRE_INC $i
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
Copyright - © All rights reserved. Zend Technologies, Inc.43
PHP 7.1 Optimizer (Control Flow Graph)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ASSIGN_ADD $sum, $i
PRE_INC $i
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
Copyright - © All rights reserved. Zend Technologies, Inc.44
PHP 7.1 Optimizer (Static Single Assignmnt Form)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $1.sum, 0
ASSIGN $2.i, 0
JMP L1
L0:
ASSIGN_ADD $?.sum → $3.sum, $?.i
PRE_INC $?.i → $4.i
L1:
IS_SMALLER $?.i, 100 -> T5
JMPNZ T5, L0
RETRUN $?.sum
Copyright - © All rights reserved. Zend Technologies, Inc.45
PHP 7.1 Optimizer (Static Single Assignmnt Form)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $1.sum, 0
ASSIGN $2.i, 0
JMP L1
L0:
ASSIGN_ADD $?.sum → $3.sum, $?.i
PRE_INC $?.i → $4.i
$5.sum = Phi($1.sum, $3.sum)
$6.i = Phi($2.i, $4.i)
IS_SMALLER $?.i, 100 -> T5
JMPNZ T5, L0
RETRUN $?.sum
Copyright - © All rights reserved. Zend Technologies, Inc.46
PHP 7.1 Optimizer (Static Single Assignmnt Form)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $1.sum, 0
ASSIGN $2.i, 0
JMP L1
L0:
ASSIGN_ADD $5.sum → $3.sum, $6.i
PRE_INC $6.i → $4.i
$5.sum = Phi($1.sum, $3.sum)
$6.i = Phi($2.i, $4.i)
IS_SMALLER $6.i, 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.47
PHP 7.1 Optimizer (Extended Static Single Assignmnt Form)
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
ASSIGN $1.sum, 0
ASSIGN $2.i, 0
JMP L1
$7.i = Pi($6.i & RANGE[--..99])
ASSIGN_ADD $5.sum → $3.sum, $7.i
PRE_INC $7.i → $4.i
$5.sum = Phi($1.sum, $3.sum)
$6.i = Phi($2.i, $4.i)
IS_SMALLER $6.i, 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.48
PHP 7.1 Optimizer (Extended Static Single Assignmnt Form)
ASSIGN $1.sum, 0
ASSIGN $2.i, 0
JMP L1
$7.i = Pi($6.i & RANGE[--..99])
ASSIGN_ADD $5.sum → $3.sum, $7.i
PRE_INC $7.i → $4.i
$5.sum = Phi($1.sum, $3.sum)
$6.i = Phi($2.i, $4.i)
IS_SMALLER $6.i, 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.49
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i = Pi($6.i & RANGE[--..99])
ASSIGN_ADD $5.sum → $3.sum, $7.i
PRE_INC $7.i → $4.i
$5.sum = Phi($1.sum, $3.sum)
$6.i = Phi($2.i, $4.i)
IS_SMALLER $6.i, 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.50
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i = Pi($6.i & RANGE[--..99])
ASSIGN_ADD $5.sum → $3.sum, $7.i
PRE_INC $7.i → $4.i
$5.sum = Phi($1.sum [long], $3.sum)
$6.i = Phi($2.i [long], $4.i)
IS_SMALLER $6.i, 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.51
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i = Pi($6.i & RANGE[--..99])
ASSIGN_ADD $5.sum → $3.sum, $7.i
PRE_INC $7.i → $4.i
$5.sum [long] = Phi($1.sum [long], $3.sum)
$6.i [long] = Phi($2.i [long], $4.i)
IS_SMALLER $6.i, 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.52
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long] = Pi($6.i [long] & RANGE[--..99])
ASSIGN_ADD $5.sum [long] → $3.sum [?], $7.i [long]
PRE_INC $7.i [long] → $4.i [?]
$5.sum [long] = Phi($1.sum [long], $3.sum [?])
$6.i [long] = Phi($2.i [long], $4.i [?])
IS_SMALLER $6.i [long], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long]
Copyright - © All rights reserved. Zend Technologies, Inc.53
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long] = Pi($6.i [long] & RANGE[--..99])
ASSIGN_ADD $5.sum [long] → $3.sum [long, double], $7.i [long]
PRE_INC $7.i [long] → $4.i [long, double]
$5.sum [long] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long] = Phi($2.i [long], $4.i [long, double])
IS_SMALLER $6.i [long], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long]
Copyright - © All rights reserved. Zend Technologies, Inc.54
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long, double] = Pi($6.i [long, double] & RANGE[--..99])
ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long, double]
PRE_INC $7.i [long, double] → $4.i [long, double]
$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long, double] = Phi($2.i [long], $4.i [long, double])
IS_SMALLER $6.i [long, double], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.55
PHP 7.1 Optimizer (Range Propagation)
ASSIGN $1.sum [0..0], 0
ASSIGN $2.i [0..0], 0
JMP L1
$7.i = Pi($6.i & RANGE[--..99])
ASSIGN_ADD $5.sum → $3.sum, $7.i
PRE_INC $7.i → $4.i
$5.sum = Phi($1.sum, $3.sum)
$6.i = Phi($2.i, $4.i)
IS_SMALLER $6.i, 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.56
PHP 7.1 Optimizer (Range Propagation)
ASSIGN $1.sum [0..0], 0
ASSIGN $2.i [0..0], 0
JMP L1
$7.i [0..0] = Pi($6.i [0..0] & RANGE[--..99])
ASSIGN_ADD $5.sum [0..0] → $3.sum [?], $7.i [0..0]
PRE_INC $7.i [0..0] → $4.i [?]
$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [?])
$6.i [0..0] = Phi($2.i [0..0], $4.i [?])
IS_SMALLER $6.i [0..0], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [0..0]
Copyright - © All rights reserved. Zend Technologies, Inc.57
PHP 7.1 Optimizer (Range Propagation)
ASSIGN $1.sum [0..0], 0
ASSIGN $2.i [0..0], 0
JMP L1
$7.i [0..0] = Pi($6.i [0..0] & RANGE[--..99])
ASSIGN_ADD $5.sum [0..0] → $3.sum [0..0], $7.i [0..0]
PRE_INC $7.i [0..0] → $4.i [1..1]
$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..0])
$6.i [0..0] = Phi($2.i [0..0], $4.i [1..1])
IS_SMALLER $6.i [0..0], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [0..0]
Copyright - © All rights reserved. Zend Technologies, Inc.58
PHP 7.1 Optimizer (Range Propagation)
ASSIGN $1.sum [0..0], 0
ASSIGN $2.i [0..0], 0
JMP L1
$7.i [0..0] = Pi($6.i [0..++] & RANGE[--..99])
ASSIGN_ADD $5.sum [0..0] → $3.sum [0..0], $7.i [0..0]
PRE_INC $7.i [0..0] → $4.i [1..1]
$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..0])
$6.i [0..++] = Phi($2.i [0..0], $4.i [1..1])
IS_SMALLER $6.i [0..++], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [0..0]
Copyright - © All rights reserved. Zend Technologies, Inc.59
PHP 7.1 Optimizer (Range Propagation)
ASSIGN $1.sum [0..0], 0
ASSIGN $2.i [0..0], 0
JMP L1
$7.i [0..99] = Pi($6.i [0..++] & RANGE[--..99])
ASSIGN_ADD $5.sum [0..0] → $3.sum [0..0], $7.i [0..99]
PRE_INC $7.i [0..99] → $4.i [1..1]
$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..0])
$6.i [0..++] = Phi($2.i [0..0], $4.i [1..1])
IS_SMALLER $6.i [0..++], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [0..0]
Copyright - © All rights reserved. Zend Technologies, Inc.60
PHP 7.1 Optimizer (Range Propagation)
ASSIGN $1.sum [0..0], 0
ASSIGN $2.i [0..0], 0
JMP L1
$7.i [0..99] = Pi($6.i [0..++] & RANGE[--..99])
ASSIGN_ADD $5.sum [0..0] → $3.sum [0..100], $7.i [0..99]
PRE_INC $7.i [0..99] → $4.i [1..100]
$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..100])
$6.i [0..++] = Phi($2.i [0..0], $4.i [1..100])
IS_SMALLER $6.i [0..++], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [0..0]
Copyright - © All rights reserved. Zend Technologies, Inc.61
PHP 7.1 Optimizer (Range Propagation)
ASSIGN $1.sum [0..0], 0
ASSIGN $2.i [0..0], 0
JMP L1
$7.i [0..99] = Pi($6.i [0..++] & RANGE[--..99])
ASSIGN_ADD $5.sum [0..++] → $3.sum [0..++], $7.i [0..99]
PRE_INC $7.i [0..99] → $4.i [1..100]
$5.sum [0..++] = Phi($1.sum [0..0], $3.sum [0..++])
$6.i [0..++] = Phi($2.i [0..0], $4.i [1..100])
IS_SMALLER $6.i [0..++], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [0..++]
Copyright - © All rights reserved. Zend Technologies, Inc.62
PHP 7.1 Optimizer (Range Propagation - narrowing)
ASSIGN $1.sum [0..0], 0
ASSIGN $2.i [0..0], 0
JMP L1
$7.i [0..99] = Pi($6.i [0..100] & RANGE[--..99])
ASSIGN_ADD $5.sum [0..++] → $3.sum [0..++], $7.i [0..99]
PRE_INC $7.i [0..99] → $4.i [1..100]
$5.sum [0..++] = Phi($1.sum [0..0], $3.sum [0..++])
$6.i [0..100] = Phi($2.i [0..0], $4.i [1..100])
IS_SMALLER $6.i [0..100], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [0..++]
Copyright - © All rights reserved. Zend Technologies, Inc.63
PHP 7.1 Optimizer (Range + Type Propagation)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long, double] = Pi($6.i [long, double] & RANGE[--..99])
ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long, double]
PRE_INC $7.i [long, double] → $4.i [long, double]
$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long, double] = Phi($2.i [long], $4.i [long, double])
IS_SMALLER $6.i [long, double], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.64
PHP 7.1 Optimizer (Range + Type Propagation)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long] = Pi($6.i [long] & RANGE[--..99])
ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long]
PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100]
$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long] = Phi($2.i [long], $4.i [long])
IS_SMALLER $6.i [long], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.65
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long] = Pi($6.i [long] & RANGE[--..99])
ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long]
PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100]
$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long] = Phi($2.i [long], $4.i [long])
IS_SMALLER $6.i [long], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.66
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long] = Pi($6.i [long] & RANGE[--..99])
ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double]
PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100]
$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long] = Phi($2.i [long], $4.i [long])
IS_SMALLER $6.i [long], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.67
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long] = Pi($6.i [long] & RANGE[--..99])
ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double]
PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100]
$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long] = Phi($2.i [long], $4.i [long])
IS_SMALLER $6.i [long], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.68
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long] = Pi($6.i [long] & RANGE[--..99])
ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double]
PRE_INC_LONG_NOOVERFLOW $7.i [long] [0..99] → $4.i [long] [1..100]
$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long] = Phi($2.i [long], $4.i [long])
IS_SMALLER $6.i [long], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.69
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long] = Pi($6.i [long] & RANGE[--..99])
ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double]
PRE_INC_LONG_NOOVERFLOW $7.i [long] [0..99] → $4.i [long] [1..100]
$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long] = Phi($2.i [long], $4.i [long])
IS_SMALLER $6.i [long], 100 -> T5
JMPNZ T5, L0
RETRUN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.70
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSIGN $2.i [long], 0
JMP L1
$7.i [long] = Pi($6.i [long] & RANGE[--..99])
ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double]
PRE_INC_LONG_NOOVERFLOW $7.i [long] [0..99] → $4.i [long] [1..100]
$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double])
$6.i [long] = Phi($2.i [long], $4.i [long])
IS_SMALLER_LONG_JMPNZ $6.i [long], 100, L0
RETRUN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.71
PHP 7.1 Optimizer (SSA deconstruction)
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ADD $sum, $i → $sum
PRE_INC_LONG_NOOVERFLOW $i
L1:
IS_SMALLER_LONG_JMPNZ $i, 100, L0
RETRUN $sum
ASSIGN $sum, 0
ASSIGN $i, 0
JMP L1
L0:
ADD $sum, $i -> T2
ASSIGN $sum, T2
POST_INC $i -> T4
FREE T4
L1:
IS_SMALLER $i, 100 -> T5
JMPNZ T5, L0
RETRUN $sum
RETUTN null
Copyright - © All rights reserved. Zend Technologies, Inc.72
PHP 7.1 Specialized Handlers
void PRE_INC_HANDLER()
{
if (Z_TYPE_P(op1) != IS_LONG) {
… // not integer
} else {
Z_LVAL_P(op1)++;
if (OVERFLOW) {
… // overflow
}
}
CHECK_EXCEPTION();
NEXT_OPCODE();
}
void
PRE_INC_HANDLER_LONG_NO_OVERFLOW()
{
Z_LVAL_P(op1)++;
NEXT_OPCODE();
}
mov 0x4(%IP), %eax // get op1 offset
incl (%FP, %eax) // increment
add 0x1c, %IP // next opcode
ret
Copyright - © All rights reserved. Zend Technologies, Inc.73
Что дальше?
●
PHP 7.0
●
Оптимизация структур данных
●
PHP 7.1
●
Анализатор потоков данных
●
Вывод типов
●
Глобальный оптимизатор для байт-кода PHP
●
Оптимизация и Специализация интерпретатора
●
PHP 7.2
●
JIT?
Copyright - © All rights reserved. Zend Technologies, Inc.74
The Computer Language Benchmarks Game (Mandelbrot)
GCC-5.3 -O3
PHP/llvm-jit
LuaJit-2.1.0-beta2
JavaScriptCore-1.12.3
V8-3.14.5.10
HHVM-3.13.2 (--count=2)
SpiderMonrey-1.8.5
PyPy-4.0.1
Java (openjdk-1.8)
PHP-7.1.0-dev
LuaJit-2.1.0-beta2 (-j off)
JavaScriptCore-1.12.3 (LLint)
PHP-7.0.7
Java (openjdk-1.8 -Xint)
Lua-5.3.2
PHP-5.6.20
Ruby-2.2.5
Python-2.7.11
HHVM-3.13.2 (Jit=false)
Perl-5.22.1
0 0.5 1 1.5 2 2.5
0.011
0.011
0.013
0.014
0.016
0.019
0.027
0.030
0.046
0.092
0.098
0.190
0.227
0.243
0.300
0.363
0.609
0.940
1.036
2.063
sec
Самый быстрый интерпретатор,
все что быстрее с JIT.
В перспективе - быстрее некуда :)
Confidential - © All rights reserved. Zend Technologies, Inc.75
Вопросы?
Dmitry Stogov
Principal Engineer at Zend Technologies
@dstogov
dmitry@zend.com
www.zend.com

"Развитие ветки PHP-7"

  • 1.
    Confidential - ©All rights reserved. Zend Technologies, Inc.1 Copyright - © All rights reserved. Zend Technologies, Inc. Развитие PHP 7.* Dmitry Stogov DevConf 2016, Москва Principal Engineer at Zend Technologies
  • 2.
    Copyright - ©All rights reserved. Zend Technologies, Inc.2 Кто Я? ● Работаю в ИТ с 1991 ● Первое знакомство с PHP в 2002 ● Автор Turck MMCache (eAccelerator) ● Работаю в Zend Technologies с 2004 ● Сейчас ведущий инженер ● Автор ext/soap и pecl/perl ● Один из ведущих разработчиков Open Source PHP ● Майнтейнер Zend OPcache ● Лидер проекта PHPNG легшего в основу PHP 7
  • 3.
    Copyright - ©All rights reserved. Zend Technologies, Inc.3 Производительность PHP на синтетических тестах 0 2 4 6 8 10 12 14 12.68 12.54 4.68 4.2 2.91 2.18 2.03 1.92 0.78 0.56 0.38 bench.php [sec] 4.4 5.0 - Jul 2004 5.1 - Nov 2005 5.2 - Nov 2006 5.3 - Nov 2009 5.4 - Mar 2012 5.5 - Jun 2013 5.6 - Aug 2014 7.0.0 - Dec 2015 7.1 Jun 2016 HHVM-3.13.2 sec PHP-7.1 еще на 25% быстрее PHP-7.0 но все еще медленнее HHVM
  • 4.
    Copyright - ©All rights reserved. Zend Technologies, Inc.4 Производительность PHP на реальных приложениях 0 50 100 150 200 250 54 51 56 67 76 91 93 101 232 235 206 WordPress-3.6.0 Home Page [req/sec] 4.4 5.0 - Jul 2004 5.1 - Nov 2005 5.2 - Nov 2006 5.3 - Nov 2009 5.4 - Mar 2012 5.5 - Jun 2013 5.6 - Aug 2014 7.0.0 - Dec 2015 7.1 Jun 2016 HHVM-3.13.2 req/sec На реальных приложениях PHP-7.1 пока не дает существенного выигрыша!
  • 5.
    Copyright - ©All rights reserved. Zend Technologies, Inc.5 PHPNG (New Generation) ● Проект получил свое развитие после попыток создания JIT для PHP ● Рефакторинг (ни каких нововведений, 100% совместимость с PHP 5) ● Основная цель — достичь нового уровня производительности и заложить базу для будущих улучшений ● Отделился от основной ветки PHP в январе 2014 ● Две недели ушло на то что-бы просто скомпилировать ядро ● Еще через две недели заработал bench.php ● Полтора месяца для обеспечения совместимости с Wordpress ● Еще через месяц (к 9 Мая) мы открыли проект ● В августе 2014 принят как основа для будущего PHP 7
  • 6.
    Copyright - ©All rights reserved. Zend Technologies, Inc.6 PHP 7.0 ● Было решено выпускать PHP 7 после PHP 5, пропустив PHP 6 ● GA релиз состоялся в декабре 2015 ● Сейчас доступен PHP-7.0.7 ● Возможность определять скалярные типы аргументов функций и возвращаемых значений ● Исключения вместо фатальных ошибок ● Анонимный классы ● Zero-cost assert() ● Новые операторы и функции (<=>, ??) ● Чистка неконсистентностей
  • 7.
    Copyright - ©All rights reserved. Zend Technologies, Inc.7 Badoo перешли на PHP 7.0 и сэкономили $1M
  • 8.
    Copyright - ©All rights reserved. Zend Technologies, Inc.8 Что дальше? ● PHP 7.0 ● Оптимизация структур данных ● PHP 7.1 ● Анализатор потоков данных ● Вывод типов ● Глобальный оптимизатор для байт-кода PHP ● Оптимизация и Специализация интерпретатора
  • 9.
    Copyright - ©All rights reserved. Zend Technologies, Inc.9 zval type_flags value type reserved ● IS_UNDEF ● IS_NULL ● IS_FALSE ● IS_TRUE ● IS_LONG ● IS_DOUBLE ● IS_STRING ● IS_ARRAY ● IS_OBJECT ● IS_RESOURCE ● IS_REFERENCE ● IS_INDIRECT ● IS_PTR ● IS_TYPE_CONSTANT ● IS_TYPE_REFCOUNTED ● IS_TYPE_COLLECTABLE ● IS_TYPE_COPYABLE ● IS_TYPE_IMMUTABLE 0 7 8 31 32 63 new type old IS_BOOL scalars refcounted new type
  • 10.
    Copyright - ©All rights reserved. Zend Technologies, Inc.10 zval (refcounted) ● IS_STRING ● IS_ARRAY ● IS_OBJECT ● IS_RESOURCE ● IS_REFERENCE type_flags value type reserved ... typerefcount flags gc_info 0 7 8 31 32 63
  • 11.
    Copyright - ©All rights reserved. Zend Technologies, Inc.11 zval (string) ● IS_STR_PERSISTENT ● IS_STR_INTERNED ● IS_STR_PERMANENTflags value type reserved hash_value typerefcount flags gc_info len val ... 0 7 8 31 32 63
  • 12.
    Copyright - ©All rights reserved. Zend Technologies, Inc.12 zval (array) flags value type reserved typerefcount flags gc_info HashTable ● IS_ARRAY_IMMUTABLE 0 7 8 31 32 63
  • 13.
    Copyright - ©All rights reserved. Zend Technologies, Inc.13 zval (array) / HashTable flags value type reserved 0 7 8 31 32 63 Bucket index N ... Bucket index 0 key hash_val Bucket 0 val ... key hash_val Bucket N val string, rc=1 «hello» typerefcount flags gc_info flags arData nTableMask nNumUsed nNumOfElem nNextFreeElement nInternalPtrnTableSize pDestructor
  • 14.
    Copyright - ©All rights reserved. Zend Technologies, Inc.14 HashTable (PHP 5.*) nKeyLenght hash_val Bucket pData pDataPtr pListNext pListPrev pNext pPrev arKey pInternalPointer nTableSize nNextFreeElement nTableMask nNumOfElem pListHead pListTail arBuckets pDestructor HashTable nKeyLenght hash_val Bucket pData pDataPtr pListNext pListPrev pNext pPrev arKey type value zval Bucket* Bucket* ... Bucket* «hello»
  • 15.
    Copyright - ©All rights reserved. Zend Technologies, Inc.15 PHP 5.6 PHP 7 Memory Usage 428 MB 34 MB Time 0.49 sec 0.06 sec $a = array(); for ($i = 0; $i < 1000000; $i++) $a[$i] = array("hello"); echo memory_get_usage(true); if (in array($color, array(“red”, “yellow”, “green”)) { ... } Immutable Arrays (Неизменяемые массивы)
  • 16.
    Copyright - ©All rights reserved. Zend Technologies, Inc.16 zval (object/PHP 7) ● IS_OBJ_DTOR_CALLED ● IS_OBJ_FREE_CALLED ● IS_OBJ_USE_GUARDS ● IS_OBJ_HAS_GUARDS flags value type reserved zend_class_entry *ce typerefcount flags gc_info zend_object_handlers *handlers HashTable *properies ... zval property_N zval property1 HashTable *guards (optional) 0 7 8 31 32 63
  • 17.
    Copyright - ©All rights reserved. Zend Technologies, Inc.17 zval (reference) flags value type reserved typerefcount flags gc_info zval val 0 7 8 31 32 63
  • 18.
    Copyright - ©All rights reserved. Zend Technologies, Inc.18 Компиляция PHP 7 <?php $name = $_GET['name']; echo “hello $namen”; Lexer Parser Compiler filename zend_op_array vars scope name hello.php opcodes ... literals arg_info FETCH_R C0, V1 zend_op ROPE_INIT C2,T1 ASSIGN $0,V2 FETCH_DIM_R V1,C1,V2 ROPE_ADD $0,T1 ECHO T1 ROPE_END C3,T1 RETURN C4 $name zend_string “_GET” zval “n” “hello “ “name” int(1) AST tokens
  • 19.
    Copyright - ©All rights reserved. Zend Technologies, Inc.19 Структуры Данных PHP 7 Времени Исполнения current_execute_data zend_executor_globals scope (removed in 7.1) .. func zend_execute_data called_scope (removed in 7.1) zval* return_value call opline symbol_table prev_execute_data run_time_cache literals zval This ... zend_op_array opcodes ... literals FETCH_R zend_op ROPE_INIT ASSIGN FETCH_DIM_R ROPE_ADD ECHO ROPE_END RETURN “_GET” zval “name” literals $name V2 V1 / T1
  • 20.
    Copyright - ©All rights reserved. Zend Technologies, Inc.20 Интерпретация PHP 7 register zend_execute_data *exexute_data __asm__(«%r14»); register zend_op *opline __asm__(«%r15»); void execute_ex(zend_execute_data *ex) { exexute_data = ex; opline = exexcute_data->opline; do { opline->handler(); } while (opline); } ZEND_VM_HANDLER(1, ZEND_ADD, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { zval *op1, *op2, *result; op1 = GET_OP1_ZVAL_PTR(BP_VAR_R); op2 = GET_OP2_ZVAL_PTR(BP_VAR_R); if (Z_TYPE_P(op1)== IS_LONG) { if (Z_TYPE_P(op2) == IS_LONG) { result = EX_VAR(opline->result.var); fast_long_add_function(result, op1, op2); } else if (Z_TYPE_P(op2) == IS_DOUBLE) { ... } else{ … } opline++; }
  • 21.
    Copyright - ©All rights reserved. Zend Technologies, Inc.21 Интерпретация PHP 7 register zend_execute_data *exexute_data __asm__(«%r14»); register zend_op *opline __asm__(«%r15»); void execute_ex(zend_execute_data *ex) { exexute_data = ex; opline = exexcute_data->opline; do { opline->handler(); } while (opline); } static void ZEND_ADD_SPEC_TMPVAR_CONST(void) { zval *op1, *op2, *result; op1 = ZEND_CALL_VAR(execute_data, opline->op1.var); op2 = execute_data->literals[opline->op2.num]; if (Z_TYPE_P(op1)== IS_LONG) { if (Z_TYPE_P(op2) == IS_LONG) { result = EX_VAR(opline->result.var); fast_long_add_function(result, op1, op2); } else if (Z_TYPE_P(op2) == IS_DOUBLE) { ... } else{ … } opline++; }
  • 22.
    Copyright - ©All rights reserved. Zend Technologies, Inc.22 VM Calling Convention (PHP 7) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (zvals) ...SEND_VAL 3 SEND_VAL 5 DO_FCALL RETURN null INIT_FCALL “foo”/2 CALL FRAME call opline prev_execute_data current_execute_data
  • 23.
    Copyright - ©All rights reserved. Zend Technologies, Inc.23 VM Calling Convention (PHP 7) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: function foo($a, $b) { return $a + $b; } foo(3, 5); ... ... ... SEND_VAL 3 SEND_VAL 5 DO_FCALL RETURN null INIT_FCALL “foo”/2 Arg1: Arg2: VM STACK (zvals) CALL FRAME opline prev_execute_data current_execute_data CALL FRAME call prev_execute_data call opline
  • 24.
    Copyright - ©All rights reserved. Zend Technologies, Inc.24 VM Calling Convention (PHP 7) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: function foo($a, $b) { return $a + $b; } foo(3, 5); SEND_VAL 3 SEND_VAL 5 DO_FCALL RETURN null INIT_FCALL “foo”/2 VM STACK (zvals) CALL FRAME call opline prev_execute_data current_execute_data int(3) ... ... Arg1: Arg2: CALL FRAME call opline prev_execute_data
  • 25.
    Copyright - ©All rights reserved. Zend Technologies, Inc.25 VM Calling Convention (PHP 7) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: function foo($a, $b) { return $a + $b; } foo(3, 5); SEND_VAL 3 SEND_VAL 5 DO_FCALL RETURN null INIT_FCALL “foo”/2 int(5) ... Arg1: Arg2: VM STACK (zvals) CALL FRAME call opline prev_execute_data current_execute_data CALL FRAME call opline prev_execute_data int(3)
  • 26.
    Copyright - ©All rights reserved. Zend Technologies, Inc.26 VM Calling Convention (PHP 7) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: function foo($a, $b) { return $a + $b; } foo(3, 5); SEND_VAL 3 SEND_VAL 5 DO_FCALL RETURN null INIT_FCALL “foo”/2 skip first 2 instructions local variables already in-place VM STACK (zvals) CALL FRAME opline prev_execute_data int(3) ... CALL FRAME call opline Arg2 $b: Arg1 $a: int(5) call prev_execute_data current_execute_data
  • 27.
    Copyright - ©All rights reserved. Zend Technologies, Inc.27 VM Calling Convention (PHP 7) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: function foo($a, $b) { return $a + $b; } foo(3, 5); SEND_VAL 3 SEND_VAL 5 DO_FCALL RETURN null INIT_FCALL “foo”/2 VM STACK (zvals) CALL FRAME call opline prev_execute_data current_execute_data VM STACK (zvals) CALL FRAME call opline prev_execute_data current_execute_data int(3) CALL FRAME call opline prev_execute_data int(5) int(8) Arg2 $b: Arg1 $a:
  • 28.
    Copyright - ©All rights reserved. Zend Technologies, Inc.28 VM Calling Convention (PHP 7) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: function foo($a, $b) { return $a + $b; } foo(3, 5); SEND_VAL 3 SEND_VAL 5 DO_FCALL RETURN null INIT_FCALL “foo”/2 VM STACK (zvals) CALL FRAME call opline prev_execute_data current_execute_data int(3) int(5) int(8) CALL FRAME prev_execute_data call opline Arg2 $b: Arg1 $a:
  • 29.
    Copyright - ©All rights reserved. Zend Technologies, Inc.29 VM Calling Convention (PHP 7) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: function foo($a, $b) { return $a + $b; } foo(3, 5); ...SEND_VAL 3 SEND_VAL 5 DO_FCALL RETURN null INIT_FCALL “foo”/2 VM STACK (zvals) CALL FRAME call opline prev_execute_data current_execute_data
  • 30.
    Copyright - ©All rights reserved. Zend Technologies, Inc.30 Что дальше? ● PHP 7.0 ● Оптимизация структур данных ● PHP 7.1 ● Анализатор потоков данных ● Вывод типов ● Глобальный оптимизатор для байт-кода PHP ● Оптимизация и Специализация интерпретатора
  • 31.
    Copyright - ©All rights reserved. Zend Technologies, Inc.31 PHP 7.1 ● Первый Alpha релиз в июне 2016 ● Feature Freeze в июле ● GA релиз запланирован на ноябрь 2016 ● Nullable types - function foo(?Node $x): ?Node; ● Void return type - function foo(): void; ● Keys in list() - foreach ($points as list(«x»=>$x, «y»=>$y)) ● Class constants visibility - private const X = 42; ● Negative string offsets - $a = “abcd”; var_dump($a[-2]); ● Invalid numeric strings - 5 * “orange” ● Closure::fromCallable()
  • 32.
    Copyright - ©All rights reserved. Zend Technologies, Inc.32 PHP 7.1 Optimizer (script) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 33.
    Copyright - ©All rights reserved. Zend Technologies, Inc.33 PHP 7.1 Optimizer (bytecode) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ADD $sum, $i -> T2 ASSIGN $sum, T2 POST_INC $i -> T4 FREE T4 L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null
  • 34.
    Copyright - ©All rights reserved. Zend Technologies, Inc.34 PHP 7.1 Optimizer (trivial optimization) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ADD $sum, $i -> T2 ASSIGN $sum, T2 POST_INC $i -> T4 FREE T4 L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null
  • 35.
    Copyright - ©All rights reserved. Zend Technologies, Inc.35 PHP 7.1 Optimizer (trivial optimization) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum += $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ASSIGN_ADD $sum, $i POST_INC $i -> T4 FREE T4 L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null
  • 36.
    Copyright - ©All rights reserved. Zend Technologies, Inc.36 PHP 7.1 Optimizer (trivial optimization) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ASSIGN_ADD $sum, $i POST_INC $i -> T4 FREE T4 L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null
  • 37.
    Copyright - ©All rights reserved. Zend Technologies, Inc.37 PHP 7.1 Optimizer (trivial optimization) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; ++$i) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ASSIGN_ADD $sum, $i PRE_INC $i L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null
  • 38.
    Copyright - ©All rights reserved. Zend Technologies, Inc.38 PHP 7.1 Optimizer (trivial optimization) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ASSIGN_ADD $sum, $i PRE_INC $i L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null
  • 39.
    Copyright - ©All rights reserved. Zend Technologies, Inc.39 PHP 7.1 Optimizer (trivial optimization) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ASSIGN_ADD $sum, $i PRE_INC $i L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum
  • 40.
    Copyright - ©All rights reserved. Zend Technologies, Inc.40 PHP 7.1 Optimizer (Control Flow Graph) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ASSIGN_ADD $sum, $i PRE_INC $i L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum
  • 41.
    Copyright - ©All rights reserved. Zend Technologies, Inc.41 PHP 7.1 Optimizer (Control Flow Graph) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ASSIGN_ADD $sum, $i PRE_INC $i L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum
  • 42.
    Copyright - ©All rights reserved. Zend Technologies, Inc.42 PHP 7.1 Optimizer (Control Flow Graph) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ASSIGN_ADD $sum, $i PRE_INC $i L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum
  • 43.
    Copyright - ©All rights reserved. Zend Technologies, Inc.43 PHP 7.1 Optimizer (Control Flow Graph) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ASSIGN_ADD $sum, $i PRE_INC $i L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum
  • 44.
    Copyright - ©All rights reserved. Zend Technologies, Inc.44 PHP 7.1 Optimizer (Static Single Assignmnt Form) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1 L0: ASSIGN_ADD $?.sum → $3.sum, $?.i PRE_INC $?.i → $4.i L1: IS_SMALLER $?.i, 100 -> T5 JMPNZ T5, L0 RETRUN $?.sum
  • 45.
    Copyright - ©All rights reserved. Zend Technologies, Inc.45 PHP 7.1 Optimizer (Static Single Assignmnt Form) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1 L0: ASSIGN_ADD $?.sum → $3.sum, $?.i PRE_INC $?.i → $4.i $5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $?.i, 100 -> T5 JMPNZ T5, L0 RETRUN $?.sum
  • 46.
    Copyright - ©All rights reserved. Zend Technologies, Inc.46 PHP 7.1 Optimizer (Static Single Assignmnt Form) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1 L0: ASSIGN_ADD $5.sum → $3.sum, $6.i PRE_INC $6.i → $4.i $5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum
  • 47.
    Copyright - ©All rights reserved. Zend Technologies, Inc.47 PHP 7.1 Optimizer (Extended Static Single Assignmnt Form) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1 $7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i $5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum
  • 48.
    Copyright - ©All rights reserved. Zend Technologies, Inc.48 PHP 7.1 Optimizer (Extended Static Single Assignmnt Form) ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1 $7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i $5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum
  • 49.
    Copyright - ©All rights reserved. Zend Technologies, Inc.49 PHP 7.1 Optimizer (Type Propagation) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i $5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum
  • 50.
    Copyright - ©All rights reserved. Zend Technologies, Inc.50 PHP 7.1 Optimizer (Type Propagation) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i $5.sum = Phi($1.sum [long], $3.sum) $6.i = Phi($2.i [long], $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum
  • 51.
    Copyright - ©All rights reserved. Zend Technologies, Inc.51 PHP 7.1 Optimizer (Type Propagation) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i $5.sum [long] = Phi($1.sum [long], $3.sum) $6.i [long] = Phi($2.i [long], $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum
  • 52.
    Copyright - ©All rights reserved. Zend Technologies, Inc.52 PHP 7.1 Optimizer (Type Propagation) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long] = Pi($6.i [long] & RANGE[--..99]) ASSIGN_ADD $5.sum [long] → $3.sum [?], $7.i [long] PRE_INC $7.i [long] → $4.i [?] $5.sum [long] = Phi($1.sum [long], $3.sum [?]) $6.i [long] = Phi($2.i [long], $4.i [?]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long]
  • 53.
    Copyright - ©All rights reserved. Zend Technologies, Inc.53 PHP 7.1 Optimizer (Type Propagation) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long] = Pi($6.i [long] & RANGE[--..99]) ASSIGN_ADD $5.sum [long] → $3.sum [long, double], $7.i [long] PRE_INC $7.i [long] → $4.i [long, double] $5.sum [long] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long, double]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long]
  • 54.
    Copyright - ©All rights reserved. Zend Technologies, Inc.54 PHP 7.1 Optimizer (Type Propagation) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long, double] = Pi($6.i [long, double] & RANGE[--..99]) ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long, double] PRE_INC $7.i [long, double] → $4.i [long, double] $5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long, double] = Phi($2.i [long], $4.i [long, double]) IS_SMALLER $6.i [long, double], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long, double]
  • 55.
    Copyright - ©All rights reserved. Zend Technologies, Inc.55 PHP 7.1 Optimizer (Range Propagation) ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1 $7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i $5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum
  • 56.
    Copyright - ©All rights reserved. Zend Technologies, Inc.56 PHP 7.1 Optimizer (Range Propagation) ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1 $7.i [0..0] = Pi($6.i [0..0] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [?], $7.i [0..0] PRE_INC $7.i [0..0] → $4.i [?] $5.sum [0..0] = Phi($1.sum [0..0], $3.sum [?]) $6.i [0..0] = Phi($2.i [0..0], $4.i [?]) IS_SMALLER $6.i [0..0], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [0..0]
  • 57.
    Copyright - ©All rights reserved. Zend Technologies, Inc.57 PHP 7.1 Optimizer (Range Propagation) ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1 $7.i [0..0] = Pi($6.i [0..0] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [0..0], $7.i [0..0] PRE_INC $7.i [0..0] → $4.i [1..1] $5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..0]) $6.i [0..0] = Phi($2.i [0..0], $4.i [1..1]) IS_SMALLER $6.i [0..0], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [0..0]
  • 58.
    Copyright - ©All rights reserved. Zend Technologies, Inc.58 PHP 7.1 Optimizer (Range Propagation) ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1 $7.i [0..0] = Pi($6.i [0..++] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [0..0], $7.i [0..0] PRE_INC $7.i [0..0] → $4.i [1..1] $5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..0]) $6.i [0..++] = Phi($2.i [0..0], $4.i [1..1]) IS_SMALLER $6.i [0..++], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [0..0]
  • 59.
    Copyright - ©All rights reserved. Zend Technologies, Inc.59 PHP 7.1 Optimizer (Range Propagation) ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1 $7.i [0..99] = Pi($6.i [0..++] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [0..0], $7.i [0..99] PRE_INC $7.i [0..99] → $4.i [1..1] $5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..0]) $6.i [0..++] = Phi($2.i [0..0], $4.i [1..1]) IS_SMALLER $6.i [0..++], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [0..0]
  • 60.
    Copyright - ©All rights reserved. Zend Technologies, Inc.60 PHP 7.1 Optimizer (Range Propagation) ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1 $7.i [0..99] = Pi($6.i [0..++] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [0..100], $7.i [0..99] PRE_INC $7.i [0..99] → $4.i [1..100] $5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..100]) $6.i [0..++] = Phi($2.i [0..0], $4.i [1..100]) IS_SMALLER $6.i [0..++], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [0..0]
  • 61.
    Copyright - ©All rights reserved. Zend Technologies, Inc.61 PHP 7.1 Optimizer (Range Propagation) ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1 $7.i [0..99] = Pi($6.i [0..++] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..++] → $3.sum [0..++], $7.i [0..99] PRE_INC $7.i [0..99] → $4.i [1..100] $5.sum [0..++] = Phi($1.sum [0..0], $3.sum [0..++]) $6.i [0..++] = Phi($2.i [0..0], $4.i [1..100]) IS_SMALLER $6.i [0..++], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [0..++]
  • 62.
    Copyright - ©All rights reserved. Zend Technologies, Inc.62 PHP 7.1 Optimizer (Range Propagation - narrowing) ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1 $7.i [0..99] = Pi($6.i [0..100] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..++] → $3.sum [0..++], $7.i [0..99] PRE_INC $7.i [0..99] → $4.i [1..100] $5.sum [0..++] = Phi($1.sum [0..0], $3.sum [0..++]) $6.i [0..100] = Phi($2.i [0..0], $4.i [1..100]) IS_SMALLER $6.i [0..100], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [0..++]
  • 63.
    Copyright - ©All rights reserved. Zend Technologies, Inc.63 PHP 7.1 Optimizer (Range + Type Propagation) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long, double] = Pi($6.i [long, double] & RANGE[--..99]) ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long, double] PRE_INC $7.i [long, double] → $4.i [long, double] $5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long, double] = Phi($2.i [long], $4.i [long, double]) IS_SMALLER $6.i [long, double], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long, double]
  • 64.
    Copyright - ©All rights reserved. Zend Technologies, Inc.64 PHP 7.1 Optimizer (Range + Type Propagation) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long] = Pi($6.i [long] & RANGE[--..99]) ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long] PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100] $5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long, double]
  • 65.
    Copyright - ©All rights reserved. Zend Technologies, Inc.65 PHP 7.1 Optimizer (Optimization) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long] = Pi($6.i [long] & RANGE[--..99]) ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long] PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100] $5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long, double]
  • 66.
    Copyright - ©All rights reserved. Zend Technologies, Inc.66 PHP 7.1 Optimizer (Optimization) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100] $5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long, double]
  • 67.
    Copyright - ©All rights reserved. Zend Technologies, Inc.67 PHP 7.1 Optimizer (Optimization) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100] $5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long, double]
  • 68.
    Copyright - ©All rights reserved. Zend Technologies, Inc.68 PHP 7.1 Optimizer (Optimization) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC_LONG_NOOVERFLOW $7.i [long] [0..99] → $4.i [long] [1..100] $5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long, double]
  • 69.
    Copyright - ©All rights reserved. Zend Technologies, Inc.69 PHP 7.1 Optimizer (Optimization) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC_LONG_NOOVERFLOW $7.i [long] [0..99] → $4.i [long] [1..100] $5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0 RETRUN $5.sum [long, double]
  • 70.
    Copyright - ©All rights reserved. Zend Technologies, Inc.70 PHP 7.1 Optimizer (Optimization) ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1 $7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC_LONG_NOOVERFLOW $7.i [long] [0..99] → $4.i [long] [1..100] $5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER_LONG_JMPNZ $6.i [long], 100, L0 RETRUN $5.sum [long, double]
  • 71.
    Copyright - ©All rights reserved. Zend Technologies, Inc.71 PHP 7.1 Optimizer (SSA deconstruction) ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ADD $sum, $i → $sum PRE_INC_LONG_NOOVERFLOW $i L1: IS_SMALLER_LONG_JMPNZ $i, 100, L0 RETRUN $sum ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1 L0: ADD $sum, $i -> T2 ASSIGN $sum, T2 POST_INC $i -> T4 FREE T4 L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null
  • 72.
    Copyright - ©All rights reserved. Zend Technologies, Inc.72 PHP 7.1 Specialized Handlers void PRE_INC_HANDLER() { if (Z_TYPE_P(op1) != IS_LONG) { … // not integer } else { Z_LVAL_P(op1)++; if (OVERFLOW) { … // overflow } } CHECK_EXCEPTION(); NEXT_OPCODE(); } void PRE_INC_HANDLER_LONG_NO_OVERFLOW() { Z_LVAL_P(op1)++; NEXT_OPCODE(); } mov 0x4(%IP), %eax // get op1 offset incl (%FP, %eax) // increment add 0x1c, %IP // next opcode ret
  • 73.
    Copyright - ©All rights reserved. Zend Technologies, Inc.73 Что дальше? ● PHP 7.0 ● Оптимизация структур данных ● PHP 7.1 ● Анализатор потоков данных ● Вывод типов ● Глобальный оптимизатор для байт-кода PHP ● Оптимизация и Специализация интерпретатора ● PHP 7.2 ● JIT?
  • 74.
    Copyright - ©All rights reserved. Zend Technologies, Inc.74 The Computer Language Benchmarks Game (Mandelbrot) GCC-5.3 -O3 PHP/llvm-jit LuaJit-2.1.0-beta2 JavaScriptCore-1.12.3 V8-3.14.5.10 HHVM-3.13.2 (--count=2) SpiderMonrey-1.8.5 PyPy-4.0.1 Java (openjdk-1.8) PHP-7.1.0-dev LuaJit-2.1.0-beta2 (-j off) JavaScriptCore-1.12.3 (LLint) PHP-7.0.7 Java (openjdk-1.8 -Xint) Lua-5.3.2 PHP-5.6.20 Ruby-2.2.5 Python-2.7.11 HHVM-3.13.2 (Jit=false) Perl-5.22.1 0 0.5 1 1.5 2 2.5 0.011 0.011 0.013 0.014 0.016 0.019 0.027 0.030 0.046 0.092 0.098 0.190 0.227 0.243 0.300 0.363 0.609 0.940 1.036 2.063 sec Самый быстрый интерпретатор, все что быстрее с JIT. В перспективе - быстрее некуда :)
  • 75.
    Confidential - ©All rights reserved. Zend Technologies, Inc.75 Вопросы? Dmitry Stogov Principal Engineer at Zend Technologies @dstogov dmitry@zend.com www.zend.com