high performance php - phpnw
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
github.com/ircmaxellyoutube.com/ircmaxell