75
Confidenal - © All rights reserved. Zend Technologies, Inc. 1 Copyright - © All rights reserved. Zend Technologies, Inc. Развитие PHP 7.* Dmitry Stogov DevConf 2016, Москва Principal Engineer at Zend Technologies

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

Embed Size (px)

Citation preview

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

Confidential - © All rights reserved. Zend Technologies, Inc.1 Copyright - © All rights reserved. Zend Technologies, Inc.

Развитие PHP 7.*

Dmitry Stogov

DevConf 2016, Москва

Principal Engineer at Zend Technologies

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

Copyright - © All rights reserved. Zend Technologies, Inc.2

Кто Я?

● Работаю в ИТ с 1991● Первое знакомство с PHP в 2002● Автор Turck MMCache (eAccelerator)● Работаю в Zend Technologies с 2004● Сейчас ведущий инженер● Автор ext/soap и pecl/perl● Один из ведущих разработчиков Open Source PHP● Майнтейнер Zend OPcache● Лидер проекта PHPNG легшего в основу PHP 7

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

Copyright - © All rights reserved. Zend Technologies, Inc.3

Производительность PHP на синтетических тестах

0 2 4 6 8 10 12 14

12.6812.54

4.684.2

2.912.18

2.031.92

0.780.56

0.38

bench.php [sec]

4.45.0 - Jul 20045.1 - Nov 20055.2 - Nov 20065.3 - Nov 20095.4 - Mar 20125.5 - Jun 20135.6 - Aug 20147.0.0 - Dec 20157.1 Jun 2016HHVM-3.13.2

sec

PHP-7.1 еще на 25% быстрее PHP-7.0 но все еще медленнее HHVM

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

Copyright - © All rights reserved. Zend Technologies, Inc.4

Производительность PHP на реальных приложениях

0 50 100 150 200 250

5451

5667

769193

101232235

206

WordPress-3.6.0 Home Page [req/sec]

4.45.0 - Jul 20045.1 - Nov 20055.2 - Nov 20065.3 - Nov 20095.4 - Mar 20125.5 - Jun 20135.6 - Aug 20147.0.0 - Dec 20157.1 Jun 2016HHVM-3.13.2

req/sec

На реальных приложениях PHP-7.1 пока не дает существенного выигрыша!

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

Copyright - © All rights reserved. Zend Technologies, Inc.5

PHPNG (New Generation)

● Проект получил свое развитие после попыток создания JIT для PHP● Рефакторинг (ни каких нововведений, 100% совместимость с PHP 5)● Основная цель — достичь нового уровня производительности и

заложить базу для будущих улучшений● Отделился от основной ветки PHP в январе 2014

● Две недели ушло на то что-бы просто скомпилировать ядро● Еще через две недели заработал bench.php● Полтора месяца для обеспечения совместимости с Wordpress● Еще через месяц (к 9 Мая) мы открыли проект● В августе 2014 принят как основа для будущего PHP 7

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

Copyright - © All rights reserved. Zend Technologies, Inc.6

PHP 7.0

● Было решено выпускать PHP 7 после PHP 5, пропустив PHP 6● GA релиз состоялся в декабре 2015● Сейчас доступен PHP-7.0.7

● Возможность определять скалярные типы аргументов функций и возвращаемых значений

● Исключения вместо фатальных ошибок● Анонимный классы● Zero-cost assert()● Новые операторы и функции (<=>, ??)● Чистка неконсистентностей

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

Copyright - © All rights reserved. Zend Technologies, Inc.7

Badoo перешли на PHP 7.0 и сэкономили $1M

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

Copyright - © All rights reserved. Zend Technologies, Inc.8

Что дальше?

● PHP 7.0● Оптимизация структур данных

● PHP 7.1● Анализатор потоков данных● Вывод типов● Глобальный оптимизатор для байт-кода PHP● Оптимизация и Специализация интерпретатора

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

Copyright - © All rights reserved. Zend Technologies, Inc.9

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.10

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.11

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.12

zval (array)

flagsvaluetype reserved

