SlideShare a Scribd company logo
Confidential - © All rights reserved. Zend Technologies, Inc.1
Copyright - © All rights reserved. Zend Technologies, Inc.
Как мы сделали PHP 7 в два раза быстрее.
Дмитрий Стогов
HighLoad++ 2016, Москва
Principal Engineer at Zend Technologies
Copyright - © All rights reserved. Zend Technologies, Inc.2
Кто Я?
●
Познакомился с программированием в 1984
●
Работаю в ИТ с 1991
●
Первое знакомство с PHP в 2002
●
Автор Turck MMCache для PHP (eAccelerator)
●
Работаю в Zend Technologies с 2004
●
Сейчас ведущий инженер
●
Автор ext/soap и pecl/perl
●
Один из ведущих разработчиков Open Source PHP
●
Майнтейнер Zend OPcache
●
Лидер проекта PHPNG, легшего в основу PHP 7
●
Лидер разработки JIT для PHP
Copyright - © All rights reserved. Zend Technologies, Inc.3
PHP – Personal Home Page
●
Инструмент для создания персональных веб-страниц
●
Первый релиз PHP/FI 2.0 от Rasmus Lerdorf 8 июня 1995
●
В 1998 Andi Gutmans и Zeev Suraski выпустили PHP 3
●
PHP 4, основанный на Zend Engine, вышел в 2000
●
PHP 5 с переработанной ООП моделью вышел в 2004
●
ZendFramework в 2007
●
Сегодня более 70% сайтов интернета используют PHP
●
C 2010 Facebook работает над альтернативной реализацией – HHVM
●
В декабре 2015 вышел PHP 7
●
В ноябре 2016 должен выйти PHP 7.1
Copyright - © All rights reserved. Zend Technologies, Inc.4
Производительность PHP на синтетических тестах
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 - Dec 2015
7.1 - Oct 2016
HHVM-3.15.2
12.68
12.54
4.68
4.20
2.91
2.18
2.03
1.92
0.78
0.50
0.38
bench.php [sec] (чем меньше, тем лучше)
sec
PHP-7.1 еще на треть быстрее PHP-7.0, но все еще медленнее HHVM (на тестах!)
Copyright - © All rights reserved. Zend Technologies, Inc.5
Производительность PHP на реальных приложениях
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 - Dec 2015
7.1 - Oct 2016
HHVM-3.15.2
62
58
64
77
86
105
108
114
298
321
313
WordPress-3.6 Home Page [req/sec] (чем больше, тем лучше)
sec
Copyright - © All rights reserved. Zend Technologies, Inc.6
Блуждание в трех соснах (около JIT)
●
Почти два года потрачено на прототип JIT для PHP-5.5
●
Ускорение для bench.php в 10 раз
●
Ускорения для Wordpress нет (при компиляции в несколько минут)
Выводы:
●
Хороший код возможен при правильном предсказании типов
●
Предсказание типов в реальных приложениях работает плохо
●
Использование совместимых с PHP структур данных делает
генерируемый код неэффективным
Copyright - © All rights reserved. Zend Technologies, Inc.7
Что же тормозит? (WordPress/PHP 5.6)
Copyright - © All rights reserved. Zend Technologies, Inc.8
PHPNG (New Generation)
●
Проект получил свое развитие после попыток создания JIT для PHP
●
Рефакторинг (никаких нововведений, 100% совместимость с PHP 5)
●
Основная цель — достичь нового уровня производительности и
заложить базу для будущих улучшений
●
Отделился от основной ветки PHP в январе 2014
●
Две недели ушло на то, чтобы просто скомпилировать ядро
●
Еще через две недели заработал bench.php
●
Полтора месяца для обеспечения совместимости с Wordpress
●
Еще через месяц (к 9 Мая) мы открыли проект
●
В августе 2014 принят как основа для будущего PHP 7
Copyright - © All rights reserved. Zend Technologies, Inc.9
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.10
zval (PHP 5)
typedef struct _zval_struct {
union {
long lval;
double dval;
struct {
char *val;
Int len;
} str;
HashTable *ht;
struct {
zend_object_handle handle;
zend_object_handlers *handlers;
} obj;
} value;
zend_uint refcount;
zend_uchar type;
zend_uchar is_ref;
} zval;
sizeof(zval) == 24
$a = 1; $b = $a; $c = «hello»; $d = $c;
$b
$c
$a
$d
VM STACK (pointers to zvals) HEAP
string( ), rc=2
int(1), rc=2
«hello»
● read type - 2 CPU instructions
● read int value - 2 CPU instructions
● read string value - 3 CPU instructions
Copyright - © All rights reserved. Zend Technologies, Inc.11
zval (PHP 5 PHP 7)→
typedef struct _zval_struct {
union {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
struct {
zend_object_handle handle;
zend_object_handlers *handlers;
} obj;
} value;
zend_uint refcount;
zend_uchar type;
zend_uchar is_ref;
} zval;
sizeof(zval) == 24
typedef struct _zval_struct {
union {
zend_long lval;
double dval;
zend_refcounted *counted;
zend_string *str;
zend_array *arr;
zend_object *obj;
zend_resource *res;
zend_reference *ref;
zval *zv;
void *ptr;
} value;
union {
struct {
zend_uchar type;
zend_uchar type_flags;
} v;
zend_uint type_info;
};
uint32_t reserved;
} zval;
sizeof(zval) == 16
new
Copyright - © All rights reserved. Zend Technologies, Inc.12
zval (PHP 5 PHP 7)→
● read type - 1 CPU instruction
● read int value - 1 CPU instruction
● read string value - 2 CPU instructions
$b
$c
$a
$d
int(1)
string( )
int(1)
string( )
VM STACK (zvals) HEAP
string, rc=2
«hello»
$a = 1; $b = $a; $c = «hello»; $d = $c;
$b
$c
$a
$d
VM STACK (pointers to zvals) HEAP
string( ), rc=2
int(1), rc=2
«hello»
● read type - 2 CPU instructions
● read int value - 2 CPU instructions
● read string value - 3 CPU instructions
Copyright - © All rights reserved. Zend Technologies, Inc.13
zval (PHP 5 PHP 7) Copy On Write→
● no CoW for scalars – few instructions
$b
$c
$a
$d
int(2)
string( )
int(1)
string( )
VM STACK (zvals) HEAP
string, rc=2
«hello»
$a = 1; $b = $a; $c = «hello»; $d = $c; $b = 2;
$b
$c
$a
$d
VM STACK (pointers to zvals) HEAP
string( ), rc=2
int(1), rc=1
«hello»
● CoW - hundreds CPU instructions
int(2), rc=1
Copyright - © All rights reserved. Zend Technologies, Inc.14
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.15
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.16
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.17
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.18
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.19
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.20
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.21
zval (object/PHP 5)
handlers
zend_class_entry *ce
typerefcount is_ref unused
zval *propertyN
HashTable *guards
0 7 8 31 32 63
handle
...
...
...
HashTable *properies
zval *property1
...
zval
zval
HEAP
OBJECT STORE
Copyright - © All rights reserved. Zend Technologies, Inc.22
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.23
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.24
zval (IS_BOOL -> IS_FALSE + IS_TRUE)
ZEND_VM_HANDLER(43, ZEND_JMPZ,
CONST|TMP|VAR|CV, ANY)
{
long ret;
zval *val =
GET_OP1_ZVAL_PTR(BP_VAR_R);
if (Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val TSRMLS_CC);
FREE_OP1();
CHECK_EXCEPTION();
}
if (!ret) {
ZEND_VM_SET_OPCODE(
opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(43, ZEND_JMPZ,
CONST|TMP|VAR|CV, ANY)
{
zval *val =
GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
if (Z_TYPE_P(val) == IS_TRUE) {
ZEND_VM_SET_OPCODE(opline + 1);
ZEND_VM_CONTINUE();
} else if (Z_TYPE_P(val) <= IS_TRUE) {
ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
if (i_zend_is_true(val TSRMLS_CC)) {
opline++;
} else {
opline = opline->op2.jmp_addr;
}
FREE_OP1();
ZEND_VM_JMP(opline);
}
type check
value read
value check
type check
slow path
slow path
Copyright - © All rights reserved. Zend Technologies, Inc.25
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
SEND_VAL 3
SEND_VAL 5
DO_FCALL “foo”/2
RETURN null
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (pointers to zvals)
...
...
...
Copyright - © All rights reserved. Zend Technologies, Inc.26
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
SEND_VAL 3
SEND_VAL 5
DO_FCALL “foo”/2
RETURN null
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (pointers to zvals)
...
... int(3), rc=1
HEAP
Arg1:
Arg2:
Copyright - © All rights reserved. Zend Technologies, Inc.27
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
SEND_VAL 3
SEND_VAL 5
DO_FCALL “foo”/2
RETURN null
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (pointers to zvals)
... int(3), rc=1
int(5), rc=1
HEAP
Arg1:
Arg2:
Copyright - © All rights reserved. Zend Technologies, Inc.28
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
SEND_VAL 3
SEND_VAL 5
DO_FCALL “foo”/2
RETURN null
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (pointers to zvals)
CALL FRAME
...
...
...
... int(3), rc=1
int(5), rc=1
HEAP
Arg1:
Arg2:
$a:
$b:
Copyright - © All rights reserved. Zend Technologies, Inc.29
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
SEND_VAL 3
SEND_VAL 5
DO_FCALL “foo”/2
RETURN null
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (pointers to zvals)
CALL FRAME
...
...
... int(3), rc=2
int(5), rc=1
HEAP
Arg1:
Arg2:
$a:
$b:
Copyright - © All rights reserved. Zend Technologies, Inc.30
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
SEND_VAL 3
SEND_VAL 5
DO_FCALL “foo”/2
RETURN null
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (pointers to zvals)
CALL FRAME
...
... int(3), rc=2
int(5), rc=2
HEAP
Arg1:
Arg2:
$a:
$b:
Copyright - © All rights reserved. Zend Technologies, Inc.31
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
SEND_VAL 3
SEND_VAL 5
DO_FCALL “foo”/2
RETURN null
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (pointers to zvals)
CALL FRAME
int(8)
... int(3), rc=2
int(5), rc=2
HEAP
Arg1:
Arg2:
$a:
$b:
Copyright - © All rights reserved. Zend Technologies, Inc.32
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
SEND_VAL 3
SEND_VAL 5
DO_FCALL “foo”/2
RETURN null
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (pointers to zvals)
CALL FRAME
int(8)
... int(3), rc=2
int(5), rc=2
HEAP
Arg1:
Arg2:
$a:
$b:
Copyright - © All rights reserved. Zend Technologies, Inc.33
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,$b,TMP1
RETURN TMP1
foo:
_main:
SEND_VAL 3
SEND_VAL 5
DO_FCALL “foo”/2
RETURN null
function foo($a, $b) {
return $a + $b;
}
foo(3, 5);
VM STACK (pointers to zvals)
...
...
...
Copyright - © All rights reserved. Zend Technologies, Inc.34
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
new instruction embedded zvals
instead of pointers
Copyright - © All rights reserved. Zend Technologies, Inc.35
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.36
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.37
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.38
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.39
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.40
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.41
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
NOTE:
● func_get_arg*() changed behavior
● function foo($_, $_) {} is not allowed
Copyright - © All rights reserved. Zend Technologies, Inc.42
Новый менеджер памяти
●
В PHP 5 менеджмент памяти потребляет более 20% процессорного времени
(на Wordpress)
●
Новый ММ отказался от алгоритмов dlmalloc и перешел на что-то,
напоминающее jemalloc
●
Уменьшены издержки памяти на служебную информацию
●
Использование поиска по битовым маскам вместо обхода списков и деревьев
●
Лучшее использование кэшей CPU
●
Специализация под часто используемые размеры блоков
●
Полностью прозрачная реализация
●
Накладные расходы ММ уменьшены до 5%
Copyright - © All rights reserved. Zend Technologies, Inc.43
Множество мелких усовершенствований
●
Быстрое API для разбора параметров внутренних функций
●
Новые инструкции VM (конкатенация строк, специализация, супер-инструкции)
●
Некоторые внутренние функции превращены в инструкции VM (strlen, is_int)
●
Использование регистров CPU под регистры VM (IP и FP)
●
Новый API для итерации по HashTable
●
Оптимизация функций дублирования и удаления массивов
●
Использование счетчиков ссылок вместо копирования везде, где можно
●
PCRE JIT
●
Оптимизация внутренних функций
●
Оптимизация serialize()
●
Уменьшение размера кода и обрабатываемых данных
Copyright - © All rights reserved. Zend Technologies, Inc.44
Откуда ускорение? (WordPress/PHP 7.0)
Copyright - © All rights reserved. Zend Technologies, Inc.45
PHP 5.6 PHP 7.0 улучшение
VM 27% 19,494M 46% 9,005M 2 раза
alloc 22% 15,575M 5% 905M 17 раз
hash 13% 9,590M 13% 2.450M 4 раза
libc 6% 4.585M 8% 1,598M 3 раза
Total: 100% 70,798M 100% 19,462M 3.5 раз
Откуда ускорение? (WordPress)
Copyright - © All rights reserved. Zend Technologies, Inc.46
Производительность PHP 7
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov
0
5
10
15
20
25
30
24.04 24.04 24.04
22.64
18.62
16.37
15.28 14.86
14.16 13.83 13.56 13.28
12.58 12.39
11.67 11.48 11.08 11.04 10.88 10.69 10.5 10.4 10.4
sec
●
Время исполнения 1000 запросов к Wordpress-3.6.0
●
php-cgi -T 1000 /.../wordpress/index.php > /dev/null
Copyright - © All rights reserved. Zend Technologies, Inc.47
PHP 5 против PHP 7 против HHVM
ZF1 Hello
ZF2 Test
Magento (home)
SugarCRM (login)
Laravel
Drupal 7
Drupal 8
Mediawiki
Wordpress-4.1
0
0.5
1
1.5
2
2.5
3
PHP 5.6
PHP 7.0.0
HHVM 3.10.0
Copyright - © All rights reserved. Zend Technologies, Inc.48
PHP 5 против PHP 7 против HHVM (версия Facebook)
Copyright - © All rights reserved. Zend Technologies, Inc.49
Badoo перешли на PHP 7.0 и сэкономили $1M
Copyright - © All rights reserved. Zend Technologies, Inc.50
Что дальше?
●
PHP 7.0
●
Оптимизация структур данных
●
PHP 7.1
●
Анализатор потоков данных
●
Вывод типов
●
Глобальный оптимизатор для байт-кода PHP
●
Оптимизация и cпециализация интерпретатора
Copyright - © All rights reserved. Zend Technologies, Inc.51
PHP 7.1
●
Уже вышел RC3 (29-го сентября 2016)
●
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.52
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.53
PHP 7.1 Optimizer (bytecode)
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
RETURN $sum
RETURN null
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.54
PHP 7.1 Optimizer (trivial optimization)
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
RETURN $sum
RETURN null
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.55
PHP 7.1 Optimizer (trivial optimization)
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
RETURN $sum
RETURN null
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.56
PHP 7.1 Optimizer (trivial optimization)
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
RETURN $sum
RETURN null
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.57
PHP 7.1 Optimizer (trivial optimization)
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
RETURN $sum
RETURN null
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.58
PHP 7.1 Optimizer (trivial optimization)
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
RETURN $sum
RETURN null
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.59
PHP 7.1 Optimizer (trivial optimization)
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
RETURN $sum
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.60
PHP 7.1 Optimizer (Control Flow Graph)
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
RETURN $sum
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.61
PHP 7.1 Optimizer (Control Flow Graph)
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
RETURN $sum
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.62
PHP 7.1 Optimizer (Control Flow Graph)
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
RETURN $sum
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.63
PHP 7.1 Optimizer (Control Flow Graph)
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
RETURN $sum
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.64
PHP 7.1 Optimizer (Static Single Assignmnt Form)
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
RETURN $?.sum
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.65
PHP 7.1 Optimizer (Static Single Assignmnt Form)
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
RETURN $?.sum
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.66
PHP 7.1 Optimizer (Static Single Assignmnt Form)
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
RETURN $5.sum
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.67
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
RETURN $5.sum
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
Copyright - © All rights reserved. Zend Technologies, Inc.68
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
RETURN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.69
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
RETURN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.70
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
RETURN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.71
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
RETURN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.72
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
RETURN $5.sum [long]
Copyright - © All rights reserved. Zend Technologies, Inc.73
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
RETURN $5.sum [long]
Copyright - © All rights reserved. Zend Technologies, Inc.74
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
RETURN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.75
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
RETURN $5.sum
Copyright - © All rights reserved. Zend Technologies, Inc.76
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..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
RETURN $5.sum [0..++]
Copyright - © All rights reserved. Zend Technologies, Inc.77
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
RETURN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.78
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
RETURN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.79
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
RETURN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.80
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
RETURN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.81
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
RETURN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.82
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
RETURN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.83
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
RETURN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.84
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
RETURN $5.sum [long, double]
Copyright - © All rights reserved. Zend Technologies, Inc.85
PHP 7.1 Optimizer (final result)
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
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
RETURN $sum
RETURN null
Copyright - © All rights reserved. Zend Technologies, Inc.86
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.87
Что дальше?
●
JIT (для PHP 7.2 или PHP 8)
●
Проект стартовал в августе 2016 и находится в самом начале пути
●
Для генерации машинного кода используется DynAsm из LuaJIT-2
●
https://github.com/zendtech/php-src/tree/jit-dynasm/ext/opcache/jit
●
Уже сегодня ускорение на bench.php в 3 раза (в 75 раз быстрее PHP 5.0)
●
На реальных приложениях ускорения нет
●
Предыдущая попытка, основанная на LLVM, давала на bench.php 2.5
кратное ускорение
●
На реальных приложениях была не применима (очень долго
компилировала)
●
https://github.com/zendtech/php-src/tree/zend-jit/ext/opcache/jit
Copyright - © All rights reserved. Zend Technologies, Inc.88
PHP ? - JIT
JIT$sum:
sub $0xc, %esp
mov $0x0, 0x30(%esi)
mov $0x4, 0x38(%esi)
mov $0x0, 0x40(%esi)
mov $0x4, 0x48(%esi)
jmp .L3
.L1:
cmp $0x4, 0x38(%esi)
jnz .L6
mov 0x30(%esi), %eax
add 0x40(%esi), %eax
jo .L5
mov %eax, 0x30(%esi)
.L2:
inc 0x40(%esi)
.L3
mov $0xeca7fa64, %edi
cmp $0x0, EG(vm_interrupt)
jnz JIT$$interrupt_handler
mov 0x40(%esi), %eax
cmp $0x64, %eax
jl .L1
...
$i++
$i < 100
$sum = 0
$i =0
<?php
function sum() {
$sum = 0;
for ($i = 0; $i < 100; $i++) {
$sum = $sum + $i;
}
return $sum;
}
$sum = $sum + $i
Copyright - © All rights reserved. Zend Technologies, Inc.89
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.15.2 (--count=2)
PHP/dynasm-jit
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.025
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.
Старый JIT (быстрее некуда :)
Новый JIT
Confidential - © All rights reserved. Zend Technologies, Inc.90
Вопросы?
Dmitry Stogov
Principal Engineer at Zend Technologies
@dstogov
dmitry@zend.com
www.zend.com
Copyright - © All rights reserved. Zend Technologies, Inc.91
Хотите еще быстрее? – HUGE TLB или HUGE PAGE
●
CPU использует виртуальную память с 4KB страницам
●
CPU TLB cahce содержит всего 64-512 слотов => 256KB-2M
●
TLB промахи требуют много времени для обработки
●
Решение – страницы размером 2MB
●
PHP-7, если может, использует 2M страницы для менеджера памяти и разделяемой
памяти opcahce, где хранятся скомпилированные скрипты
●
opcache.huge_tlb_caches=1 так же копирует сегмент кода в Huge Pages
●
grep "Huge" /proc/meminfo
AnonHugePages: 0 kB
HugePages_Total: 512
HugePages_Free: 497
HugePages_Rsvd: 55
HugePages_Surp: 0
Hugepagesize: 2048 kB
●
https://wiki.debian.org/Hugepages#Enabling_HugeTlbPage
Copyright - © All rights reserved. Zend Technologies, Inc.92
Хотите еще быстрее? – 32-битная сборка?
●
Почти все современные процессоры 64-битные
●
Почти все современные ОС 64-битные
●
X86_64 может обрабатывать данные, используя меньшее количество
инструкций
●
X86_64 предлагает 8 дополнительных регистров общего назначения
●
Но: 64-битные адреса занимают больше места, требуют больше памяти, что
ведет к увеличению промахов в CPU кэше и уменьшению производительности.
●
Использование 32-битного PHP (gcc -m32 -sse2) обычно дает 5% прирост
Copyright - © All rights reserved. Zend Technologies, Inc.93
Хотите еще быстрее? – PGO/FDO сборка
●
make prof-gen
●
sapi/cgi/php-cgi -T 3000 /.../wordpress/index.php > /dev/null
●
make prof-clean
●
make prof-use
●
Скорость +8%
●
Объем кода -8% (size sapi/cli/php)
Copyright - © All rights reserved. Zend Technologies, Inc.94
Хотите еще быстрее? – opcache.file_cahe
●
PHP7 opcache дает возможность дополнительно кэшировать скрипты на диске
(запрещено по умолчанию)
●
mkdir /tmp/opcahe
●
Добавить opcache.file_cahce=/tmp/opcache в php.ini
●
Уменьшает пиковые нагрузки при рестарте PHP и переполнении SHM кэша
●
Улучшает время отклика в эти моменты в 2-3 раза
●
Может использоваться в сценариях апгрейда (можно предварительно
загрузить дисковый кэш)
●
file_cache может работать вообще без SHM
Copyright - © All rights reserved. Zend Technologies, Inc.95
Не забывайте про оптимизацию всего стека
●
Оптимизация вашего PHP приложения даст наибольший результат
●
Кэшируйте все, что можно
●
Правильно выбирайте количество PHP процессов (больше – не значит лучше)
●
MariaDB, сконфигурированная по умолчанию, замедляла Wordpress почти на
30%
query_cache_size=16M
query_cache_type=1
●
TCP stack
●
Не отключайте Hyper-Threading

More Related Content

What's hot (20)

Node.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitter
Simen Li
 
Distributed systems at ok.ru #rigadevday
Distributed systems at ok.ru #rigadevday
odnoklassniki.ru
 
My talk at Linux Piter 2015
My talk at Linux Piter 2015
Alex Chistyakov
 
Being closer to Cassandra by Oleg Anastasyev. Talk at Cassandra Summit EU 2013
Being closer to Cassandra by Oleg Anastasyev. Talk at Cassandra Summit EU 2013
odnoklassniki.ru
 
HandlerSocket - A NoSQL plugin for MySQL
HandlerSocket - A NoSQL plugin for MySQL
Jui-Nan Lin
 
REDIS intro and how to use redis
REDIS intro and how to use redis
Kris Jeong
 
Java Runtime: повседневные обязанности JVM
Java Runtime: повседневные обязанности JVM
odnoklassniki.ru
 
スローダウン、ハングを一発解決 スレッドダンプはトラブルシューティングの味方 #wlstudy
スローダウン、ハングを一発解決 スレッドダンプはトラブルシューティングの味方 #wlstudy
Yusuke Yamamoto
 
Everything you wanted to know about Stack Traces and Heap Dumps
Everything you wanted to know about Stack Traces and Heap Dumps
Andrei Pangin
 
Indexierung mit MySQL
Indexierung mit MySQL
FromDual GmbH
 
Event loop
Event loop
codepitbull
 
2015.07.16 Способы диагностики PostgreSQL
2015.07.16 Способы диагностики PostgreSQL
dev1ant
 
How to cook lettuce @Java casual
How to cook lettuce @Java casual
Go Hagiwara
 
Mасштабирование микросервисов на Go, Matt Heath (Hailo)
Mасштабирование микросервисов на Go, Matt Heath (Hailo)
Ontico
 
MySQL Replication Troubleshooting for Oracle DBAs
MySQL Replication Troubleshooting for Oracle DBAs
Sveta Smirnova
 
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
John Kim
 
Доклад Антона Поварова "Go in Badoo" с Golang Meetup
Доклад Антона Поварова "Go in Badoo" с Golang Meetup
Badoo Development
 
Multithreading in Node.js and JavaScript
Multithreading in Node.js and JavaScript
Timur Shemsedinov
 
Large Scale Log collection using LogStash & mongoDB
Large Scale Log collection using LogStash & mongoDB
Gaurav Bhardwaj
 
Kettunen, miaubiz fuzzing at scale and in style
Kettunen, miaubiz fuzzing at scale and in style
DefconRussia
 
Node.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitter
Simen Li
 
Distributed systems at ok.ru #rigadevday
Distributed systems at ok.ru #rigadevday
odnoklassniki.ru
 
My talk at Linux Piter 2015
My talk at Linux Piter 2015
Alex Chistyakov
 
Being closer to Cassandra by Oleg Anastasyev. Talk at Cassandra Summit EU 2013
Being closer to Cassandra by Oleg Anastasyev. Talk at Cassandra Summit EU 2013
odnoklassniki.ru
 
HandlerSocket - A NoSQL plugin for MySQL
HandlerSocket - A NoSQL plugin for MySQL
Jui-Nan Lin
 
REDIS intro and how to use redis
REDIS intro and how to use redis
Kris Jeong
 
Java Runtime: повседневные обязанности JVM
Java Runtime: повседневные обязанности JVM
odnoklassniki.ru
 
スローダウン、ハングを一発解決 スレッドダンプはトラブルシューティングの味方 #wlstudy
スローダウン、ハングを一発解決 スレッドダンプはトラブルシューティングの味方 #wlstudy
Yusuke Yamamoto
 
Everything you wanted to know about Stack Traces and Heap Dumps
Everything you wanted to know about Stack Traces and Heap Dumps
Andrei Pangin
 
Indexierung mit MySQL
Indexierung mit MySQL
FromDual GmbH
 
2015.07.16 Способы диагностики PostgreSQL
2015.07.16 Способы диагностики PostgreSQL
dev1ant
 
How to cook lettuce @Java casual
How to cook lettuce @Java casual
Go Hagiwara
 
Mасштабирование микросервисов на Go, Matt Heath (Hailo)
Mасштабирование микросервисов на Go, Matt Heath (Hailo)
Ontico
 
MySQL Replication Troubleshooting for Oracle DBAs
MySQL Replication Troubleshooting for Oracle DBAs
Sveta Smirnova
 
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
John Kim
 
Доклад Антона Поварова "Go in Badoo" с Golang Meetup
Доклад Антона Поварова "Go in Badoo" с Golang Meetup
Badoo Development
 
Multithreading in Node.js and JavaScript
Multithreading in Node.js and JavaScript
Timur Shemsedinov
 
Large Scale Log collection using LogStash & mongoDB
Large Scale Log collection using LogStash & mongoDB
Gaurav Bhardwaj
 
Kettunen, miaubiz fuzzing at scale and in style
Kettunen, miaubiz fuzzing at scale and in style
DefconRussia
 

Similar to Как мы сделали PHP 7 в два раза быстрее PHP 5 / Дмитрий Стогов (Zend Technologies) (20)

PHP7 - The New Engine for old good train
PHP7 - The New Engine for old good train
Xinchen Hui
 
PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)
Nikita Popov
 
PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)
Nikita Popov
 
PHP 7 performances from PHP 5
PHP 7 performances from PHP 5
julien pauli
 
The secret of PHP7's Performance
The secret of PHP7's Performance
Xinchen Hui
 
The why and how of moving to PHP 5.4/5.5
The why and how of moving to PHP 5.4/5.5
Wim Godden
 
Php Extensions for Dummies
Php Extensions for Dummies
Elizabeth Smith
 
Php’s guts
Php’s guts
Elizabeth Smith
 
Php in 2013 (Web-5 2013 conference)
Php in 2013 (Web-5 2013 conference)
julien pauli
 
The why and how of moving to php 5.4/5.5
The why and how of moving to php 5.4/5.5
Wim Godden
 
PHP5.5 is Here
PHP5.5 is Here
julien pauli
 
PHP in 2018 - Q1 - AFUP Limoges
PHP in 2018 - Q1 - AFUP Limoges
✅ William Pinaud
 
Php extensions
Php extensions
Elizabeth Smith
 
Zend Framework Workshop
Zend Framework Workshop
10n Software, LLC
 
The why and how of moving to php 5.4
The why and how of moving to php 5.4
Wim Godden
 
Php7 extensions workshop
Php7 extensions workshop
julien pauli
 
ZendCon 08 php 5.3
ZendCon 08 php 5.3
webhostingguy
 
The new features of PHP 7
The new features of PHP 7
Zend by Rogue Wave Software
 
The new features of PHP 7 - Enrico Zimuel - Codemotion Milan 2016
The new features of PHP 7 - Enrico Zimuel - Codemotion Milan 2016
Codemotion
 
Symfony live 2017_php7_performances
Symfony live 2017_php7_performances
julien pauli
 
PHP7 - The New Engine for old good train
PHP7 - The New Engine for old good train
Xinchen Hui
 
PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)
Nikita Popov
 
PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)
Nikita Popov
 
PHP 7 performances from PHP 5
PHP 7 performances from PHP 5
julien pauli
 
The secret of PHP7's Performance
The secret of PHP7's Performance
Xinchen Hui
 
The why and how of moving to PHP 5.4/5.5
The why and how of moving to PHP 5.4/5.5
Wim Godden
 
Php Extensions for Dummies
Php Extensions for Dummies
Elizabeth Smith
 
Php in 2013 (Web-5 2013 conference)
Php in 2013 (Web-5 2013 conference)
julien pauli
 
The why and how of moving to php 5.4/5.5
The why and how of moving to php 5.4/5.5
Wim Godden
 
PHP in 2018 - Q1 - AFUP Limoges
PHP in 2018 - Q1 - AFUP Limoges
✅ William Pinaud
 
The why and how of moving to php 5.4
The why and how of moving to php 5.4
Wim Godden
 
Php7 extensions workshop
Php7 extensions workshop
julien pauli
 
The new features of PHP 7 - Enrico Zimuel - Codemotion Milan 2016
The new features of PHP 7 - Enrico Zimuel - Codemotion Milan 2016
Codemotion
 
Symfony live 2017_php7_performances
Symfony live 2017_php7_performances
julien pauli
 
Ad

More from Ontico (20)

