High Performance PHP - PHPNW

Post on 02-Dec-2014

1978 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

In reality, a fairly deep dive into compilers and how different PHP compiler implementations work. Abstract: PHP powers the majority of the internet. It's a fast, scalable and capable language. But what do you do when it's not fast enough? Do you switch to HHVM? What about HippyVM? What about Recki-CT? What about other options? In this talk, we'll dive into the options for speeding up a PHP site. We'll go over the options, when they are appropriate, and when they are not. We'll talk about how to make a site faster. We'll demystify and de-FUD the conversation around these alternative implementations, and get down to the real numbers involved.

Transcript

High Performance PHPAnthony Ferrara

So you think you have scale problems?

You Don’t Have Scale Problems

Tip #1:

You Don’t Have Scale Problems

Tip #1:

Your Code Just Sucks

Scale Free Networks

Scale Free Networks

Top 20% Of Sites

80% Of Traffic

Scale Free Networks

Top 20% Of Sites

80% Of Traffic

Top 4% Of Sites64% Of Traffic

Scale Free Networks

Top 20% Of Sites

80% Of Traffic

Top 4% Of Sites64% Of Traffic

Percent Traffic

20% 80%

4% 64%

0.8% 51.2%

0.016% 40.9%

0.0032% 32.78%

0.00064% 26.214%

0.0000128% 20.971%

Hardware Is CheapFleshware Is Not!

Server$0.25 Per Hour

Relative Costs

Developer$50 Per Hour

Server$0.25 Per Hour

Relative Costs

Developer$50 Per Hour

1 Developer Hour ≈≈

400 Server Hours

On Average, A Developer Needs To Save One

Server/Year Every 22 Hours To Justify Salary...

It’s A Gross Oversimplification...

Speed != ScaleTip #2:

Speed != ScaleTip #2:

Speed == User ExperienceScale == Server Experience

Adding Servers Will Not Fix Speed Issues

Changing Servers Will Not Fix Speed

Issues

Changing Platforms Will Not Fix Speed

Issues

Changing Languages Will Not Fix Speed

Issues

Cache For Scale, Not Speed!!!

Tip #3:

Cache For Scale, Not Speed!!!

Tip #3:

Caching For Speed Is A Band-Aid On A Gunshot Wound

Changing Code Will Fix Speed Issues

Fix Slow Code... Don’t Mitigate It

Disclaimer:

The Rest Of This Talk Is About SCALE, Not Speed

Types Of Programming Languages

- Machine Language- Device Specific- Note: NOT Assembly

- Everything Else

What Is A Machine?- CPU Hardware?- GPU Hardware?- Virtual Hardware?- A Virtual CPU?- A Virtual Runtime?

What Is A Machine?

Anything That Can Execute A Language

Directly

Types Of Programming Languages

- Machine Language- Device Specific- Note: NOT Assembly

- Everything Else

Types Of Programming Languages

- Machine Language- Device Specific- Note: NOT Assembly

- Everything ElseExecuted Directly

Compiler (n): A computer program (or set of programs) that

transforms source code written in one language (the source language) into another language (the target

language).

Types Of Compilers

- Assemblers- Basically Source Maps

- Ahead Of Time (AOT)- Just In Time (JIT)

- Tracing JIT- Local JIT- Region

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10)

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10)

GUARD(arg[0], int)

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10)

GUARD(arg[0], int)int x = 1

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10)

GUARD(arg[0], int)int x = 1int y = 2

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10)

GUARD(arg[0], int)int x = 1int y = 2int z = arg[0] + x

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10)

GUARD(arg[0], int)int x = 1int y = 2int z = arg[0] + xint tmp = z + y

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10)

GUARD(arg[0], int)int x = 1int y = 2int z = arg[0] + xint tmp = z + yreturn tmp

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10.5)

GUARD(arg[0], int)int x = 1int y = 2int z = arg[0] + xint tmp = z + yreturn tmp

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10.5)

GUARD(arg[0], int)int x = 1int y = 2int z = arg[0] + xint tmp = z + yreturn tmp

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10.5)