typerefcount flags gc_info

HashTable

● IS_ARRAY_IMMUTABLE

0 7 8 31 32 63

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

Copyright - © All rights reserved. Zend Technologies, Inc.13

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.14

HashTable (PHP 5.*)

nKeyLenghthash_valBucket

pDatapDataPtrpListNextpListPrevpNextpPrevarKey

pInternalPointer

nTableSize

nNextFreeElement

nTableMasknNumOfElem

pListHeadpListTailarBucketspDestructor

HashTable

nKeyLenghthash_valBucket

pDatapDataPtrpListNextpListPrevpNextpPrevarKey

typevaluezval

Bucket*Bucket*...Bucket*

«hello»

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

Copyright - © All rights reserved. Zend Technologies, Inc.15

PHP 5.6 PHP 7

Memory Usage 428 MB 34 MB

Time 0.49 sec 0.06 sec

$a = array();for ($i = 0; $i < 1000000; $i++) $a[$i] = array("hello");echo memory_get_usage(true);

if (in array($color, array(“red”, “yellow”, “green”)) { ...}

Immutable Arrays (Неизменяемые массивы)

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

Copyright - © All rights reserved. Zend Technologies, Inc.16

zval (object/PHP 7)

● IS_OBJ_DTOR_CALLED● IS_OBJ_FREE_CALLED● IS_OBJ_USE_GUARDS● IS_OBJ_HAS_GUARDS

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.17

zval (reference)

flagsvaluetype reserved

typerefcount flags gc_info

zval val

0 7 8 31 32 63

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

Copyright - © All rights reserved. Zend Technologies, Inc.18

Компиляция PHP 7

<?php$name = $_GET['name'];echo “hello $name\n”;

Lexer

Parser

Compiler

filename

zend_op_array

vars

scope

name

hello.php

opcodes

...

literals

arg_info

FETCH_R C0, V1

zend_op

ROPE_INIT C2,T1

ASSIGN $0,V2

FETCH_DIM_R V1,C1,V2

ROPE_ADD $0,T1

ECHO T1

ROPE_END C3,T1

RETURN C4

$name

zend_string

“_GET”

zval

“\n”

“hello “

“name”

int(1)

AST

tokens

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

Copyright - © All rights reserved. Zend Technologies, Inc.19

Структуры Данных PHP 7 Времени Исполнения

current_execute_data

zend_executor_globals

scope (removed in 7.1)

..

func

zend_execute_data

called_scope (removed in 7.1)

zval* return_value

call

opline

symbol_table

prev_execute_data

run_time_cache

literals

zval This

...

zend_op_array

opcodes

...

literals

FETCH_R

zend_op

ROPE_INIT

ASSIGN

FETCH_DIM_R

ROPE_ADD

ECHO

ROPE_END

RETURN

“_GET”

zval

“name”

literals

$name

V2

V1 / T1

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

Copyright - © All rights reserved. Zend Technologies, Inc.20

Интерпретация PHP 7

register zend_execute_data *exexute_data__asm__(«%r14»);

register zend_op *opline__asm__(«%r15»);

void execute_ex(zend_execute_data *ex){ exexute_data = ex; opline = exexcute_data->opline; do { opline->handler(); } while (opline);}

ZEND_VM_HANDLER(1, ZEND_ADD, CONST|TMPVAR|CV, CONST|TMPVAR|CV)

{zval *op1, *op2, *result;

op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);if (Z_TYPE_P(op1)== IS_LONG) {

if (Z_TYPE_P(op2) == IS_LONG) {result = EX_VAR(opline->result.var);fast_long_add_function(result, op1, op2);

} else if (Z_TYPE_P(op2) == IS_DOUBLE) { ... } else{

…}opline++;

}

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

Copyright - © All rights reserved. Zend Technologies, Inc.21

Интерпретация PHP 7

register zend_execute_data *exexute_data__asm__(«%r14»);

register zend_op *opline__asm__(«%r15»);

void execute_ex(zend_execute_data *ex){ exexute_data = ex; opline = exexcute_data->opline; do { opline->handler(); } while (opline);}

static void ZEND_ADD_SPEC_TMPVAR_CONST(void)

{zval *op1, *op2, *result;

op1 = ZEND_CALL_VAR(execute_data, opline->op1.var); op2 = execute_data->literals[opline->op2.num];if (Z_TYPE_P(op1)== IS_LONG) {

if (Z_TYPE_P(op2) == IS_LONG) {result = EX_VAR(opline->result.var);fast_long_add_function(result, op1, op2);

} else if (Z_TYPE_P(op2) == IS_DOUBLE) { ... } else{

…}opline++;

}

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

Copyright - © All rights reserved. Zend Technologies, Inc.22

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.23

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.24

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.25

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)

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

Copyright - © All rights reserved. Zend Technologies, Inc.26

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.27

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:

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

Copyright - © All rights reserved. Zend Technologies, Inc.28

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:

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

Copyright - © All rights reserved. Zend Technologies, Inc.29

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

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

Copyright - © All rights reserved. Zend Technologies, Inc.30

Что дальше?

● PHP 7.0● Оптимизация структур данных

● PHP 7.1● Анализатор потоков данных● Вывод типов● Глобальный оптимизатор для байт-кода PHP● Оптимизация и Специализация интерпретатора

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

Copyright - © All rights reserved. Zend Technologies, Inc.31

PHP 7.1

● Первый Alpha релиз в июне 2016● Feature Freeze в июле● GA релиз запланирован на ноябрь 2016

● Nullable types - function foo(?Node $x): ?Node;● Void return type - function foo(): void;● Keys in list() - foreach ($points as list(«x»=>$x, «y»=>$y))● Class constants visibility - private const X = 42;● Negative string offsets - $a = “abcd”; var_dump($a[-2]);● Invalid numeric strings - 5 * “orange”● Closure::fromCallable()

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

Copyright - © All rights reserved. Zend Technologies, Inc.32

PHP 7.1 Optimizer (script)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

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

Copyright - © All rights reserved. Zend Technologies, Inc.33

PHP 7.1 Optimizer (bytecode)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ADD $sum, $i -> T2 ASSIGN $sum, T2 POST_INC $i -> T4 FREE T4L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null

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

Copyright - © All rights reserved. Zend Technologies, Inc.34

PHP 7.1 Optimizer (trivial optimization)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ADD $sum, $i -> T2 ASSIGN $sum, T2 POST_INC $i -> T4 FREE T4L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null

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

Copyright - © All rights reserved. Zend Technologies, Inc.35

PHP 7.1 Optimizer (trivial optimization)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum += $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ASSIGN_ADD $sum, $i

POST_INC $i -> T4 FREE T4L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null

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

Copyright - © All rights reserved. Zend Technologies, Inc.36

PHP 7.1 Optimizer (trivial optimization)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ASSIGN_ADD $sum, $i

POST_INC $i -> T4 FREE T4L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null

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

Copyright - © All rights reserved. Zend Technologies, Inc.37

PHP 7.1 Optimizer (trivial optimization)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; ++$i) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ASSIGN_ADD $sum, $i

