The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects...

28
Laruence THE NEXT GENERATION OF PHP KEEP GETTING FASTER PHP DEVELOPER

Transcript of The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects...

Page 1: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

Laruence

THE NEXT GENERATION OF PHPKEEP GETTING FASTER

PHP DEVELOPER

Page 2: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

SELF INTRODUCTION

·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects

·Maintainer Of Opcache, Msgpack Projects

·PHP Core Developer Since 2011

·Zend Consultant Since 2013

·PHP7 Core Developer

·Chief Software Architect At Lianjia Since 2015

A PROGRAMER

Page 3: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PHP HISTORY

·Created In 1994 By Rasmus Lerdorf

·20+ Years Programming Language

·Most Popular Web Service Program Language

·Php7 Is Released At 3 Dec 2015

·Latest Version Is PHP7.2

BORN FOR WEB

PHP

ASP.NET

Java

Static files

ColdFusion

Ruby

Perl

JavaScript

Python

Erlang

82.6%

15.1%

2.6%

1.5%

0.6%

0.6%

0.4%

0.4%

0.2%

0.1%

W3Techs.com,7 June 2017

Page 4: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PHP7

·The Biggest Performance Boost Version

·Over 100 % Performance Boosted

·Released Two Years Ago

THE FASTEST PHP

Page 5: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PHP7.1

·Static Single Assignment IR(SSA)

DATAFLOW ANALYSIS

function calc($a, $b) { $a = $a * 2 % 1000; $b = $b * 3 % 1000; return $a + $b; }

function calc($a1, $b2) { //$a1: [ANY], $b2: [ANY] $T3 = $a1 * 2; //$T3: [LONG, DOUBLE] $a4 = $T3 % 1000; //$a4: [LONG] $T5 = $b2 * 3; //$T5: [LONG, DOUBLE] $b6 = $T5 % 1000; //$b6: [LONG] $T7 = $a4 + $b6; //$T7: [LONG, DOUBLE] return $T7; }

·Data Flow Analysis Optimization

·Type Inference System

·Enhancement Of Range Inference

·Enhancement Of Type Inference Using Pi-Node

php -d opcache.opt_debug_level=-1 calc.php

Page 6: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PHP7.1

·Type Narrowing

TYPE INFERENCE SYSTEM

php -d opcache.opt_debug_level=-1 calc.php

function calc($a, $b) { //$a1: [ANY], $b2: [ANY] if (is_int($a)) { if (is_int($b)) { //PI($a2): [LONG] return $a + $b; //PI($b2): [LONG] } } }

Page 7: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PHP7.1

·Range Inference

TYPE INFERENCE SYSTEM

php -d opcache.opt_debug_level=-1 calc.php

function simple(int $a) { //$a1: [LONG} if ($a < 100) { if ($a > 98) { //PI($a2): [LONG(-INF ~ 100)] return ++$a; //PI($a3): [LONG(98 ~ 100)] } } }

Page 8: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PHP7.1

·Type Special Opcode Handler

·Avoiding Type-Check In Runtime

·Make Fast-Path Faster

TYPE SPECIAL OPCODE HANDLER

function calc($a1, $b2) { //$a1: [ANY], $b2: [ANY] $T3 = $a1 * 2; //$T3: [LONG, DOUBLE] $a4 = $T3 % 1000; //$a4: [LONG] $T5 = $b2 * 3; //$T5: [LONG, DOUBLE] $b6 = $T5 % 1000; //$b6: [LONG] $T7 = $a4 + $b6; //ZEND_ADD_LONG return $T7; }

php -d opcache.opt_debug_level=-1 simple.php

Page 9: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PHP7.2

·Sparse Conditional Constant Propagation

·Escape Analysis

·Dede Code Removal

SCCP & DCE

function simple() { $a = array(); $b = 1;

$a[0] = 2;

echo $a[0] + $b;

++$b;

return; }

function simple() { echo 3; return; }

phpdbg -p simple .php

Page 10: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PHP7.2

·Hybrid Vm Engine (Default Vm)

·Hybrid With Call+Goto

·Based On GCC Computed Goto[1]

HYBRID VM

CALL VM HIBRID VM

function add($a, $b) { return $a + $b; }

add(1, 2);

LOOP: CALLEND

INIT_FALLSEND_VAL

INTERPTER

SEND_VALDO_FCALL

RETURN

add()

CALLRET

HANDLERS

SWITCH: CALLEND

INIT_FALLSEND_VAL

INTERPTER

SEND_VALDO_FCALL

RETURN

add()

CALLRET

HOT HANDLERS

Page 11: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PERFORMANCE EVOLUTIONKEEP GETTING FASTER

0

3.5

7

10.5

14

PHP-5.0 PHP-5.1 PHP-5.2 PHP-5.3 PHP-5.4 PHP-5.5 PHP-5.6 PHP-7.0 PHP-7.1 PHP-7.2

0.8130.9211.022

2.9913.0453.1023.762

5.318

6.527

13.424

Page 12: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JUST-IN-TIME COMPILER

·JIT For PHP7

·Require Gcc 4.8 +(Global Register)

·X86-32/64 Supported

·Using Dynasm To Emitting Machine Codes(Mcode)[2]

·Already Opened Source[3]

BRAND NEW WAY

Compiler JIT

Type Inference

Register Allocation

ExecuteOpcode Mcode

Range Inference

SHM

Liveness Analysis

Page 13: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JUST-IN-TIME COMPILERCONFIGURATION(TEMPORARY)

opcache.jit=1 2 0 5Use AVX

JIT Strategy

Register alloc

JIT Level

0: JIT functions on load 1: JIT functions on execute 2: JIT most frequently called functions on first requrest 3: JIT functions after N calls or loop iterations 4: JIT functions with @jit annotation

0: JIT off 1: Minimal optimization 2: Basic optimization 3: optimize based on type-inference 4: optimize based on type-Inference and call-tree 5: optimize based on type-Inference and inner-procedure analises

Page 14: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JUST-IN-TIME COMPILER

· Inline Opcodes Dispatch

·opcache.jit=1201

BASIC OPTIMIZATION

function calc($a, $b) { $a = $a * 2 % 1000; $b = $b * 3 % 1000; return $a + $b; }

call ZEND_MUL_SPEC_CV_CONST_HANDLER cmp $0x0, EG(exception) jnz JIT$$exception_handler call ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER cmp $0x0, EG(exception) jnz JIT$$exception_handler call ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER cmp $0x0, EG(exception) jnz JIT$$exception_handler call ZEND_MUL_SPEC_CV_CONST_HANDLER cmp $0x0, EG(exception) jnz JIT$$exception_handler call ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER cmp $0x0, EG(exception) jnz JIT$$exception_handler call ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER cmp $0x0, EG(exception) jnz JIT$$exception_handler call ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER cmp $0x0, EG(exception) jnz JIT$$exception_handler

php -dopcache.jit_debug=1 calc.phpphpdbg -p* calc.php

#0 RECV 1 $a #1 RECV 2 $b #2 MUL $a 2 ~1 #3 MOD ~1 1000 ~0 #4 ASSIGN $a ~0 #5 MUL $b 3 ~1 #6 MOD ~1 1000 ~0 #7 ASSIGN $b ~0 #8 ADD $a $b ~0 #9 RETURN ~0

Page 15: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JUST-IN-TIME COMPILER

·PHP Is Weak-Type Language

·Lots Of Type-Checks In Runtime

TYPE CHECK AVOIDING

#0 RECV 1 $a #1 RECV 2 $b #2 MUL $a 2 ~1 #3 MOD ~1 1000 ~0 #4 ASSIGN $a ~0 #5 MUL $b 3 ~1 #6 MOD ~1 1000 ~0 #7 ASSIGN $b ~0 #8 ADD $a $b ~0 #9 RETURN ~0

phpdbg -p* calc.php

ZEND_VM_HANDLER(1, ZEND_ADD, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; zval *op1, *op2, *result;

op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { result = EX_VAR(opline->result.var); fast_long_add_function(result, op1, op2); ZEND_VM_NEXT_OPCODE(); } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { result = EX_VAR(opline->result.var); ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2)); ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { result = EX_VAR(opline->result.var); ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2)); ZEND_VM_NEXT_OPCODE(); } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { result = EX_VAR(opline->result.var); ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2))); ZEND_VM_NEXT_OPCODE(); } }

