Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Confidential - © All rights reserved. Zend Technologies, Inc.1
Copyright - © All rights reserved. Zend Technologies, Inc.
...
Copyright - © All rights reserved. Zend Technologies, Inc.2
Кто Я?
●
Познакомился с программированием в 1984
●
Работаю в И...
Copyright - © All rights reserved. Zend Technologies, Inc.3
PHP – Personal Home Page
●
Инструмент для создания персональны...
Copyright - © All rights reserved. Zend Technologies, Inc.4
Производительность PHP на синтетических тестах
4.4
5.0 - Jul 2...
Copyright - © All rights reserved. Zend Technologies, Inc.5
Производительность PHP на реальных приложениях
4.4
5.0 - Jul 2...
Copyright - © All rights reserved. Zend Technologies, Inc.6
Блуждание в трех соснах (около JIT)
●
Почти два года потрачено...
Copyright - © All rights reserved. Zend Technologies, Inc.7
Что же тормозит? (WordPress/PHP 5.6)
Copyright - © All rights reserved. Zend Technologies, Inc.8
PHPNG (New Generation)
●
Проект получил свое развитие после по...
Copyright - © All rights reserved. Zend Technologies, Inc.9
PHP 7.0
●
Было решено выпускать PHP 7 после PHP 5, пропустив P...
Copyright - © All rights reserved. Zend Technologies, Inc.10
zval (PHP 5)
typedef struct _zval_struct {
union {
long lval;...
Copyright - © All rights reserved. Zend Technologies, Inc.11
zval (PHP 5 PHP 7)→
typedef struct _zval_struct {
union {
lon...
Copyright - © All rights reserved. Zend Technologies, Inc.12
zval (PHP 5 PHP 7)→
● read type - 1 CPU instruction
● read in...
Copyright - © All rights reserved. Zend Technologies, Inc.13
zval (PHP 5 PHP 7) Copy On Write→
● no CoW for scalars – few ...
Copyright - © All rights reserved. Zend Technologies, Inc.14
zval
type_flags
value
type reserved
● IS_UNDEF
● IS_NULL
● IS...
Copyright - © All rights reserved. Zend Technologies, Inc.15
zval (refcounted)
● IS_STRING
● IS_ARRAY
● IS_OBJECT
● IS_RES...
Copyright - © All rights reserved. Zend Technologies, Inc.16
zval (string)
● IS_STR_PERSISTENT
● IS_STR_INTERNED
● IS_STR_...
Copyright - © All rights reserved. Zend Technologies, Inc.17
zval (array)
flags
value
type reserved
typerefcount flags gc_...
Copyright - © All rights reserved. Zend Technologies, Inc.18
HashTable (PHP 5.*)
nKeyLenght
hash_val
Bucket
pData
pDataPtr...
Copyright - © All rights reserved. Zend Technologies, Inc.19
zval (array) / HashTable
flags
value
type reserved
0 7 8 31 3...
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 se...
Copyright - © All rights reserved. Zend Technologies, Inc.21
zval (object/PHP 5)
handlers
zend_class_entry *ce
typerefcoun...
Copyright - © All rights reserved. Zend Technologies, Inc.22
zval (object/PHP 7)
● IS_OBJ_DTOR_CALLED
● IS_OBJ_FREE_CALLED...
Copyright - © All rights reserved. Zend Technologies, Inc.23
zval (reference)
flags
value
type reserved
typerefcount flags...
Copyright - © All rights reserved. Zend Technologies, Inc.24
zval (IS_BOOL -> IS_FALSE + IS_TRUE)
ZEND_VM_HANDLER(43, ZEND...
Copyright - © All rights reserved. Zend Technologies, Inc.25
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,...
Copyright - © All rights reserved. Zend Technologies, Inc.26
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,...
Copyright - © All rights reserved. Zend Technologies, Inc.27
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,...
Copyright - © All rights reserved. Zend Technologies, Inc.28
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,...
Copyright - © All rights reserved. Zend Technologies, Inc.29
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,...
Copyright - © All rights reserved. Zend Technologies, Inc.30
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,...
Copyright - © All rights reserved. Zend Technologies, Inc.31
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,...
Copyright - © All rights reserved. Zend Technologies, Inc.32
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,...
Copyright - © All rights reserved. Zend Technologies, Inc.33
VM Calling Convention (PHP 5.*)
RECV 1, $a
RECV 2, $b
ADD $a,...
Copyright - © All rights reserved. Zend Technologies, Inc.34
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b...
Copyright - © All rights reserved. Zend Technologies, Inc.35
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b...
Copyright - © All rights reserved. Zend Technologies, Inc.36
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b...
Copyright - © All rights reserved. Zend Technologies, Inc.37
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b...
Copyright - © All rights reserved. Zend Technologies, Inc.38
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b...
Copyright - © All rights reserved. Zend Technologies, Inc.39
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b...
Copyright - © All rights reserved. Zend Technologies, Inc.40
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b...
Copyright - © All rights reserved. Zend Technologies, Inc.41
VM Calling Convention (PHP 7)
RECV 1, $a
RECV 2, $b
ADD $a,$b...
Copyright - © All rights reserved. Zend Technologies, Inc.42
Новый менеджер памяти
●
В PHP 5 менеджмент памяти потребляет ...
Copyright - © All rights reserved. Zend Technologies, Inc.43
Множество мелких усовершенствований
●
Быстрое API для разбора...
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 раза
al...
Copyright - © All rights reserved. Zend Technologies, Inc.46
Производительность PHP 7
Jan Feb Mar Apr May Jun Jul Aug Sep ...
Copyright - © All rights reserved. Zend Technologies, Inc.47
PHP 5 против PHP 7 против HHVM
ZF1 Hello
ZF2 Test
Magento (ho...
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...
Copyright - © All rights reserved. Zend Technologies, Inc.51
PHP 7.1
●
Уже вышел RC3 (29-го сентября 2016)
●
GA релиз запл...
Copyright - © All rights reserved. Zend Technologies, Inc.52
PHP 7.1 Optimizer (script)
<?php
function sum() {
$sum = 0;
f...
Copyright - © All rights reserved. Zend Technologies, Inc.53
PHP 7.1 Optimizer (bytecode)
ASSIGN $sum, 0
ASSIGN $i, 0
JMP ...
Copyright - © All rights reserved. Zend Technologies, Inc.54
PHP 7.1 Optimizer (trivial optimization)
ASSIGN $sum, 0
ASSIG...
Copyright - © All rights reserved. Zend Technologies, Inc.55
PHP 7.1 Optimizer (trivial optimization)
ASSIGN $sum, 0
ASSIG...
Copyright - © All rights reserved. Zend Technologies, Inc.56
PHP 7.1 Optimizer (trivial optimization)
ASSIGN $sum, 0
ASSIG...
Copyright - © All rights reserved. Zend Technologies, Inc.57
PHP 7.1 Optimizer (trivial optimization)
ASSIGN $sum, 0
ASSIG...
Copyright - © All rights reserved. Zend Technologies, Inc.58
PHP 7.1 Optimizer (trivial optimization)
ASSIGN $sum, 0
ASSIG...
Copyright - © All rights reserved. Zend Technologies, Inc.59
PHP 7.1 Optimizer (trivial optimization)
ASSIGN $sum, 0
ASSIG...
Copyright - © All rights reserved. Zend Technologies, Inc.60
PHP 7.1 Optimizer (Control Flow Graph)
ASSIGN $sum, 0
ASSIGN ...
Copyright - © All rights reserved. Zend Technologies, Inc.61
PHP 7.1 Optimizer (Control Flow Graph)
ASSIGN $sum, 0
ASSIGN ...
Copyright - © All rights reserved. Zend Technologies, Inc.62
PHP 7.1 Optimizer (Control Flow Graph)
ASSIGN $sum, 0
ASSIGN ...
Copyright - © All rights reserved. Zend Technologies, Inc.63
PHP 7.1 Optimizer (Control Flow Graph)
ASSIGN $sum, 0
ASSIGN ...
Copyright - © All rights reserved. Zend Technologies, Inc.64
PHP 7.1 Optimizer (Static Single Assignmnt Form)
ASSIGN $1.su...
Copyright - © All rights reserved. Zend Technologies, Inc.65
PHP 7.1 Optimizer (Static Single Assignmnt Form)
ASSIGN $1.su...
Copyright - © All rights reserved. Zend Technologies, Inc.66
PHP 7.1 Optimizer (Static Single Assignmnt Form)
ASSIGN $1.su...
Copyright - © All rights reserved. Zend Technologies, Inc.67
PHP 7.1 Optimizer (Extended Static Single Assignmnt Form)
ASS...
Copyright - © All rights reserved. Zend Technologies, Inc.68
PHP 7.1 Optimizer (Extended Static Single Assignmnt Form)
ASS...
Copyright - © All rights reserved. Zend Technologies, Inc.69
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
...
Copyright - © All rights reserved. Zend Technologies, Inc.70
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
...
Copyright - © All rights reserved. Zend Technologies, Inc.71
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
...
Copyright - © All rights reserved. Zend Technologies, Inc.72
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
...
Copyright - © All rights reserved. Zend Technologies, Inc.73
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
...
Copyright - © All rights reserved. Zend Technologies, Inc.74
PHP 7.1 Optimizer (Type Propagation)
ASSIGN $1.sum [long], 0
...
Copyright - © All rights reserved. Zend Technologies, Inc.75
PHP 7.1 Optimizer (Range Propagation)
ASSIGN $1.sum [0..0], 0...
Copyright - © All rights reserved. Zend Technologies, Inc.76
PHP 7.1 Optimizer (Range Propagation)
ASSIGN $1.sum [0..0], 0...
Copyright - © All rights reserved. Zend Technologies, Inc.77
PHP 7.1 Optimizer (Range + Type Propagation)
ASSIGN $1.sum [l...
Copyright - © All rights reserved. Zend Technologies, Inc.78
PHP 7.1 Optimizer (Range + Type Propagation)
ASSIGN $1.sum [l...
Copyright - © All rights reserved. Zend Technologies, Inc.79
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSI...
Copyright - © All rights reserved. Zend Technologies, Inc.80
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSI...
Copyright - © All rights reserved. Zend Technologies, Inc.81
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSI...
Copyright - © All rights reserved. Zend Technologies, Inc.82
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSI...
Copyright - © All rights reserved. Zend Technologies, Inc.83
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSI...
Copyright - © All rights reserved. Zend Technologies, Inc.84
PHP 7.1 Optimizer (Optimization)
ASSIGN $1.sum [long], 0
ASSI...
Copyright - © All rights reserved. Zend Technologies, Inc.85
PHP 7.1 Optimizer (final result)
ASSIGN $sum, 0
ASSIGN $i, 0
...
Copyright - © All rights reserved. Zend Technologies, Inc.86
PHP 7.1 Specialized Handlers
void PRE_INC_HANDLER()
{
if (Z_T...
Copyright - © All rights reserved. Zend Technologies, Inc.87
Что дальше?
●
JIT (для PHP 7.2 или PHP 8)
●
Проект стартовал ...
Copyright - © All rights reserved. Zend Technologies, Inc.88
PHP ? - JIT
JIT$sum:
sub $0xc, %esp
mov $0x0, 0x30(%esi)
mov ...
Copyright - © All rights reserved. Zend Technologies, Inc.89
The Computer Language Benchmarks Game (Mandelbrot)
GCC-5.3 -O...
Confidential - © All rights reserved. Zend Technologies, Inc.90
Вопросы?
Dmitry Stogov
Principal Engineer at Zend Technolo...
Copyright - © All rights reserved. Zend Technologies, Inc.91
Хотите еще быстрее? – HUGE TLB или HUGE PAGE
●
CPU использует...
Copyright - © All rights reserved. Zend Technologies, Inc.92
Хотите еще быстрее? – 32-битная сборка?
●
Почти все современн...
Copyright - © All rights reserved. Zend Technologies, Inc.93
Хотите еще быстрее? – PGO/FDO сборка
●
make prof-gen
●
sapi/c...
Copyright - © All rights reserved. Zend Technologies, Inc.94
Хотите еще быстрее? – opcache.file_cahe
●
PHP7 opcache дает в...
Copyright - © All rights reserved. Zend Technologies, Inc.95
Не забывайте про оптимизацию всего стека
●
Оптимизация вашего...
Upcoming SlideShare
Loading in …5
×

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

996 views

Published on

PHP 7.0 вышел год назад и уже используется многими крупными компаниями. Почти все они отмечают, что переход с PHP 5 дал приблизительно двукратное увеличение производительности на своих реальных задачах, позволив сократить количество серверов.

Я расскажу о том, как мы пришли к идеям, легшим в основу PHP 7; о внутреннем устройстве PHP, изменениях в базовых структурах данных и алгоритмах, определивших успех; новых идеях, реализуемых в еще не вышедших версиях.

Published in: Engineering

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

  1. 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. 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. 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. 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. 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. 6. Copyright - © All rights reserved. Zend Technologies, Inc.6 Блуждание в трех соснах (около JIT) ● Почти два года потрачено на прототип JIT для PHP-5.5 ● Ускорение для bench.php в 10 раз ● Ускорения для Wordpress нет (при компиляции в несколько минут) Выводы: ● Хороший код возможен при правильном предсказании типов ● Предсказание типов в реальных приложениях работает плохо ● Использование совместимых с PHP структур данных делает генерируемый код неэффективным
  7. 7. Copyright - © All rights reserved. Zend Technologies, Inc.7 Что же тормозит? (WordPress/PHP 5.6)
  8. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 42. Copyright - © All rights reserved. Zend Technologies, Inc.42 Новый менеджер памяти ● В PHP 5 менеджмент памяти потребляет более 20% процессорного времени (на Wordpress) ● Новый ММ отказался от алгоритмов dlmalloc и перешел на что-то, напоминающее jemalloc ● Уменьшены издержки памяти на служебную информацию ● Использование поиска по битовым маскам вместо обхода списков и деревьев ● Лучшее использование кэшей CPU ● Специализация под часто используемые размеры блоков ● Полностью прозрачная реализация ● Накладные расходы ММ уменьшены до 5%
  43. 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. 44. Copyright - © All rights reserved. Zend Technologies, Inc.44 Откуда ускорение? (WordPress/PHP 7.0)
  45. 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. 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. 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. 48. Copyright - © All rights reserved. Zend Technologies, Inc.48 PHP 5 против PHP 7 против HHVM (версия Facebook)
  49. 49. Copyright - © All rights reserved. Zend Technologies, Inc.49 Badoo перешли на PHP 7.0 и сэкономили $1M
  50. 50. Copyright - © All rights reserved. Zend Technologies, Inc.50 Что дальше? ● PHP 7.0 ● Оптимизация структур данных ● PHP 7.1 ● Анализатор потоков данных ● Вывод типов ● Глобальный оптимизатор для байт-кода PHP ● Оптимизация и cпециализация интерпретатора
  51. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 90. Confidential - © All rights reserved. Zend Technologies, Inc.90 Вопросы? Dmitry Stogov Principal Engineer at Zend Technologies @dstogov dmitry@zend.com www.zend.com
  91. 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. 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. 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. 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. 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

×