One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
Ontico
 
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Ontico
 
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Ontico
 
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Ontico
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Ontico
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Ontico
 
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Ontico
 
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
Ontico
 
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
Ontico
 
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Ontico
 
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Ontico
 
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Ontico
 
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Ontico
 
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
Ontico
 
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Ontico
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Ontico
 
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
Ontico
 
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Ontico
 
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Ontico
 
Как мы учились чинить самолеты в воздухе / Евгений Коломеец (Virtuozzo)
Как мы учились чинить самолеты в воздухе / Евгений Коломеец (Virtuozzo)
Ontico
 
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
Ontico
 
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Ontico
 
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Ontico
 
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Ontico
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Ontico
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Ontico
 
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Ontico
 
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
Ontico
 
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
Ontico
 
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Ontico
 
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Ontico
 
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Ontico
 
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Ontico
 
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
Ontico
 
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Ontico
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Ontico
 
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
Ontico
 
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Ontico
 
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Ontico
 
Как мы учились чинить самолеты в воздухе / Евгений Коломеец (Virtuozzo)
Как мы учились чинить самолеты в воздухе / Евгений Коломеец (Virtuozzo)
Ontico
 
Ad

Recently uploaded (20)

Rearchitecturing a 9-year-old legacy Laravel application.pdf
Rearchitecturing a 9-year-old legacy Laravel application.pdf
Takumi Amitani
 