PRE_INC $i

L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null

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

Copyright - © All rights reserved. Zend Technologies, Inc.38

PHP 7.1 Optimizer (trivial optimization)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ASSIGN_ADD $sum, $i

PRE_INC $i

L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum RETUTN null

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

Copyright - © All rights reserved. Zend Technologies, Inc.39

PHP 7.1 Optimizer (trivial optimization)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ASSIGN_ADD $sum, $i

PRE_INC $i

L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.40

PHP 7.1 Optimizer (Control Flow Graph)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ASSIGN_ADD $sum, $i

PRE_INC $i

L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.41

PHP 7.1 Optimizer (Control Flow Graph)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1

L0: ASSIGN_ADD $sum, $i PRE_INC $i

L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0 RETRUN $sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.42

PHP 7.1 Optimizer (Control Flow Graph)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1

L0: ASSIGN_ADD $sum, $i PRE_INC $i

L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0

RETRUN $sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.43

PHP 7.1 Optimizer (Control Flow Graph)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1

L0: ASSIGN_ADD $sum, $i PRE_INC $i

L1: IS_SMALLER $i, 100 -> T5 JMPNZ T5, L0

RETRUN $sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.44

PHP 7.1 Optimizer (Static Single Assignmnt Form)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1

L0: ASSIGN_ADD $?.sum → $3.sum, $?.i PRE_INC $?.i → $4.i

