php, under the hood - dpc
DESCRIPTION
PHP is one of the most popular open source programming languages in the world. It powers some of the highest traffic sites in the world, and at the same time it powers some of the lowest traffic sites in the world. But have you ever wondered how it works under the hood? Have you been overwelmed by the thought of looking at the C code that runs PHP? Well, this talk is for you! We're going to explore how PHP works under the hood, by looking at a PHP implementation of it: PHPPHP! Have you ever wondered what an OPCODE Cache is really doing? Have you ever wondered what a T_PAAMAYIM_NEKUDOTAYIM is? Have you ever wondered why an interpreted languages has a compiler? We'll explore all of these topics, and more! And the best part of it all? You don't need to know C to understand the details! Using PHPPHP, we can explore the language details in a high level language, where things like memory management don't get in the way of the real content. If you've ever wanted to know how PHP works, this is the talk for you!TRANSCRIPT
PHPUnder The Hood
What Is PHP?● An Easy To Learn Language?
○ Sure!● A Simple Language?
○ Usually● A Well Designed Language?
○ HA!● An Effective Language!
○ Absolutely!
PHP Is...
Dynamically Typed
$a = 1;$b = "a";
PHP Is...
Weak Typed
1 + "1b" == 2
PHP Is...
Implementation Defined
ImplementationsMain:
C-PHP: www.php.netAlt:
HipHop - FacebookRoadsend - CompilerPhalanger - .NETPHP Compiler - CompilerPHPPHP - PHP
Interesting Note:C-PHP Requires PHP To Compile!
PHP Is...
Compiled
PHP Is...
DynamicallyCompiled
On-Demand
It All Starts With TheSAPI
SAPI● Server API● "Starts" PHP and issues request(s)● Common SAPIs:
○ CLI○ CGI (and FastCGI)○ mod_php○ FPM○ etc...
Execution Pipeline
Execution PipelineStart Up
Request
Shut Down
SAPI
Execution PipelineStart Up
Request
Shut Down
SAPIConfig Init
Engine Init
Module Init
Zend/zend.c
PHPPHP/PHP.php
Execution PipelineStart Up
Request
Shut Down
SAPI
Module Shutdown
EngineShutdown
Zend/zend.c
Execution PipelineStart Up
Request
Shut Down
SAPI
Request Init
Compile Code
Execute Code
Request Shutdown
Compiler PipelineLexer
Lexer Step● C-PHP
○ Tokenizes using RE2C○ Produces Array of Tokens
● PHPPHP○ Uses core tokenizer (or emulative)○ PHPParser Powered
Zend/zend_language_scanner.l
PHPParser/Lexer/Emulative.php
Compiler PipelineLexer
Parser
Parse Step● C-PHP
○ Directly Generates OPCode Array○ BISON Powered
● PHPPHP○ Generates AST Structure○ PHPParser Powered
Zend/zend_language_parser.y
Compiler PipelineLexer
Parser
Compiler
Compile Step● C-PHP
○ Compiled Directly During Parse○ Single Pass Compilation
● PHPPHP○ Recurses Over AST○ Single Pass (for now)○
PHPPHP/Engine/Compiler.php
Compiler PipelineLexer
Parser
Compiler
OpCode
OpCodes● A Series of Operations
○ Just like Assembler Opcodes○ Represent "units of functionality"
● Designed to run on Virtual Machine○ Zend Engine○ Or PHPPHP!
$a = 1;$b = 2;echo $a + $b;
Notice Anything?
What If We Cached The OpCodes?
We Can Cache!● Given the compiler is Idempodent
○ (has no side-effects)○ (hint: it's not)
● OpCodes are really Pointers○ Swizzling!!!
In Other Words
OpCode CachingIs Hard!
Time To Execute!
Zend/zend_vm_execute.h
PHPPHP/Engine/Executor.php
Executor Pipeline
OpCode
Is Return?No Yes
Return
But What Are We Executing?
Zend/zend_vm_execute.h
Interesting Note:vm_execute.h
Is Generated By PHP
PHPPHP/Engine/OpLines/Add.php
Variables!
Zend/zend.h
PHPPHP/Engine/Zval/Value.php
Ref-Counting● RefCount + References
○ Allows Copy-On-Write● Variable Is "Deleted" When
RefCount = 0
● Enables Primitive Garbage Collection○ Circular GC is also implemented
That's All There Is To It!
Let's Look At An Example
$a = 1;$b = 2;var_dump( $a + $b);
line # op return operands----------------------------------- 2 0 ASSIGN !0, 1 3 1 ASSIGN !1, 2 6 2 ADD ~2 !0, !1 3 SEND_VAL ~2 4 DO_FCALL 'var_dump' 5 RETURN 1
[0] => PHPPHP\Engine\OpLines\Assign[1] => PHPPHP\Engine\OpLines\Assign[2] => PHPPHP\Engine\OpLines\Add[3] => PHPPHP\Engine\OpLines\InitFCallByName[4] => PHPPHP\Engine\OpLines\Send[5] => PHPPHP\Engine\OpLines\FunctionCall[6] => PHPPHP\Engine\OpLines\ReturnOp
[0] => PHPPHP\Engine\OpLines\Assign Object (
[op1] => PHPPHP\Engine\Zval\Ptr Object (
[zval:protected] => PHPPHP\Engine\Zval\Variable Object (
[name:protected] => PHPPHP\Engine\Zval\Ptr Object (
[zval:protected] => PHPPHP\Engine\Zval\Value Object (
[value:protected] => a
[refcount:protected] => 1
[isRef:protected] =>
[dtorFunc:protected] =>
)
)
[class:protected] =>
[zval:protected] =>
[executor:protected] =>
[scope] => 1
)
)
[op2] => PHPPHP\Engine\Zval\Ptr Object (
[zval:protected] => PHPPHP\Engine\Zval\Value Object (
[value:protected] => 1
[refcount:protected] => 1
[isRef:protected] =>
[dtorFunc:protected] =>
)
)
[result] =>
[lineno] => 2
)
PHPPHP/Engine/OpLines/Assign.php
PHPPHP/Engine/OpLines/Add.php
PHPPHP/Engine/OpLines/InitFCallByName.php
PHPPHP/Engine/OpLines/Send.php
PHPPHP/Engine/OpLines/FunctionCall.php
There's A Ton More
Get Involved!
More Info● github.com/php/php-src● lxr.php.net● github.com/ircmaxell/PHPPHP
● Reference Series○ wiki.php.net○ blog.ircmaxell.com
■ PHP Internals Series
Anthony FerraraJoind.in/8443
@[email protected]/ircmaxell