SAVE_OPLINE(); if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } add_function(EX_VAR(opline->result.var), op1, op2); FREE_OP1(); FREE_OP2(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); }

function calc($a, $b) { $a = $a * 2 % 1000; $b = $b * 3 % 1000; return $a + $b; }

Page 16: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JUST-IN-TIME COMPILER

·Only Run The Necessary Codes

·opcache.jit=1205

TYPE CHECK AVOIDING

function calc($a1, $b2) { //$a1: [ANY], $b2: [ANY] $T3 = $a1 * 2; //$T3: [LONG, DOUBLE] $a4 = $T3 % 1000; //$a4: [LONG] $T5 = $b2 * 3; //$T5: [LONG, DOUBLE] $b6 = $T5 % 1000; //$b6: [LONG] $T7 = $a4 + $b6; //$T7: [LONG, DOUBLE] return $T7; }

phpdbg -p* calc.php

php -d opcache.opt_debug_level=-1 calc.php php -d opcache.jit_debug=1 calc.php

#0 RECV 1 $a #1 RECV 2 $b #2 MUL $a 2 ~1 #3 MOD ~1 1000 ~0 #4 ASSIGN $a ~0 #5 MUL $b 3 ~1 #6 MOD ~1 1000 ~0 #7 ASSIGN $b ~0 #8 ADD $a $b ~0 #9 RETURN ~0

mov 0x50(%r14), %rax add 0x60(%r14), %rax jo .L27 mov %rax, 0x70(%r14) mov $0x4, 0x78(%r14)

Page 17: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JUST-IN-TIME COMPILER

·Registers Allocation For Long/Double

·Linear Scan Register Allocation(Toggled Between Opcache.Jit=1205 And1005)[4]

REGISTERS ALLOCATION

mov $0x0, 0x50(%r14) mov $0x4, 0x58(%r14) jmp .L2 .L1: add $0x1, 0x50(%r14) .L2: cmp $0x0, EG(vm_interrupt) jnz JIT$$interrupt_handler cmp $0x3e8, 0x50(%r14) jl .L1

function loop() { for ($i = 0; $i < 1000; $i++) { } }

xor %rdx, %rdx jmp .L2 .L1: add $0x1, %rdx .L2: cmp $0x0, EG(vm_interrupt) jnz JIT$$interrupt_handler cmp $0x3e8, %rdx jl .L1

php -dopcache.jit_debug=1 loop.php

Page 18: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JUST-IN-TIME COMPILER

·Over 100% Improvement In Bench VS PHP-7.2

BENCHMARK

0

3.5

7

10.5

14

PHP-5.0 PHP-5.1 PHP-5.2 PHP-5.3 PHP-5.4 PHP-5.5 PHP-5.6 PHP-7.0 PHP-7.1 PHP-7.2 PHP-JIT

0.3440.8130.9211.022

2.9913.0453.1023.762

5.318

6.527

13.424

Page 19: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JUST-IN-TIME COMPILER

·Benchmark Details VS PHP-7.2

BENCHMARK

0

0.045

0.09

0.135

0.18

SIMPLESIMPLECALLSIMPLEUCALLSIMPLEUDCALLMANDEL

MANDEL2ACKERMANN

ARY

ARY2

ARY3

FIBO

HASH1

HASH2

HEAPSORT

MATRIXNESTEDLOOP

SIEVE

STRCAT

0.0090.0120.023

0.0330.030.018

0.023

0.065

0.038

0.0050.006

0.0240.0220.020.0020.0020.0020.01

0.0130.024

0.067

0.0440.042

0.0220.023

0.17

0.111

0.0070.009

0.048

0.104

0.077

0.010.010.010.022

PHP-7.2 PHP-JIT

Page 20: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JUST-IN-TIME COMPILER

·7% Qps Improvement In Wordpress Homepage VS PHP-7.2

WORDPRESS HOMEPAGE BENCHMARK

0

100

200

300

400

PHP-5.0 PHP-5.1 PHP-5.2 PHP-5.3 PHP-5.4 PHP-5.5 PHP-5.6 PHP-7.0 PHP-7.1 PHP-7.2 PHP-JIT

353330321317

1121101078275

00

Page 21: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JIT CONSTRAINT

·Volatile Variable In Main Scope

·We Don’t Optimize Codes In Main Scope

PSEUDO-MAIN SCOPE

set_error_handler(function() { $GLOBALS['a'] = "str"; });

$a = 1; $b = $c;

Page 22: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JIT CONSTRAINT

·Dynamic Scope Modification

·Can Not Optimize Codes Which Include Such Usage

DYNAMIC SCOPE INTROSPECTION

function example() { $a = 1; $b = "a"; ${$b} = "str"; }

function example() { $a = 1; extract(array("a" => "str")); }

Page 23: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JIT CONSTRAINT

·Reference Arguments Passing Can Only Be See In Callee-Side

REFERENCE

function fn(&$val) { $val = "str"; }

function example() { $a = 1; fn($a); }

Page 24: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JIT CONSTRAINT

· Inter-Script Optimization Is Impossible

INDEPENDENT SCRIPTS

if ($_GET["first"]) { include "a.php"; } else { include "b.php"; }

function example() { $a = fn(); }

function fn() { return "str"; }

function fn() { return array(); }

Page 25: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JIT CONSTRAINT

·Wordpress Homepage Type Inference Result

THATS WHY

0%

17.5%

35%

52.5%

70%

ANY TYPE 1-TYPE 2-TYPE 3-TYPE 4-TYPE 5-TYPE 6-TYPE 7-TYPE

3.6%0.9%1.1%1.7%3.2%

7%

16.3%

66.2%

Page 26: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

JIT CONSTRAINT

·Visible Improvement On Old Applications

·Significant Improvement On Well-Written Codes

·Type Inference Plays Very Important Role In Jit

·More Type Info == More Performance Improvement

·Use Type-Hints If You Could

THATS WHY

function add(int $a, int $b):int { }

Page 27: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

LINKS

·Computed GOTO: https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Labels-as-Values.html

·The Unofficial DynAsm Documentation: http://corsix.github.io/dynasm-doc/index.html

·Zend JIT Repo: https://github.com/zendtech/php-src

·Linear Scan Register Allocation on SSA Form: http://www.christianwimmer.at/Publications/Wimmer10a/Wimmer10a.pdf

Page 28: The Next G of PHP · SELF INTRODUCTION ·Author Of Yaf, Yar, Yac, Yaconf, Taint Projects ·Maintainer Of Opcache, Msgpack Projects ·PHP Core Developer Since 2011 ·Zend Consultant

PHP : K E E P G E T T I NG F A S T ER

THANKS