Upload
ontico
View
172
Download
3
Embed Size (px)
Citation preview
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.45.0 - Jul 2004
5.1 - Nov 20055.2 - Nov 20065.3 - Nov 20095.4 - Mar 20125.5 - Jun 20135.6 - Aug 20147.0 - Dec 20157.1 - Oct 2016HHVM-3.15.2
12.6812.54
4.684.20
2.912.18
2.031.92
0.780.50
0.38
bench.php [sec] (чем меньше, тем лучше)
sec
PHP-7.1 еще на треть быстрее PHP-7.0, но все еще медленнее HHVM (на тестах!)
Copyright - © All rights reserved. Zend Technologies, Inc.5
Производительность PHP на реальных приложениях
4.45.0 - Jul 2004
5.1 - Nov 20055.2 - Nov 20065.3 - Nov 20095.4 - Mar 20125.5 - Jun 20135.6 - Aug 20147.0 - Dec 20157.1 - Oct 2016HHVM-3.15.2
6258
6477
86105108
114298
321313
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_flagsvaluetype 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_flagsvaluetype 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
valuetype reserved
hash_valuetyperefcount flags gc_info
lenval...
0 7 8 31 32 63
Copyright - © All rights reserved. Zend Technologies, Inc.17
zval (array)
flagsvaluetype 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.*)
nKeyLenghthash_valBucket
pDatapDataPtrpListNextpListPrevpNextpPrevarKey
pInternalPointer
nTableSize
nNextFreeElement
nTableMasknNumOfElem
pListHeadpListTailarBucketspDestructor
HashTable
nKeyLenghthash_valBucket
pDatapDataPtrpListNextpListPrevpNextpPrevarKey
typevaluezval
Bucket*Bucket*...Bucket*
«hello»
Copyright - © All rights reserved. Zend Technologies, Inc.19
zval (array) / HashTable
flagsvaluetype reserved0 7 8 31 32 63
Bucket index N...Bucket index 0
keyhash_valBucket 0
val
...
keyhash_valBucket N
val
string, rc=1«hello»
typerefcount flags gc_infoflagsarData
nTableMask
nNumUsed nNumOfElem
nNextFreeElementnInternalPtrnTableSize
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 *propertyNHashTable *guards
0 7 8 31 32 63
handle
...
...
...
HashTable *properieszval *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
flagsvaluetype reserved
zend_class_entry *cetyperefcount flags gc_info
zend_object_handlers *handlersHashTable *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)
flagsvaluetype 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 checkvalue read
value check
type check
slow path
slow path
Copyright - © All rights reserved. Zend Technologies, Inc.25
VM Calling Convention (PHP 5.*)
RECV 1, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
SEND_VAL 3SEND_VAL 5DO_FCALL “foo”/2RETURN 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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
SEND_VAL 3SEND_VAL 5DO_FCALL “foo”/2RETURN 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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
SEND_VAL 3SEND_VAL 5DO_FCALL “foo”/2RETURN 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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
SEND_VAL 3SEND_VAL 5DO_FCALL “foo”/2RETURN 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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
SEND_VAL 3SEND_VAL 5DO_FCALL “foo”/2RETURN 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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
SEND_VAL 3SEND_VAL 5DO_FCALL “foo”/2RETURN 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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
SEND_VAL 3SEND_VAL 5DO_FCALL “foo”/2RETURN 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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
SEND_VAL 3SEND_VAL 5DO_FCALL “foo”/2RETURN 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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
SEND_VAL 3SEND_VAL 5DO_FCALL “foo”/2RETURN 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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
function foo($a, $b) { return $a + $b;}foo(3, 5);
VM STACK (zvals)
...SEND_VAL 3SEND_VAL 5DO_FCALLRETURN null
INIT_FCALL “foo”/2
CALL FRAME
callopline
prev_execute_data
current_execute_data
new instruction embedded zvalsinstead of pointers
Copyright - © All rights reserved. Zend Technologies, Inc.35
VM Calling Convention (PHP 7)
RECV 1, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
function foo($a, $b) { return $a + $b;}foo(3, 5);
...
...
...
SEND_VAL 3SEND_VAL 5DO_FCALLRETURN null
INIT_FCALL “foo”/2
Arg1:Arg2:
VM STACK (zvals)
CALL FRAMEopline
prev_execute_data
current_execute_data
CALL FRAME
call
prev_execute_datacallopline
Copyright - © All rights reserved. Zend Technologies, Inc.36
VM Calling Convention (PHP 7)
RECV 1, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
function foo($a, $b) { return $a + $b;}foo(3, 5);
SEND_VAL 3SEND_VAL 5DO_FCALLRETURN null
INIT_FCALL “foo”/2
VM STACK (zvals)
CALL FRAME
callopline
prev_execute_data
current_execute_data
int(3)......
Arg1:Arg2:
CALL FRAME
callopline
prev_execute_data
Copyright - © All rights reserved. Zend Technologies, Inc.37
VM Calling Convention (PHP 7)
RECV 1, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
function foo($a, $b) { return $a + $b;}foo(3, 5);
SEND_VAL 3SEND_VAL 5DO_FCALLRETURN null
INIT_FCALL “foo”/2
int(5)...
Arg1:Arg2:
VM STACK (zvals)
CALL FRAME
callopline
prev_execute_data
current_execute_data
CALL FRAME
callopline
prev_execute_dataint(3)
Copyright - © All rights reserved. Zend Technologies, Inc.38
VM Calling Convention (PHP 7)
RECV 1, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
function foo($a, $b) { return $a + $b;}foo(3, 5);
SEND_VAL 3SEND_VAL 5DO_FCALLRETURN null
INIT_FCALL “foo”/2
skip first 2 instructions
local variables already in-place
VM STACK (zvals)
CALL FRAMEopline
prev_execute_data
int(3)
...
CALL FRAME
callopline
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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
function foo($a, $b) { return $a + $b;}foo(3, 5);
SEND_VAL 3SEND_VAL 5DO_FCALLRETURN null
INIT_FCALL “foo”/2
VM STACK (zvals)
CALL FRAME
callopline
prev_execute_data
current_execute_data
VM STACK (zvals)
CALL FRAME
callopline
prev_execute_data
current_execute_data
int(3)
CALL FRAME
callopline
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, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
function foo($a, $b) { return $a + $b;}foo(3, 5);
SEND_VAL 3SEND_VAL 5DO_FCALLRETURN null
INIT_FCALL “foo”/2
VM STACK (zvals)
CALL FRAME
callopline
prev_execute_data
current_execute_data
int(3)int(5)int(8)
CALL FRAME
prev_execute_datacallopline
Arg2 $b:Arg1 $a:
Copyright - © All rights reserved. Zend Technologies, Inc.41
VM Calling Convention (PHP 7)
RECV 1, $aRECV 2, $bADD $a,$b,TMP1RETURN TMP1
foo:
_main:
function foo($a, $b) { return $a + $b;}foo(3, 5);
...SEND_VAL 3SEND_VAL 5DO_FCALLRETURN null
INIT_FCALL “foo”/2
VM STACK (zvals)
CALL FRAME
callopline
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 Nov0
5
10
15
20
25
30
24.04 24.04 24.0422.64
18.62
16.3715.28 14.86
14.16 13.83 13.56 13.2812.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 HelloZF2 Test
Magento (home)SugarCRM (login)
LaravelDrupal 7
Drupal 8Mediawiki
Wordpress-4.1
0
0.5
1
1.5
2
2.5
3
PHP 5.6PHP 7.0.0HHVM 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 L1L0: ADD $sum, $i -> T2 ASSIGN $sum, T2 POST_INC $i -> T4 FREE T4L1: 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 L1L0: ADD $sum, $i -> T2 ASSIGN $sum, T2 POST_INC $i -> T4 FREE T4L1: 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 L1L0: ASSIGN_ADD $sum, $i
POST_INC $i -> T4 FREE T4L1: 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 L1L0: ASSIGN_ADD $sum, $i
POST_INC $i -> T4 FREE T4L1: 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 L1L0: 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 L1L0: 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 L1L0: 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 L1L0: 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 L1L0: ADD $sum, $i → $sum PRE_INC_LONG_NOOVERFLOW $iL1: IS_SMALLER_LONG_JMPNZ $i, 100, L0 RETURN $sum
ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ADD $sum, $i -> T2 ASSIGN $sum, T2 POST_INC $i -> T4 FREE T4L1: 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, %espmov $0x0, 0x30(%esi)mov $0x4, 0x38(%esi)mov $0x0, 0x40(%esi)mov $0x4, 0x48(%esi)jmp .L3
.L1:cmp $0x4, 0x38(%esi)jnz .L6mov 0x30(%esi), %eaxadd 0x40(%esi), %eaxjo .L5mov %eax, 0x30(%esi)
.L2:inc 0x40(%esi)
.L3mov $0xeca7fa64, %edicmp $0x0, EG(vm_interrupt)jnz JIT$$interrupt_handlermov 0x40(%esi), %eaxcmp $0x64, %eaxjl .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 -O3PHP/llvm-jit
LuaJit-2.1.0-beta2JavaScriptCore-1.12.3
V8-3.14.5.10HHVM-3.15.2 (--count=2)
PHP/dynasm-jitSpiderMonrey-1.8.5
PyPy-4.0.1Java (openjdk-1.8)
PHP-7.1.0-devLuaJit-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.20Ruby-2.2.5
Python-2.7.11HHVM-3.13.2 (Jit=false)
Perl-5.22.1
0 0.5 1 1.5 2 2.5
0.0110.0110.0130.0140.0160.0190.0250.0270.0300.046
0.0920.098
0.1900.2270.243
0.3000.363
0.6090.940
1.0362.063
sec
Самый быстрый интерпретатор,все что быстрее с JIT.
Старый JIT (быстрее некуда :)
Новый JIT
Confidential - © All rights reserved. Zend Technologies, Inc.90
Вопросы?
Dmitry Stogov
Principal Engineer at Zend Technologies
@dstogov
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