Fundamentals of Digital Design_Class_12th April.pptx
Fundamentals of Digital Design_Class_12th April.pptx
drdebarshi1993
 
Présentation_gestion[1] [Autosaved].pptx
Présentation_gestion[1] [Autosaved].pptx
KHADIJAESSAKET
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
djiceramil
 
IntroSlides-June-GDG-Cloud-Munich community [email protected]
IntroSlides-June-GDG-Cloud-Munich community [email protected]
Luiz Carneiro
 
02 - Ethics & Professionalism - BEM, IEM, MySET.PPT
02 - Ethics & Professionalism - BEM, IEM, MySET.PPT
SharinAbGhani1
 
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
João Esperancinha
 
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
CenterEnamel
 
A Comprehensive Investigation into the Accuracy of Soft Computing Tools for D...
A Comprehensive Investigation into the Accuracy of Soft Computing Tools for D...
Journal of Soft Computing in Civil Engineering
 
Fundamentals of Digital Design_Class_21st May - Copy.pptx
Fundamentals of Digital Design_Class_21st May - Copy.pptx
drdebarshi1993
 
Understanding Amplitude Modulation : A Guide
Understanding Amplitude Modulation : A Guide
CircuitDigest
 
WIRELESS COMMUNICATION SECURITY AND IT’S PROTECTION METHODS
WIRELESS COMMUNICATION SECURITY AND IT’S PROTECTION METHODS
samueljackson3773
 