L1: IS_SMALLER $?.i, 100 -> T5 JMPNZ T5, L0

RETRUN $?.sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.45

PHP 7.1 Optimizer (Static Single Assignmnt Form)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1

L0: ASSIGN_ADD $?.sum → $3.sum, $?.i PRE_INC $?.i → $4.i

$5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $?.i, 100 -> T5 JMPNZ T5, L0

RETRUN $?.sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.46

PHP 7.1 Optimizer (Static Single Assignmnt Form)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1

L0: ASSIGN_ADD $5.sum → $3.sum, $6.i PRE_INC $6.i → $4.i

$5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.47

PHP 7.1 Optimizer (Extended Static Single Assignmnt Form)

<?php

function sum() {

$sum = 0;

for ($i = 0; $i < 100; $i++) {

$sum = $sum + $i;

}

return $sum;

}

ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1

$7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i

$5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.48

PHP 7.1 Optimizer (Extended Static Single Assignmnt Form)

ASSIGN $1.sum, 0 ASSIGN $2.i, 0 JMP L1

$7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i

$5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.49

PHP 7.1 Optimizer (Type Propagation)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i

$5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.50

PHP 7.1 Optimizer (Type Propagation)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i

$5.sum = Phi($1.sum [long], $3.sum) $6.i = Phi($2.i [long], $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.51

PHP 7.1 Optimizer (Type Propagation)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i

$5.sum [long] = Phi($1.sum [long], $3.sum) $6.i [long] = Phi($2.i [long], $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.52

PHP 7.1 Optimizer (Type Propagation)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long] = Pi($6.i [long] & RANGE[--..99]) ASSIGN_ADD $5.sum [long] → $3.sum [?], $7.i [long] PRE_INC $7.i [long] → $4.i [?]

$5.sum [long] = Phi($1.sum [long], $3.sum [?]) $6.i [long] = Phi($2.i [long], $4.i [?]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long]

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

Copyright - © All rights reserved. Zend Technologies, Inc.53

PHP 7.1 Optimizer (Type Propagation)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long] = Pi($6.i [long] & RANGE[--..99]) ASSIGN_ADD $5.sum [long] → $3.sum [long, double], $7.i [long] PRE_INC $7.i [long] → $4.i [long, double]

$5.sum [long] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long, double]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long]

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

Copyright - © All rights reserved. Zend Technologies, Inc.54

PHP 7.1 Optimizer (Type Propagation)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long, double] = Pi($6.i [long, double] & RANGE[--..99]) ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long, double] PRE_INC $7.i [long, double] → $4.i [long, double]

$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long, double] = Phi($2.i [long], $4.i [long, double]) IS_SMALLER $6.i [long, double], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long, double]

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

Copyright - © All rights reserved. Zend Technologies, Inc.55

PHP 7.1 Optimizer (Range Propagation)

ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1

$7.i = Pi($6.i & RANGE[--..99]) ASSIGN_ADD $5.sum → $3.sum, $7.i PRE_INC $7.i → $4.i

$5.sum = Phi($1.sum, $3.sum) $6.i = Phi($2.i, $4.i) IS_SMALLER $6.i, 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum

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

Copyright - © All rights reserved. Zend Technologies, Inc.56

PHP 7.1 Optimizer (Range Propagation)

ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1

$7.i [0..0] = Pi($6.i [0..0] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [?], $7.i [0..0] PRE_INC $7.i [0..0] → $4.i [?]

$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [?]) $6.i [0..0] = Phi($2.i [0..0], $4.i [?]) IS_SMALLER $6.i [0..0], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [0..0]

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

