2. Hello everybody
Julien PAULI
Programming in PHP since ~20y (~1999-2000)
Programming in C for PHP Internals
PHP 5.5 and 5.6 Release Manager
Working at SensioLabs in Paris
http://www.phpinternalsbook.com co-author
@julienpauli - http://jpauli.tech - jpauli@php.net
3. What we'll cover together
Reminder on how PHP works
Introduction to OPCodes
The need of an OPCode cache
OPCache in deep
OPCache configuration settings
4. What is PHP ?
PHP
Programming language
"Scripting language"
No *manual* compilation needed
Fire and forget
Automatic memory management
Facultative strong typing. Type juggler
Provides OOP features
Highly dynamic, highly extensible
5. How does PHP work ?
Parsing
(Lexer + parser)
Compiling
Executing
opcodes
PHP code
AST nodes
Result
6. Zend Virtual Machine
Parsing
(Lexer + parser)
Compiling
Executing
"VirtualMachine"
Its purpose is to provide a platform-
independent programming
environment that abstracts away
details of the underlying hardware or
operating system, and allows a
program to execute in the same way
on any platform (Wikipedia)
7. The PHP way
Compile, execute, forget - Compile, execute, forget -
Compile, execute, forget - Compile, execute, forget -
Compile, execute, forget - Compile, execute, forget -
Compile, execute, forget - Compile, execute, forget …
By default (by design), PHP discards all the code it just
executed
Request n+1 knows nothing about request n
8. The PHP Way
If your pages get hit several times without changing (most
likely)
→ compile the same scripts several times
→ it still produces the same OPCodes
Parsing
(Lexer + parser)
Compiling
9. Compiling VS Executing
Compile, then execute
Which one is the longest ?
Depends on your scripts
Compile
Execute
Execute
Compile
11. Understanding compil. / exec.
Classes usually require much more compile time than exec
time
include / require / eval() = compile + execute
autoload = compile + execute
.. deffered at execution
Compile Execute
include/require ?
eval() ?
autoload ?
B
N
Y
E
13. Save at first run
Compiling
Executing
opcodes
AST nodes
Caching
opcodesShared
Memory
opcodes
save
time
File
System
OR
14. Load (same script) after
OPCode cache
Executing
opcodes
PHP code
opcodes
load
Shared
Memory
File
System
OR
15. Optimize
Why not optimize the OPCode array ?
opcodes
Optimizing
opcodes
opcodes
Caching
Compiling
save
Executing
opcodes
Shared
Memory
File
System
OR
17. OPCode
In computer science, an opcode (operation code) is the
portion of a machine language instruction that specifies the
operation to be performed. (Wikipedia)
Opcodes can also be found in so called byte codes and
other representations intended for a software interpreter
rather than a hardware device. (Wikipedia)
21. Example of OPCode
<?php
const DEF = "default";
if (isset($argv[1])) {
$b = (array)$argv[1];
} else {
$b = DEF;
}
var_dump($b);
Execution
Compilation
The more code to parse, the longer the compilation phase
The more OPCodes generated, the longer the execution
Depends on OPCodes, some are long to run, some are very fast
DECLARE_CONST
ISSET_ISEMPTY_DIM_OBJ
JMPZ
FETCH_DIM_R
CAST
ASSIGN
JMP
FETCH_CONSTANT
ASSIGN
INIT_FCALL
SEND_VAR
DO_ICALL
RETURN
22. Optimize execution
Some OPCodes are heavier than
others
OPCodes may be run several
times (in fact, yes they do)
The optimizer can play a role
Optimizing
Caching
Compiling
Executing
23. OPCache
"OPCache" is PHP OPCode cache
It is both a cache, and an optimizer
It is bundled by defaut with PHP
But it may not be activated by default
24. Optimizer
Tries to simplify/optimize the OPCodes so that there are
less of them and they are more efficient
Works on code branches (if, switch, try …)
Optimize constant expressions - Look for dead code / code reuse
25. Try the optimizer
php
-dzend_extension=opcache
-dopcache.enable_cli=1
-dopcache.opt_debug_level=0x30000
-dopcache.optimization_level=0x7FFFFFFF
/tmp/php.php
26. Optimizer impact
The optimizer is very heavy, and burns tons of CPU cycles
At compilation
But compilation only happens once, as opcodes will be
cached
So they'd better be cached optimized, than raw
The very first run of a big application should pay a big perf
penalty
Prime your caches
Use OPCache file-based cache
27. Interned strings optimized
In computer science, string interning is a method of storing
only one copy of each distinct string value, which must be
immutable. Interning strings makes some string processing
tasks more time- or space-efficient at the cost of requiring
more time when the string is created or interned. The
distinct values are stored in a string intern pool
Wikipedia
28. Interned strings concept
Anytime a static string occurs in compiler, memorize it,
and reuse its pointer when needed.
OPCache optimizes them even more
class foo
{
public function bar($a = "foo")
{
}
}
$foo = new foo;
$foo->bar("foo");
29. No Interned strings
class foo
{
public function bar($a = "foo")
{
}
}
$foo = new foo;
$foo->bar("foo");
foo bar a foo foo foo foo bar foo
memory
31. OPCache & interned strings
OPCache interns strings from all PHP processes of the same
PHP pool
Nice memory savings on big pools
interned string mem interned string mem interned string mem
interned string mem
36. OPCache settings
memory_consumption
Size of Shared Memory
Don't forget to increase according to your needs
Buy more RAM, NEVER have a cache full, have margin
max_accelerated_files (=2000)
Max number of KEYS to be stored
KEYS are paths to files : ./foo.php, ../foo.php, etc...
One file usually is ~= 2 to 3 KEYS
Aligned at next prime number
Slots are preallocated : don't give too high number
Monitor
38. OPCache settings
validate_timestamps (=true)
Check for file update to invalidate it
Checks are triggered every revalidate_freq seconds
revalidate_freq (=2)
How often check for file updates to invalidate them
0 = every time
Revalidate = syscall cached by PHP's realpath cache
revalidate_paths (=0)
1 : only the resolved realpath is used as cache key
0 : the unresolved path is also added as a cache key
use_cwd (=1)
prepend cwd to every cache key for relative paths
39. OPCache memory details
When a script changes, it is
recompiled (if validate_timestamps
= 1)
Its old memory space is then
considered as "wasted" (it is then
NOT freed)
When cache is full, if max_wasted_percentage is reached :
a cache restart is triggered
Cache restart = empty cache and recompile all
Cache is never restarted if not full
40. OPcache other settings
optimization_level (=0x7fffffff)
Enable/disable some optimizations.
enable_file_override (=0)
Redefines file_exists(), is_readable() and is_file() to look into cache
before : recommanded
blacklist_filename (=NULL)
Prevents caching some files you decide
consistency_checks (=0)
Computes a checksum at each file fetch. Not recommanded, ~5-
8% slowdown
opcache.save_comments (=1)
Saves PHPDoc comments to shared memory
41. OPcache other settings
enable_cli (=0)
Enables opcache in CLI mode
Long living apps like PHPUnit and COmposer mat benefit from the
optimizer and the cache
Other short scripts will pay an impact against the optimizer : don't
enable
huge_code_pages (=0)
Moves the PHP process code memory segment to huge pages
On some specific OS, with a mainly-statically-linked PHP, that can have
a beneficial impact
Check /proc/meminfo to activate HugePage before usage
protect_memory (=0)
mprotect() the SHM against writes. Useless until you find a bug, crash,
and want to debug it
42. Know what happens
error_log (=stderr)
File to write log to
log_verbosity_level (=1)
0=fatals … 4=debug
43. OPCache do's and don't's
Prime your cache smoothly
https://github.com/engineyard/ey-php-performance-tools
Prevent cache stampede
Have enough shared memory
Size your hashtables correctly
Try not to generate php files on runtime
Prevent highly modified files from beeing cached
Use blacklists
Every cache action will lock the shared memory
And PHP Engine is not threaded