GUARD(arg[0], int)int x = 1int y = 2int z = arg[0] + xint tmp = z + yreturn tmp

BAILOUT

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10.5)

GUARD(arg[0], int)int x = 1int y = 2int z = arg[0] + xint tmp = z + yreturn tmp

BAILOUT

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Tracing JIT add(10.5)

GUARD(arg[0], float).....

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Local JIT add(10)

function add($num) { $x = 1; $y = 2; $z = $num + $x; return $z + $y;}

Local JIT / AOT add(10)

GUARD(arg[0], int)int z = arg[0] + 1int tmp = z + 2return tmp

But How Does It Do It?

AOT / Local JIT Compiler

Code

ParserOperations

Target Code

IR

Code Generator

Real “Compilers”

Code

Compiler 1

Target Code

IR 1

Compiler 2

IR 2

Compiler n

function blah($num) { if ($num) { return $num + 1; } return 0;}

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

TokenizeT_FUNCTIONT_STRINGT_VARIABLET_IFT_VARIABLET_RETURNT_VARIABLET_LNUMBERT_RETURNT_LNUMBER

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Parsefunction

- params: [$num]- stmts:

- If:- cond:

- Variable: $num- stmts:

- Return- Add

- Variable: $num- LNumber: 1

- Return- LNumber: 0

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Graph

function blah($num) {

$x = 1;

$x = $x + $num;

return $x + 1;

}

Static Single Assignment (SSA)

Assign $x = 1Add ($x = $x + $num)Add ($tmp = $x + 1)Return $tmp

function blah($num) {

$x = 1;

$x = $x + $num;

return $x + 1;

}

Static Single Assignment (SSA)

Assign $x1 = 1Add ($x = $x + $num)Add ($tmp = $x + 1)Return $tmp

function blah($num) {

$x = 1;

$x = $x + $num;

return $x + 1;

}

Static Single Assignment (SSA)

Assign $x1 = 1Add ($x2 = $x1 + $num)Add ($tmp = $x + 1)Return $tmp

function blah($num) {

$x = 1;

$x = $x + $num;

return $x + 1;

}

Static Single Assignment (SSA)

Assign $x1 = 1Add ($x2 = $x1 + $num)Add ($tmp = $x2 + 1)Return $tmp

function blah($num) {

$x = 1;

$x = $x + $num;

return $x + 1;

}

Static Single Assignment (SSA)

Assign $x1 = 1Add ($x2 = $x1 + $num)Add ($tmp = $x2 + 1)Return $tmp

function blah($num) {

$x = 1;

if ($num) {

$x = 2;

}

return $x;

}

Static Single Assignment (SSA)PHI Function

Assign $x = 1Jumpz $num endAssign $x = 2:endReturn $x

function blah($num) {

$x = 1;

if ($num) {

$x = 2;

}

return $x;

}

Static Single Assignment (SSA)PHI Function

Assign $x1 = 1Jumpz $num endAssign $x = 2:endReturn $x

function blah($num) {

$x = 1;

if ($num) {

$x = 2;

}

return $x;

}

Static Single Assignment (SSA)PHI Function

Assign $x1 = 1Jumpz $num endAssign $x2 = 2:endReturn $x

function blah($num) {

$x = 1;

if ($num) {

$x = 2;

}

return $x;

}

Static Single Assignment (SSA)PHI Function

Assign $x1 = 1Jumpz $num endAssign $x2 = 2:endReturn $x

function blah($num) {

$x = 1;

if ($num) {

$x = 2;

}

return $x;

}

Static Single Assignment (SSA)PHI Function

Assign $x1 = 1Jumpz $num endAssign $x2 = 2:endPhi $x3 = ($x1, $x2)Return $x

function blah($num) {

$x = 1;

if ($num) {

$x = 2;

}

return $x;

}

Static Single Assignment (SSA)PHI Function

Assign $x1 = 1Jumpz $num endAssign $x2 = 2:endPhi $x3 = ($x1, $x2)Return $x3