Copyright - © All rights reserved. Zend Technologies, Inc.57

PHP 7.1 Optimizer (Range Propagation)

ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1

$7.i [0..0] = Pi($6.i [0..0] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [0..0], $7.i [0..0] PRE_INC $7.i [0..0] → $4.i [1..1]

$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..0]) $6.i [0..0] = Phi($2.i [0..0], $4.i [1..1]) IS_SMALLER $6.i [0..0], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [0..0]

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

Copyright - © All rights reserved. Zend Technologies, Inc.58

PHP 7.1 Optimizer (Range Propagation)

ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1

$7.i [0..0] = Pi($6.i [0..++] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [0..0], $7.i [0..0] PRE_INC $7.i [0..0] → $4.i [1..1]

$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..0]) $6.i [0..++] = Phi($2.i [0..0], $4.i [1..1]) IS_SMALLER $6.i [0..++], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [0..0]

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

Copyright - © All rights reserved. Zend Technologies, Inc.59

PHP 7.1 Optimizer (Range Propagation)

ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1

$7.i [0..99] = Pi($6.i [0..++] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [0..0], $7.i [0..99] PRE_INC $7.i [0..99] → $4.i [1..1]

$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..0]) $6.i [0..++] = Phi($2.i [0..0], $4.i [1..1]) IS_SMALLER $6.i [0..++], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [0..0]

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

Copyright - © All rights reserved. Zend Technologies, Inc.60

PHP 7.1 Optimizer (Range Propagation)

ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1

$7.i [0..99] = Pi($6.i [0..++] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..0] → $3.sum [0..100], $7.i [0..99] PRE_INC $7.i [0..99] → $4.i [1..100]

$5.sum [0..0] = Phi($1.sum [0..0], $3.sum [0..100]) $6.i [0..++] = Phi($2.i [0..0], $4.i [1..100]) IS_SMALLER $6.i [0..++], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [0..0]

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

Copyright - © All rights reserved. Zend Technologies, Inc.61

PHP 7.1 Optimizer (Range Propagation)

ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1

$7.i [0..99] = Pi($6.i [0..++] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..++] → $3.sum [0..++], $7.i [0..99] PRE_INC $7.i [0..99] → $4.i [1..100]

$5.sum [0..++] = Phi($1.sum [0..0], $3.sum [0..++]) $6.i [0..++] = Phi($2.i [0..0], $4.i [1..100]) IS_SMALLER $6.i [0..++], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [0..++]

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

Copyright - © All rights reserved. Zend Technologies, Inc.62

PHP 7.1 Optimizer (Range Propagation - narrowing)

ASSIGN $1.sum [0..0], 0 ASSIGN $2.i [0..0], 0 JMP L1

$7.i [0..99] = Pi($6.i [0..100] & RANGE[--..99]) ASSIGN_ADD $5.sum [0..++] → $3.sum [0..++], $7.i [0..99] PRE_INC $7.i [0..99] → $4.i [1..100]

$5.sum [0..++] = Phi($1.sum [0..0], $3.sum [0..++]) $6.i [0..100] = Phi($2.i [0..0], $4.i [1..100]) IS_SMALLER $6.i [0..100], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [0..++]

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

Copyright - © All rights reserved. Zend Technologies, Inc.63

PHP 7.1 Optimizer (Range + Type Propagation)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long, double] = Pi($6.i [long, double] & RANGE[--..99]) ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long, double] PRE_INC $7.i [long, double] → $4.i [long, double]

$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long, double] = Phi($2.i [long], $4.i [long, double]) IS_SMALLER $6.i [long, double], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long, double]

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

Copyright - © All rights reserved. Zend Technologies, Inc.64

PHP 7.1 Optimizer (Range + Type Propagation)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long] = Pi($6.i [long] & RANGE[--..99]) ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long] PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100]

$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long, double]

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

Copyright - © All rights reserved. Zend Technologies, Inc.65