OCS Group SG - HPHT Well Design and Operation - SN.pdf
OCS Group SG - HPHT Well Design and Operation - SN.pdf
Muanisa Waras
 
Flow Chart Proses Bisnis prosscesss.docx
Flow Chart Proses Bisnis prosscesss.docx
rifka575530
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
djiceramil
 
FINAL 2013 Module 20 Corrosion Control and Sequestering PPT Slides.pptx
FINAL 2013 Module 20 Corrosion Control and Sequestering PPT Slides.pptx
kippcam
 
SEW make Brake BE05 – BE30 Brake – Repair Kit
SEW make Brake BE05 – BE30 Brake – Repair Kit
projectultramechanix
 
How Binning Affects LED Performance & Consistency.pdf
How Binning Affects LED Performance & Consistency.pdf
Mina Anis
 
COMPOSITE COLUMN IN STEEL CONCRETE COMPOSITES.ppt
COMPOSITE COLUMN IN STEEL CONCRETE COMPOSITES.ppt
ravicivil
 
NALCO Green Anode Plant,Compositions of CPC,Pitch
NALCO Green Anode Plant,Compositions of CPC,Pitch
arpitprachi123
 
Rearchitecturing a 9-year-old legacy Laravel application.pdf
Rearchitecturing a 9-year-old legacy Laravel application.pdf
Takumi Amitani
 
Fundamentals of Digital Design_Class_12th April.pptx
Fundamentals of Digital Design_Class_12th April.pptx
drdebarshi1993
 
Présentation_gestion[1] [Autosaved].pptx
Présentation_gestion[1] [Autosaved].pptx
KHADIJAESSAKET
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
djiceramil
 
02 - Ethics & Professionalism - BEM, IEM, MySET.PPT
02 - Ethics & Professionalism - BEM, IEM, MySET.PPT
SharinAbGhani1
 
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
João Esperancinha
 
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
CenterEnamel
 
Fundamentals of Digital Design_Class_21st May - Copy.pptx
Fundamentals of Digital Design_Class_21st May - Copy.pptx
drdebarshi1993
 
Understanding Amplitude Modulation : A Guide
Understanding Amplitude Modulation : A Guide
CircuitDigest
 
WIRELESS COMMUNICATION SECURITY AND IT’S PROTECTION METHODS
WIRELESS COMMUNICATION SECURITY AND IT’S PROTECTION METHODS
samueljackson3773
 
OCS Group SG - HPHT Well Design and Operation - SN.pdf
OCS Group SG - HPHT Well Design and Operation - SN.pdf
Muanisa Waras
 
Flow Chart Proses Bisnis prosscesss.docx
Flow Chart Proses Bisnis prosscesss.docx
rifka575530
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
djiceramil
 
FINAL 2013 Module 20 Corrosion Control and Sequestering PPT Slides.pptx
FINAL 2013 Module 20 Corrosion Control and Sequestering PPT Slides.pptx
kippcam
 
SEW make Brake BE05 – BE30 Brake – Repair Kit
SEW make Brake BE05 – BE30 Brake – Repair Kit
projectultramechanix
 
How Binning Affects LED Performance & Consistency.pdf
How Binning Affects LED Performance & Consistency.pdf
Mina Anis
 
COMPOSITE COLUMN IN STEEL CONCRETE COMPOSITES.ppt
COMPOSITE COLUMN IN STEEL CONCRETE COMPOSITES.ppt
ravicivil
 
NALCO Green Anode Plant,Compositions of CPC,Pitch
NALCO Green Anode Plant,Compositions of CPC,Pitch
arpitprachi123
 