function blah($num) {

$x = 1;

$x = $x + $num;

return $x + 1;

}

OptimizingStatic Single Assignment (SSA)

Assign $x1 = 1Add ($x2 = $x1 + $num)Add ($tmp = $x2 + 1)Return $tmp

function blah($num) {

$x = 1;

$x = $x + $num;

return $x + 1;

}

OptimizingStatic Single Assignment (SSA)

Assign $x1 = 1Add ($x2 = $x1 + $num)Add ($tmp = $x2 + 1)Return $tmp

function blah($num) {

$x = 1;

$x = $x + $num;

return $x + 1;

}

OptimizingStatic Single Assignment (SSA)

Add ($x2 = 1 + $num)Add ($tmp = $x2 + 1)Return $tmp

OptimizationsType Efficiency Potential Complexity

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Peephole

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Peephole

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Peephole

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Peephole

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Peephole

OptimizationsType Efficiency Potential Complexity

Peephole High Low Simple

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Local

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Local

OptimizationsType Efficiency Potential Complexity

Peephole High Low Simple

Local Medium Moderate Simple

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Global

OptimizationsType Efficiency Potential Complexity

Peephole High Low Simple

Local Medium Moderate Simple

Global Low High Complex

function blah($num) {

if ($num) {

return $num + 1;

}

return 0;

}

Loop

?

OptimizationsType Efficiency Potential Complexity

Peephole High Low Simple

Local Medium Moderate Simple

Global Low High Complex

Loop Medium Moderate Complex

Putting It All Together

Types Of CompilersAOT Tracing JIT Local JIT Region

Complexity Simple Moderate High Very High

Optimizations Static None Dynamic Dynamic+Static

Restart Cost None Moderate High High

Potential Performance (Static Code)

Best Moderate Good Better

Potential Performance(Dynamic Code)

Moderate Good Better Best

Zend PHP (5.6)

PHPZend

OpCodeCache

AOT Compiler

line # * op return operands-------------------------------------------- 3 0 RECV !0 4 1 ADD ~0 !0, 1 2 RETURN ~0

Zend OpCode

HHVM (3.2)

PHP

HHVM OpCode

Cache

AOTCompiler

Native Machine

Code

Cache

Local JIT

10: Int 1 19: CGetL2 0 21: AddO 22: RetC

HHVM OpCode (ByteCode)

HippyVM

PHP

Hippy OpCode

Cache

AOTCompiler

Native Machine

Code

Cache

Tracing JIT

Recki-CT + JITFu

PHP Cache

AOT Compiler

Recki IR

JIT (kindof)

Compiler

Native Machine

Code

Recki-CT Graph

param $1 longconst $2 numeric 1var $3 numeric+ $1 $2 $3return $3

Recki-CT IR

Recki-CT + PECL

PHP

AOT Compiler

Recki IR Native Machine

Code

PECL

AOT Compiler

Types Of CompilersAOT Tracing JIT Local JIT Region VM?

Zend X X

HHVM X ? X

HippyVM X X

Recki-CT X ...

V8 X ?

SpiderMonkey \ / X

Performance Depends More On

Your Code Than The Engine…

function add($num) { $x = 1; $y = $x . “1”; $z = $y + 2; return $z + $num;}

Avoid Dynamic Types

add(1)add(“1”)add([1, 2, 3])add(“HI!”)add(new StdClass())add(null)add(function() {})add(fopen(“foo.txt”))

function blah($num) { global $amt;}

Avoid Globals

function blah($num) { $func = “foo”; $func($num);}

Avoid Dynamic Function Calls

if ($blah) { function blah($num) { }}

Avoid Conditional Declarations

function blah($num) { eval(...) create_function(...)}

Avoid Eval

The More Dynamic The Code, The Slower

It Will Run

Anthony Ferrara

joind.in/11805@ircmaxell

me@ircmaxell.comblog.ircmaxell.com

github.com/ircmaxellyoutube.com/ircmaxell

top related