PHP 7.1 Optimizer (Optimization)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long] = Pi($6.i [long] & RANGE[--..99]) ASSIGN_ADD $5.sum [long, double] → $3.sum [long, double], $7.i [long] PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100]

$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long, double]

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

Copyright - © All rights reserved. Zend Technologies, Inc.66

PHP 7.1 Optimizer (Optimization)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100]

$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long, double]

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

Copyright - © All rights reserved. Zend Technologies, Inc.67

PHP 7.1 Optimizer (Optimization)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC $7.i [long] [0..99] → $4.i [long] [1..100]

$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long, double]

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

Copyright - © All rights reserved. Zend Technologies, Inc.68

PHP 7.1 Optimizer (Optimization)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC_LONG_NOOVERFLOW $7.i [long] [0..99] → $4.i [long] [1..100]

$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long, double]

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

Copyright - © All rights reserved. Zend Technologies, Inc.69

PHP 7.1 Optimizer (Optimization)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC_LONG_NOOVERFLOW $7.i [long] [0..99] → $4.i [long] [1..100]

$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER $6.i [long], 100 -> T5 JMPNZ T5, L0

RETRUN $5.sum [long, double]

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

Copyright - © All rights reserved. Zend Technologies, Inc.70

PHP 7.1 Optimizer (Optimization)

ASSIGN $1.sum [long], 0 ASSIGN $2.i [long], 0 JMP L1

$7.i [long] = Pi($6.i [long] & RANGE[--..99]) ADD $3.sum [long, double], $7.i [long] → $5.sum [long, double] PRE_INC_LONG_NOOVERFLOW $7.i [long] [0..99] → $4.i [long] [1..100]

$5.sum [long, double] = Phi($1.sum [long], $3.sum [long, double]) $6.i [long] = Phi($2.i [long], $4.i [long]) IS_SMALLER_LONG_JMPNZ $6.i [long], 100, L0

RETRUN $5.sum [long, double]

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

Copyright - © All rights reserved. Zend Technologies, Inc.71

PHP 7.1 Optimizer (SSA deconstruction)

ASSIGN $sum, 0 ASSIGN $i, 0 JMP L1L0: ADD $sum, $i → $sum PRE_INC_LONG_NOOVERFLOW $iL1: IS_SMALLER_LONG_JMPNZ $i, 100, L0 RETRUN $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 RETRUN $sum RETUTN null

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

Copyright - © All rights reserved. Zend Technologies, Inc.72

PHP 7.1 Specialized Handlers

void PRE_INC_HANDLER(){ if (Z_TYPE_P(op1) != IS_LONG) { … // not integer } else { Z_LVAL_P(op1)++; if (OVERFLOW) { … // overflow } } CHECK_EXCEPTION(); NEXT_OPCODE();}

void PRE_INC_HANDLER_LONG_NO_OVERFLOW(){ Z_LVAL_P(op1)++; NEXT_OPCODE();}

mov 0x4(%IP), %eax // get op1 offset incl (%FP, %eax) // increment add 0x1c, %IP // next opcode ret

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

Copyright - © All rights reserved. Zend Technologies, Inc.73

Что дальше?

● PHP 7.0● Оптимизация структур данных

● PHP 7.1● Анализатор потоков данных● Вывод типов● Глобальный оптимизатор для байт-кода PHP● Оптимизация и Специализация интерпретатора

● PHP 7.2● JIT?

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

Copyright - © All rights reserved. Zend Technologies, Inc.74

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.13.2 (--count=2)

SpiderMonrey-1.8.5PyPy-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.7Java (openjdk-1.8 -Xint)

Lua-5.3.2PHP-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.0270.0300.046

0.0920.098

0.1900.2270.243

0.3000.363

0.6090.940

1.0362.063

sec

Самый быстрый интерпретатор,все что быстрее с JIT.

В перспективе - быстрее некуда :)

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

Confidential - © All rights reserved. Zend Technologies, Inc.75

Вопросы?

Dmitry Stogov

Principal Engineer at Zend Technologies

@dstogov

[email protected]

www.zend.com