Как мы сделали PHP 7 в два раза быстрее PHP 5 / Дмитрий Стогов (Zend Technologies)

  • 1. Confidential - © All rights reserved. Zend Technologies, Inc.1 Copyright - © All rights reserved. Zend Technologies, Inc. Как мы сделали PHP 7 в два раза быстрее. Дмитрий Стогов HighLoad++ 2016, Москва Principal Engineer at Zend Technologies
  • 2. Copyright - © All rights reserved. Zend Technologies, Inc.2 Кто Я? ● Познакомился с программированием в 1984 ● Работаю в ИТ с 1991 ● Первое знакомство с PHP в 2002 ● Автор Turck MMCache для PHP (eAccelerator) ● Работаю в Zend Technologies с 2004 ● Сейчас ведущий инженер ● Автор ext/soap и pecl/perl ● Один из ведущих разработчиков Open Source PHP ● Майнтейнер Zend OPcache ● Лидер проекта PHPNG, легшего в основу PHP 7 ● Лидер разработки JIT для PHP
  • 3. Copyright - © All rights reserved. Zend Technologies, Inc.3 PHP – Personal Home Page ● Инструмент для создания персональных веб-страниц ● Первый релиз PHP/FI 2.0 от Rasmus Lerdorf 8 июня 1995 ● В 1998 Andi Gutmans и Zeev Suraski выпустили PHP 3 ● PHP 4, основанный на Zend Engine, вышел в 2000 ● PHP 5 с переработанной ООП моделью вышел в 2004 ● ZendFramework в 2007 ● Сегодня более 70% сайтов интернета используют PHP ● C 2010 Facebook работает над альтернативной реализацией – HHVM ● В декабре 2015 вышел PHP 7 ● В ноябре 2016 должен выйти PHP 7.1
  • 4. Copyright - © All rights reserved. Zend Technologies, Inc.4 Производительность PHP на синтетических тестах 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 - Dec 2015 7.1 - Oct 2016 HHVM-3.15.2 12.68 12.54 4.68 4.20 2.91 2.18 2.03 1.92 0.78 0.50 0.38 bench.php [sec] (чем меньше, тем лучше) sec PHP-7.1 еще на треть быстрее PHP-7.0, но все еще медленнее HHVM (на тестах!)
  • 5. Copyright - © All rights reserved. Zend Technologies, Inc.5 Производительность PHP на реальных приложениях 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 - Dec 2015 7.1 - Oct 2016 HHVM-3.15.2 62 58 64 77 86 105 108 114 298 321 313 WordPress-3.6 Home Page [req/sec] (чем больше, тем лучше) sec
  • 6. Copyright - © All rights reserved. Zend Technologies, Inc.6 Блуждание в трех соснах (около JIT) ● Почти два года потрачено на прототип JIT для PHP-5.5 ● Ускорение для bench.php в 10 раз ● Ускорения для Wordpress нет (при компиляции в несколько минут) Выводы: ● Хороший код возможен при правильном предсказании типов ● Предсказание типов в реальных приложениях работает плохо ● Использование совместимых с PHP структур данных делает генерируемый код неэффективным
  • 7. Copyright - © All rights reserved. Zend Technologies, Inc.7 Что же тормозит? (WordPress/PHP 5.6)
  • 8. Copyright - © All rights reserved. Zend Technologies, Inc.8 PHPNG (New Generation) ● Проект получил свое развитие после попыток создания JIT для PHP ● Рефакторинг (никаких нововведений, 100% совместимость с PHP 5) ● Основная цель — достичь нового уровня производительности и заложить базу для будущих улучшений ● Отделился от основной ветки PHP в январе 2014 ● Две недели ушло на то, чтобы просто скомпилировать ядро ● Еще через две недели заработал bench.php ● Полтора месяца для обеспечения совместимости с Wordpress ● Еще через месяц (к 9 Мая) мы открыли проект ● В августе 2014 принят как основа для будущего PHP 7
  • 9. Copyright - © All rights reserved. Zend Technologies, Inc.9 PHP 7.0 ● Было решено выпускать PHP 7 после PHP 5, пропустив PHP 6 ● GA релиз состоялся в декабре 2015 ● Сейчас доступен PHP-7.0.7 ● Возможность определять скалярные типы аргументов функций и возвращаемых значений ● Исключения вместо фатальных ошибок ● Анонимные классы ● Zero-cost assert() ● Новые операторы и функции (<=>, ??) ● Чистка неконсистентностей
  • 10. Copyright - © All rights reserved. Zend Technologies, Inc.10 zval (PHP 5) typedef struct _zval_struct { union { long lval; double dval; struct { char *val; Int len; } str; HashTable *ht; struct { zend_object_handle handle; zend_object_handlers *handlers; } obj; } value; zend_uint refcount; zend_uchar type; zend_uchar is_ref; } zval; sizeof(zval) == 24 $a = 1; $b = $a; $c = «hello»; $d = $c; $b $c $a $d VM STACK (pointers to zvals) HEAP string( ), rc=2 int(1), rc=2 «hello» ● read type - 2 CPU instructions ● read int value - 2 CPU instructions ● read string value - 3 CPU instructions
  • 11. Copyright - © All rights reserved. Zend Technologies, Inc.11 zval (PHP 5 PHP 7)→ typedef struct _zval_struct { union { long lval; double dval; struct { char *val; int len; } str; HashTable *ht; struct { zend_object_handle handle; zend_object_handlers *handlers; } obj; } value; zend_uint refcount; zend_uchar type; zend_uchar is_ref; } zval; sizeof(zval) == 24 typedef struct _zval_struct { union { zend_long lval; double dval; zend_refcounted *counted; zend_string *str; zend_array *arr; zend_object *obj; zend_resource *res; zend_reference *ref; zval *zv; void *ptr; } value; union { struct { zend_uchar type; zend_uchar type_flags; } v; zend_uint type_info; }; uint32_t reserved; } zval; sizeof(zval) == 16 new
  • 12. Copyright - © All rights reserved. Zend Technologies, Inc.12 zval (PHP 5 PHP 7)→ ● read type - 1 CPU instruction ● read int value - 1 CPU instruction ● read string value - 2 CPU instructions $b $c $a $d int(1) string( ) int(1) string( ) VM STACK (zvals) HEAP string, rc=2 «hello» $a = 1; $b = $a; $c = «hello»; $d = $c; $b $c $a $d VM STACK (pointers to zvals) HEAP string( ), rc=2 int(1), rc=2 «hello» ● read type - 2 CPU instructions ● read int value - 2 CPU instructions ● read string value - 3 CPU instructions
  • 13. Copyright - © All rights reserved. Zend Technologies, Inc.13 zval (PHP 5 PHP 7) Copy On Write→ ● no CoW for scalars – few instructions $b $c $a $d int(2) string( ) int(1) string( ) VM STACK (zvals) HEAP string, rc=2 «hello» $a = 1; $b = $a; $c = «hello»; $d = $c; $b = 2; $b $c $a $d VM STACK (pointers to zvals) HEAP string( ), rc=2 int(1), rc=1 «hello» ● CoW - hundreds CPU instructions int(2), rc=1
  • 14. Copyright - © All rights reserved. Zend Technologies, Inc.14 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
  • 15. Copyright - © All rights reserved. Zend Technologies, Inc.15 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
  • 16. Copyright - © All rights reserved. Zend Technologies, Inc.16 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
  • 17. Copyright - © All rights reserved. Zend Technologies, Inc.17 zval (array) flags value type reserved typerefcount flags gc_info HashTable ● IS_ARRAY_IMMUTABLE 0 7 8 31 32 63
  • 18. Copyright - © All rights reserved. Zend Technologies, Inc.18 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»
  • 19. Copyright - © All rights reserved. Zend Technologies, Inc.19 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
  • 20. Copyright - © All rights reserved. Zend Technologies, Inc.20 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 (Неизменяемые массивы)
  • 21. Copyright - © All rights reserved. Zend Technologies, Inc.21 zval (object/PHP 5) handlers zend_class_entry *ce typerefcount is_ref unused zval *propertyN HashTable *guards 0 7 8 31 32 63 handle ... ... ... HashTable *properies zval *property1 ... zval zval HEAP OBJECT STORE
  • 22. Copyright - © All rights reserved. Zend Technologies, Inc.22 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
  • 23. Copyright - © All rights reserved. Zend Technologies, Inc.23 zval (reference) flags value type reserved typerefcount flags gc_info zval val 0 7 8 31 32 63
  • 24. Copyright - © All rights reserved. Zend Technologies, Inc.24 zval (IS_BOOL -> IS_FALSE + IS_TRUE) ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY) { long ret; zval *val = GET_OP1_ZVAL_PTR(BP_VAR_R); if (Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); } else { ret = i_zend_is_true(val TSRMLS_CC); FREE_OP1(); CHECK_EXCEPTION(); } if (!ret) { ZEND_VM_SET_OPCODE( opline->op2.jmp_addr); ZEND_VM_CONTINUE(); } ZEND_VM_NEXT_OPCODE(); } ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY) { zval *val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if (Z_TYPE_P(val) == IS_TRUE) { ZEND_VM_SET_OPCODE(opline + 1); ZEND_VM_CONTINUE(); } else if (Z_TYPE_P(val) <= IS_TRUE) { ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); ZEND_VM_CONTINUE(); } if (i_zend_is_true(val TSRMLS_CC)) { opline++; } else { opline = opline->op2.jmp_addr; } FREE_OP1(); ZEND_VM_JMP(opline); } type check value read value check type check slow path slow path
  • 25. Copyright - © All rights reserved. Zend Technologies, Inc.25 VM Calling Convention (PHP 5.*) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: SEND_VAL 3 SEND_VAL 5 DO_FCALL “foo”/2 RETURN null function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (pointers to zvals) ... ... ...
  • 26. Copyright - © All rights reserved. Zend Technologies, Inc.26 VM Calling Convention (PHP 5.*) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: SEND_VAL 3 SEND_VAL 5 DO_FCALL “foo”/2 RETURN null function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (pointers to zvals) ... ... int(3), rc=1 HEAP Arg1: Arg2:
  • 27. Copyright - © All rights reserved. Zend Technologies, Inc.27 VM Calling Convention (PHP 5.*) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: SEND_VAL 3 SEND_VAL 5 DO_FCALL “foo”/2 RETURN null function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (pointers to zvals) ... int(3), rc=1 int(5), rc=1 HEAP Arg1: Arg2:
  • 28. Copyright - © All rights reserved. Zend Technologies, Inc.28 VM Calling Convention (PHP 5.*) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: SEND_VAL 3 SEND_VAL 5 DO_FCALL “foo”/2 RETURN null function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (pointers to zvals) CALL FRAME ... ... ... ... int(3), rc=1 int(5), rc=1 HEAP Arg1: Arg2: $a: $b:
  • 29. Copyright - © All rights reserved. Zend Technologies, Inc.29 VM Calling Convention (PHP 5.*) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: SEND_VAL 3 SEND_VAL 5 DO_FCALL “foo”/2 RETURN null function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (pointers to zvals) CALL FRAME ... ... ... int(3), rc=2 int(5), rc=1 HEAP Arg1: Arg2: $a: $b:
  • 30. Copyright - © All rights reserved. Zend Technologies, Inc.30 VM Calling Convention (PHP 5.*) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: SEND_VAL 3 SEND_VAL 5 DO_FCALL “foo”/2 RETURN null function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (pointers to zvals) CALL FRAME ... ... int(3), rc=2 int(5), rc=2 HEAP Arg1: Arg2: $a: $b:
  • 31. Copyright - © All rights reserved. Zend Technologies, Inc.31 VM Calling Convention (PHP 5.*) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: SEND_VAL 3 SEND_VAL 5 DO_FCALL “foo”/2 RETURN null function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (pointers to zvals) CALL FRAME int(8) ... int(3), rc=2 int(5), rc=2 HEAP Arg1: Arg2: $a: $b:
  • 32. Copyright - © All rights reserved. Zend Technologies, Inc.32 VM Calling Convention (PHP 5.*) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: SEND_VAL 3 SEND_VAL 5 DO_FCALL “foo”/2 RETURN null function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (pointers to zvals) CALL FRAME int(8) ... int(3), rc=2 int(5), rc=2 HEAP Arg1: Arg2: $a: $b:
  • 33. Copyright - © All rights reserved. Zend Technologies, Inc.33 VM Calling Convention (PHP 5.*) RECV 1, $a RECV 2, $b ADD $a,$b,TMP1 RETURN TMP1 foo: _main: SEND_VAL 3 SEND_VAL 5 DO_FCALL “foo”/2 RETURN null function foo($a, $b) { return $a + $b; } foo(3, 5); VM STACK (pointers to zvals) ... ... ...
  • 34. Copyright - © All rights reserved. Zend Technologies, Inc.34 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 new instruction embedded zvals instead of pointers
  • 35. Copyright - © All rights reserved. Zend Technologies, Inc.35 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
  • 36. Copyright - © All rights reserved. Zend Technologies, Inc.36 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
  • 37. Copyright - © All rights reserved. Zend Technologies, Inc.37 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)
  • 38. Copyright - © All rights reserved. Zend Technologies, Inc.38 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
  • 39. Copyright - © All rights reserved. Zend Technologies, Inc.39 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:
  • 40. Copyright - © All rights reserved. Zend Technologies, Inc.40 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:
  • 41. Copyright - © All rights reserved. Zend Technologies, Inc.41 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 NOTE: ● func_get_arg*() changed behavior ● function foo($_, $_) {} is not allowed
  • 42. Copyright - © All rights reserved. Zend Technologies, Inc.42 Новый менеджер памяти ● В PHP 5 менеджмент памяти потребляет более 20% процессорного времени (на Wordpress) ● Новый ММ отказался от алгоритмов dlmalloc и перешел на что-то, напоминающее jemalloc ● Уменьшены издержки памяти на служебную информацию ● Использование поиска по битовым маскам вместо обхода списков и деревьев ● Лучшее использование кэшей CPU ● Специализация под часто используемые размеры блоков ● Полностью прозрачная реализация ● Накладные расходы ММ уменьшены до 5%
  • 43. Copyright - © All rights reserved. Zend Technologies, Inc.43 Множество мелких усовершенствований ● Быстрое API для разбора параметров внутренних функций ● Новые инструкции VM (конкатенация строк, специализация, супер-инструкции) ● Некоторые внутренние функции превращены в инструкции VM (strlen, is_int) ● Использование регистров CPU под регистры VM (IP и FP) ● Новый API для итерации по HashTable ● Оптимизация функций дублирования и удаления массивов ● Использование счетчиков ссылок вместо копирования везде, где можно ● PCRE JIT ● Оптимизация внутренних функций ● Оптимизация serialize() ● Уменьшение размера кода и обрабатываемых данных
  • 44. Copyright - © All rights reserved. Zend Technologies, Inc.44 Откуда ускорение? (WordPress/PHP 7.0)
  • 45. Copyright - © All rights reserved. Zend Technologies, Inc.45 PHP 5.6 PHP 7.0 улучшение VM 27% 19,494M 46% 9,005M 2 раза alloc 22% 15,575M 5% 905M 17 раз hash 13% 9,590M 13% 2.450M 4 раза libc 6% 4.585M 8% 1,598M 3 раза Total: 100% 70,798M 100% 19,462M 3.5 раз Откуда ускорение? (WordPress)
  • 46. Copyright - © All rights reserved. Zend Technologies, Inc.46 Производительность PHP 7 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov 0 5 10 15 20 25 30 24.04 24.04 24.04 22.64 18.62 16.37 15.28 14.86 14.16 13.83 13.56 13.28 12.58 12.39 11.67 11.48 11.08 11.04 10.88 10.69 10.5 10.4 10.4 sec ● Время исполнения 1000 запросов к Wordpress-3.6.0 ● php-cgi -T 1000 /.../wordpress/index.php > /dev/null
  • 47. Copyright - © All rights reserved. Zend Technologies, Inc.47 PHP 5 против PHP 7 против HHVM ZF1 Hello ZF2 Test Magento (home) SugarCRM (login) Laravel Drupal 7 Drupal 8 Mediawiki Wordpress-4.1 0 0.5 1 1.5 2 2.5 3 PHP 5.6 PHP 7.0.0 HHVM 3.10.0
  • 48. Copyright - © All rights reserved. Zend Technologies, Inc.48 PHP 5 против PHP 7 против HHVM (версия Facebook)
  • 49. Copyright - © All rights reserved. Zend Technologies, Inc.49 Badoo перешли на PHP 7.0 и сэкономили $1M
  • 50. Copyright - © All rights reserved. Zend Technologies, Inc.50 Что дальше? ● PHP 7.0 ● Оптимизация структур данных ● PHP 7.1 ● Анализатор потоков данных ● Вывод типов ● Глобальный оптимизатор для байт-кода PHP ● Оптимизация и cпециализация интерпретатора
  • 51. Copyright - © All rights reserved. Zend Technologies, Inc.51 PHP 7.1 ● Уже вышел RC3 (29-го сентября 2016) ● 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()
  • 52. Copyright - © All rights reserved. Zend Technologies, Inc.52 PHP 7.1 Optimizer (script) <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 53. Copyright - © All rights reserved. Zend Technologies, Inc.53 PHP 7.1 Optimizer (bytecode) 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 RETURN $sum RETURN null <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 54. Copyright - © All rights reserved. Zend Technologies, Inc.54 PHP 7.1 Optimizer (trivial optimization) 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 RETURN $sum RETURN null <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 55. Copyright - © All rights reserved. Zend Technologies, Inc.55 PHP 7.1 Optimizer (trivial optimization) 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 RETURN $sum RETURN null <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 56. Copyright - © All rights reserved. Zend Technologies, Inc.56 PHP 7.1 Optimizer (trivial optimization) 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 RETURN $sum RETURN null <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 57. Copyright - © All rights reserved. Zend Technologies, Inc.57 PHP 7.1 Optimizer (trivial optimization) 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 RETURN $sum RETURN null <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 58. Copyright - © All rights reserved. Zend Technologies, Inc.58 PHP 7.1 Optimizer (trivial optimization) 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 RETURN $sum RETURN null <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 59. Copyright - © All rights reserved. Zend Technologies, Inc.59 PHP 7.1 Optimizer (trivial optimization) 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 RETURN $sum <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 60. Copyright - © All rights reserved. Zend Technologies, Inc.60 PHP 7.1 Optimizer (Control Flow Graph) 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 RETURN $sum <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 61. Copyright - © All rights reserved. Zend Technologies, Inc.61 PHP 7.1 Optimizer (Control Flow Graph) 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 RETURN $sum <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 62. Copyright - © All rights reserved. Zend Technologies, Inc.62 PHP 7.1 Optimizer (Control Flow Graph) 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 RETURN $sum <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 63. Copyright - © All rights reserved. Zend Technologies, Inc.63 PHP 7.1 Optimizer (Control Flow Graph) 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 RETURN $sum <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 64. Copyright - © All rights reserved. Zend Technologies, Inc.64 PHP 7.1 Optimizer (Static Single Assignmnt Form) 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 RETURN $?.sum <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 65. Copyright - © All rights reserved. Zend Technologies, Inc.65 PHP 7.1 Optimizer (Static Single Assignmnt Form) 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 RETURN $?.sum <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 66. Copyright - © All rights reserved. Zend Technologies, Inc.66 PHP 7.1 Optimizer (Static Single Assignmnt Form) 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 RETURN $5.sum <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 67. Copyright - © All rights reserved. Zend Technologies, Inc.67 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 RETURN $5.sum <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; }
  • 68. Copyright - © All rights reserved. Zend Technologies, Inc.68 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 RETURN $5.sum
  • 69. Copyright - © All rights reserved. Zend Technologies, Inc.69 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 RETURN $5.sum
  • 70. Copyright - © All rights reserved. Zend Technologies, Inc.70 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 RETURN $5.sum
  • 71. Copyright - © All rights reserved. Zend Technologies, Inc.71 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 RETURN $5.sum
  • 72. Copyright - © All rights reserved. Zend Technologies, Inc.72 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 RETURN $5.sum [long]
  • 73. Copyright - © All rights reserved. Zend Technologies, Inc.73 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 RETURN $5.sum [long]
  • 74. Copyright - © All rights reserved. Zend Technologies, Inc.74 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 RETURN $5.sum [long, double]
  • 75. Copyright - © All rights reserved. Zend Technologies, Inc.75 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 RETURN $5.sum
  • 76. Copyright - © All rights reserved. Zend Technologies, Inc.76 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..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 RETURN $5.sum [0..++]
  • 77. Copyright - © All rights reserved. Zend Technologies, Inc.77 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 RETURN $5.sum [long, double]
  • 78. Copyright - © All rights reserved. Zend Technologies, Inc.78 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 RETURN $5.sum [long, double]
  • 79. Copyright - © All rights reserved. Zend Technologies, Inc.79 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 RETURN $5.sum [long, double]
  • 80. Copyright - © All rights reserved. Zend Technologies, Inc.80 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 RETURN $5.sum [long, double]
  • 81. Copyright - © All rights reserved. Zend Technologies, Inc.81 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 RETURN $5.sum [long, double]
  • 82. Copyright - © All rights reserved. Zend Technologies, Inc.82 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 RETURN $5.sum [long, double]
  • 83. Copyright - © All rights reserved. Zend Technologies, Inc.83 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 RETURN $5.sum [long, double]
  • 84. Copyright - © All rights reserved. Zend Technologies, Inc.84 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 RETURN $5.sum [long, double]
  • 85. Copyright - © All rights reserved. Zend Technologies, Inc.85 PHP 7.1 Optimizer (final result) 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 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 RETURN $sum RETURN null
  • 86. Copyright - © All rights reserved. Zend Technologies, Inc.86 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
  • 87. Copyright - © All rights reserved. Zend Technologies, Inc.87 Что дальше? ● JIT (для PHP 7.2 или PHP 8) ● Проект стартовал в августе 2016 и находится в самом начале пути ● Для генерации машинного кода используется DynAsm из LuaJIT-2 ● https://github.com/zendtech/php-src/tree/jit-dynasm/ext/opcache/jit ● Уже сегодня ускорение на bench.php в 3 раза (в 75 раз быстрее PHP 5.0) ● На реальных приложениях ускорения нет ● Предыдущая попытка, основанная на LLVM, давала на bench.php 2.5 кратное ускорение ● На реальных приложениях была не применима (очень долго компилировала) ● https://github.com/zendtech/php-src/tree/zend-jit/ext/opcache/jit
  • 88. Copyright - © All rights reserved. Zend Technologies, Inc.88 PHP ? - JIT JIT$sum: sub $0xc, %esp mov $0x0, 0x30(%esi) mov $0x4, 0x38(%esi) mov $0x0, 0x40(%esi) mov $0x4, 0x48(%esi) jmp .L3 .L1: cmp $0x4, 0x38(%esi) jnz .L6 mov 0x30(%esi), %eax add 0x40(%esi), %eax jo .L5 mov %eax, 0x30(%esi) .L2: inc 0x40(%esi) .L3 mov $0xeca7fa64, %edi cmp $0x0, EG(vm_interrupt) jnz JIT$$interrupt_handler mov 0x40(%esi), %eax cmp $0x64, %eax jl .L1 ... $i++ $i < 100 $sum = 0 $i =0 <?php function sum() { $sum = 0; for ($i = 0; $i < 100; $i++) { $sum = $sum + $i; } return $sum; } $sum = $sum + $i
  • 89. Copyright - © All rights reserved. Zend Technologies, Inc.89 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.15.2 (--count=2) PHP/dynasm-jit 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.025 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. Старый JIT (быстрее некуда :) Новый JIT
  • 90. Confidential - © All rights reserved. Zend Technologies, Inc.90 Вопросы? Dmitry Stogov Principal Engineer at Zend Technologies @dstogov [email protected] www.zend.com
  • 91. Copyright - © All rights reserved. Zend Technologies, Inc.91 Хотите еще быстрее? – HUGE TLB или HUGE PAGE ● CPU использует виртуальную память с 4KB страницам ● CPU TLB cahce содержит всего 64-512 слотов => 256KB-2M ● TLB промахи требуют много времени для обработки ● Решение – страницы размером 2MB ● PHP-7, если может, использует 2M страницы для менеджера памяти и разделяемой памяти opcahce, где хранятся скомпилированные скрипты ● opcache.huge_tlb_caches=1 так же копирует сегмент кода в Huge Pages ● grep "Huge" /proc/meminfo AnonHugePages: 0 kB HugePages_Total: 512 HugePages_Free: 497 HugePages_Rsvd: 55 HugePages_Surp: 0 Hugepagesize: 2048 kB ● https://wiki.debian.org/Hugepages#Enabling_HugeTlbPage
  • 92. Copyright - © All rights reserved. Zend Technologies, Inc.92 Хотите еще быстрее? – 32-битная сборка? ● Почти все современные процессоры 64-битные ● Почти все современные ОС 64-битные ● X86_64 может обрабатывать данные, используя меньшее количество инструкций ● X86_64 предлагает 8 дополнительных регистров общего назначения ● Но: 64-битные адреса занимают больше места, требуют больше памяти, что ведет к увеличению промахов в CPU кэше и уменьшению производительности. ● Использование 32-битного PHP (gcc -m32 -sse2) обычно дает 5% прирост
  • 93. Copyright - © All rights reserved. Zend Technologies, Inc.93 Хотите еще быстрее? – PGO/FDO сборка ● make prof-gen ● sapi/cgi/php-cgi -T 3000 /.../wordpress/index.php > /dev/null ● make prof-clean ● make prof-use ● Скорость +8% ● Объем кода -8% (size sapi/cli/php)
  • 94. Copyright - © All rights reserved. Zend Technologies, Inc.94 Хотите еще быстрее? – opcache.file_cahe ● PHP7 opcache дает возможность дополнительно кэшировать скрипты на диске (запрещено по умолчанию) ● mkdir /tmp/opcahe ● Добавить opcache.file_cahce=/tmp/opcache в php.ini ● Уменьшает пиковые нагрузки при рестарте PHP и переполнении SHM кэша ● Улучшает время отклика в эти моменты в 2-3 раза ● Может использоваться в сценариях апгрейда (можно предварительно загрузить дисковый кэш) ● file_cache может работать вообще без SHM
  • 95. Copyright - © All rights reserved. Zend Technologies, Inc.95 Не забывайте про оптимизацию всего стека ● Оптимизация вашего PHP приложения даст наибольший результат ● Кэшируйте все, что можно ● Правильно выбирайте количество PHP процессов (больше – не значит лучше) ● MariaDB, сконфигурированная по умолчанию, замедляла Wordpress почти на 30% query_cache_size=16M query_cache_type=1 ● TCP stack ● Не отключайте Hyper-Threading