SlideShare a Scribd company logo
1 of 106
Download to read offline
PHP & Performance
By: Ilia Alshanetsky
2
• This cycle happens
for every include
file, not just for the
"main" script.
• Compilation can
easily consume
more time than
execution.
PHP Script
Zend Compile
Zend Execute
@
include/require
method
function
call
Compiler/Opcode Caches
• Each PHP script is compiled only once for
each revision.
• Reduced File IO, opcodes are being read
from memory instead of being parsed from
disk.
• Opcodes can optimized for faster execution.
Quick Comparison
0
50
100
150
200
FUDforum
Smarty
phpMyAdmin
Stock PHP 4.4.0
APC
PHP Accelerator
eAccelerator
Zend Platform
5
• For absolute maximum performance, ensure that
all of the software is compiled to take advantage
of the available hardware.
• Enable all compiler optimizations with -O3
• Tune the code to your CPU via -march –mcpu
• CPU specific features -msse –mmmx
-mfpmath=sse
• Drop debug data -fomit-frame-pointer
export CFLAGS="-O3 -msse -mmmx -march=pentium3 
-mcpu=pentium3 -funroll-loops -mfpmath=sse 
-fomit-frame-pointer"
Compiler Optimizations
Web Server: File IO
✓ Keep
DirectoryIndex file
list as short as possible.
✓ Whenever possible
disable .htaccess via
AllowOverride
none.
✓ Use Options
FollowSymLinks to
simplify file access
process in Apache.
✓ If logs are
unnecessary disable
them.
✓ If logging is a must,
log everything to 1 file
and break it up during
the analysis stage.
7
• Syscall is function executed by the Kernel.
The goal is to minimize the number of these
calls needed to perform a request.
• Do not enable ExtendedStatus.
• For Deny/Allow rules use IPs rather then
domains.
• Do not enable HostnameLookups.
• Set ServerToken=prod
Web Server: Syscalls
8
• In theory KeepAlive is supposed to make
things faster, however if not used carefully
it can cripple the server.
• In Apache set KeepAlive timeout,
KeepAliveTimeout as low as possible.
Suggested value: 10 seconds.
• If the server is only serving dynamic
requests, disable KeepAlive all together.
Web Server: KeepAlive
9
• The goal is to pass off as much work to the kernel
as efficiently as possible.
• Optimizes PHP to OS Communication
• Reduces Number Of System Calls
Matching Your IO Sizes
PHP Apache OS Client
10
• Efficient
• Flexible
• In your script, with ob_start()
• Everywhere, with output_buffering = On
• Improves browser’s rendering speed
PHP: Output Control
PHP Apache
Apache: Output Control
• The idea is to hand off entire page to the
kernel without blocking.
• Set SendBufferSize = PageSize
Apache OS
OS: Output Control
OS (Linux)
/proc/sys/net/ipv4/tcp_wmem
4096 16384 maxcontentsize
min default max
/proc/sys/net/ipv4/tcp_mem
(maxcontentsize * maxclients) / pagesize
✴ Be careful on low memory systems!
OS Client
13
• While Apache is great for dynamic requests,
static requests can be served WAY FASTER
by other web servers.
๏ lighttpd
๏ Boa
๏ Tux
๏ thttpd
• For static requests these servers are easily
300-400% faster then Apache 1 or 2.
Static Content Serving
Less Output == Faster
• Saves server bandwidth (saves $$ too).
• Reduces server resource usage (CPU/
Memory/Disk)
• Pages load faster for clients.
• Reduces network IO high traffic sites,
where it is the primary bottleneck in
most cases.
15
• Most browsers support content compression.
• Compressed pages are on average are 6-8 times smaller.
๏ Apache 1 (mod_gzip / mod_deflate)
๏ Apache 2 (mod_deflate)
๏ PHP
‣ From PHP configuration zlib.output_compression=1
‣ From inside the script ob_start(“ob_gzhandler”)
✴ Compression will utilize 3%-5% of CPU.
Content Compression
Content Reduction
• Use a post-
processor like
Tidy to
remove
formatting,
comments and
CCSify the
code.
<?php
$o = array("clean" => true,
"drop-proprietary-attributes" => true,
"drop-font-tags" => true,
"drop-empty-paras" => true,
"hide-comments" => true,
"join-classes" => true,
"join-styles" => true
);
$tidy = tidy_parse_file("php.html", $o);
tidy_clean_repair($tidy);
echo $tidy;
?>
17
➡ register_globals = Off **
➡ magic_quotes_gpc = Off
➡ expose_php = Off
➡ register_argc_argv = Off
➡ always_populate_raw_post_data = Off **
➡ session.use_trans_sid = Off **
➡ session.auto_start = Off **
➡ session.gc_divisor = 1000 or 10000
Tuning PHP Configuration
18
• Identify Bottlenecks
• Track Resource Usage
• Generate Call Trees
• Create Progress Tracking Data
Profiling & Benchmarking
19
• Apache Bench
‣ ab utility bundled with Apache
• Siege
‣ http://www.joedog.org/JoeDog/Siege
• http_load (Excellent for latency tests)
‣ http://www.acme.com/software/http_load/
Testing Web Servers
Web Server Testing
Concurrency Level: 10
Time taken for tests: 0.265 seconds
Complete requests: 100
Failed requests: 0
Broken pipe errors: 0
Total transferred: 5077082 bytes
HTML transferred: 5061168 bytes
Requests per second: 377.36 [#/sec] (mean)
Time per request: 26.50 [ms] (mean)
Time per request: 2.65 [ms] (mean)
Transfer rate: 19158.80 [Kbytes/sec]
Latency Test
1000 fetches, 5 max parallel,
2.9648e+07 bytes,
in 0.813035 seconds
29648 mean bytes/connection
1229.96 fetches/sec,
3.64658e+07 bytes/sec
msecs/connect:
0.463202 mean, 12.082 max, 0.045 min
msecs/first-response:
3.12969 mean, 50.783 max, 0.811 min
HTTP response codes:
code 200 -- 1000
1 msec = 0.0001 seconds
22
• APD (Pure profiler)
‣ http://pecl.php.net/apd
• XDebug (Profiler & Debugger)
‣ http://xdebug.org/
• DBG (Profiler & Debugger)
‣ http://dd.cron.ru/dbg/
Profiling PHP Code
Profiling with APD
• Installation Steps
• pecl install apd
• Modify php.ini
zend_extension=apd.so
Zend Execute
APD Start
APD Finish
Process repeated for
every function/method call
24
• Profiling of a script starts from the point when the
apd_set_pprof_trace() function is called.
• All code executed prior, will not be profiled.
$parts = preg_split("!s!", "a b c");
function test(&$var) {
$var = base64_encode(trim($var));
}
apd_set_pprof_trace();
array_walk($parts, 'test');
✴ Use the auto_prepend_file php.ini setting to activate
profiling for an entire application.
Generating A Trace
Interpreting the Results
Real User System secs cumm.
%Time (excl/cumm) (excl/cumm) (excl/cumm) Calls call s/call Name
-----------------------------------------------------------------------------------------
82.4 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0007 0.0007 apd_set_pprof_trace
10.2 0.00 0.00 0.00 0.00 0.00 0.00 3 0.0000 0.0000 trim
4.3 0.00 0.00 0.00 0.00 0.00 0.00 3 0.0000 0.0000 base64_encode
1.9 0.00 0.00 0.00 0.00 0.00 0.00 3 0.0000 0.0000 test
0.6 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0000 0.0001 array_walk
0.6 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0000 0.0008 main
26
• Hard-drive is in most cases the slowest
part of the system, yet all the data
eventually comes from it.
• By adjust the drive configuration
parameters you can help your OS get
the most out of it.
Drive Tuning
27
• Use the hdparm utility to adjust
settings.
• -c1 - set IDE 32-bit I/O setting
• -d1 - enable DMA
• -u1 - enable IRQ unmasking
• -m16 - turn on multicount
• -X 34|66|100|133 - transfer mode
Drive Tuning Parameters
Validating Changes
Benchmark the affect of the changes using:
hdparm -tT /dev/[drive]
29
• One way to accelerate File IO operations is by
moving the files and directories to a RAM disk.
• On Linux this is extremely simple to do using via
tmpfs.
# Speed Up /tmp Directory
mount --bind -ttmpfs /tmp /tmp
# Accelerate Scripts Directory
mount --bind -ttmpfs /home/webroot /home/webroot
RAM Disk
30
• PHP’s session extension by default stores each
session inside a separate file.
• Many files in one directory reduce access speed.
➡ Assign each user their own session directory
➡ Split sessions into multiple directories
session.save_path = "N;/path"
Session Storage
Session Storage Alternatives
• File system is slow, lets use memory
• mm - native shared memory storage
• apc - use APC’s store/fetch/delete
• memcache - memory storage daemon
Now let’s tune PHP code
OOP Tips
• Always declare your static methods!
• Cleaner & Faster code
<?php
class bench {
    public function a() { return 1; }
    public static function b() { return 1; }
}
$s = microtime(1);
for ($i = 0; $i < 100000; $i++) bench::a();
$e = microtime(1);
echo "Dynamic Static Method: ".($e - $s)."n";
$s = microtime(1);
for ($i = 0; $i < 100000; $i++) bench::b();
$e = microtime(1);
echo "Declared Static Method: ".($e - $s)."n";
Speed Comparison
0
0.05
0.10
0.15
0.20
Declared Non-Declared
Use Class Constants
• Parsed at compile time, no execution
overhead.
• Faster lookups due to a smaller hash.
• “Namespacing” & shorter hash names.
• Cleaner code speeds up debugging ;-)
Avoid Magic
• Magic methods such as __get()/__set()
• Magic loading functions such as
__autoload()
• Dynamic methods via __call()
require_once() is once too many
lstat64("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=7368, ...}) = 0
lstat64("/tmp/a.php", {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
open("/tmp/a.php", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
fstat64(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
lstat64("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=7368, ...}) = 0
lstat64("/tmp/a.php", {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
open("/tmp/a.php", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
fstat64(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
<?php
require_once "./a.php";
require_once "./a.php";
• If you absolutely cannot avoid
require_once and include_once use full
paths.
• In PHP 5.2>= this will allow PHP to
avoid opening the file twice.
๏ php_version()
✓ PHP_VERSION constant
๏ php_uname(‘s’)
✓ PHP_OS constant
๏ php_sapi_name()
✓ PHP_SAPI constant
Avoid Pointless Function Calls
Quick Comparison
0
0.625
1.250
1.875
2.500
PHP_OS php_uname() php_uname(’s’)
0.04
2.08
1.88
Fastest Win32 Detection in the West
• Does not use functions
• Does not care about
WinXP, WinNT, Windows,
Windows98, NT 5.0, etc...
• Always available
$isWindows = 
DIRECTORY_SEPARATOR == '';
What time is it?
Rather then calling time(),
time() and time() again, use
$_SERVER[‘REQUEST_TIME’]
Provides a timestamp, with a
second precision, without any
function calls.
PCRE Slowdowns
$text = preg_replace( '/=?([^?]+)?/',
'=?iso-8859-1?', $origtext );
$text = preg_replace( 
'"/(n|t|rn|s)+/"', ' ', $origtext );
Use non-capturing patterns
• Placing ?: at the start of a sub-pattern makes it
non-capturing.
• This means PHP/PCRE does not need to
allocate memory to store the matched content
block.
$text = preg_replace( '/=?(?:[^?]+)?/',
'=?iso-8859-1?', $origtext );
$text = preg_replace( 
'"/(?:n|t|rn|s)+/"', ' ', $origtext );
End Result
0
8.75
17.50
26.25
35.00
30.92
26.38
Seconds
A 15% performance improvement, with
a 2 character change.
Capuring
Non-Capturing
If Possible Avoid Regex
<?php
// Slow
if (preg_match("!^foo_!i", "FoO_")) { }
// Much faster
if (!strncasecmp("foo_", "FoO_", 4)) { }
// Slow
if (preg_match("![a8f9]!", "sometext")) { }
// Faster
if (strpbrk("a8f9", "sometext")) { }
// Slow
if (preg_match("!string!i", "text")) {}
// Faster
if (stripos("text", "string") !== false) {} 
More Regex Avoidance
$text = preg_replace( "/n/", "n", $text);
In this case it would be simpler and to
mention faster to use a regular str_replace()
$text = str_replace( "/n/", "n", $text);
Speed Comparison
0
11.25
22.50
33.75
45.00
1 to 1 1 to 2 1 to 3 2 to 2
preg_replace str_replace strtr
Use strtr() Properly!
Any ideas on how we can make this code
10 times faster?
$rep = array( '-' => '*', '.' => '*' );
if ( sizeof( $globArr ) > 1 ) {
$glob = "-" . strtr( $globArr[1], $rep );
} else {
$glob = strtr( $globArr[0], $rep );
}
Use Strings!
Elimination of array operations speeds up
the code and simplifies the internal work
in strtr() function.
if ( sizeof( $globArr ) > 1 ) {
$glob = "-" . strtr( $globArr[1], '-.', '**' );
} else {
$glob = strtr( $globArr[0], '-.', '**' );
}
0 15 30 45 60
4.29
55.70
Seconds
strtr(string)
strtr(array)
Don’t Replace When you
• Any replacement operation requires
memory, if only to store the “modified”
result.
• A quick strpos() to determine if any
replacement is actually needed can save
memory and improve performance!
Test Scenario
$s = microtime(1);
for ($i = 0; $i < 10000; $i++)
    str_replace('Ilia', 'Derick', $str);
$e = microtime(1);
echo "non-check (match): ".($e - $s)."n";
$s = microtime(1);
for ($i = 0; $i < 10000; $i++)
    if (strpos($str, 'Ilia') !== false)
        str_replace('Ilia', 'Derick', $str);
$e = microtime(1);
echo "check (match): ".($e - $s)."n";
$str is a PHP 5.2 news files, roughly 95kb in size.
no-match
match
01.753.505.257.00
6.76
1.88
6.75
4.34
regular w/check
@ operator is evil!
• The error blocking operator, is the most
expensive character in PHP’s alphabet.
• This seemingly innocuous operator
actually performs fairly intensive
operations in the background.
@action();
$old = ini_set(“error_reporting”, 0);
action();
ini_set(“error_reporting”, $old);
Better String Comparison
<?php
// The Good
if (!strncmp(PHP_OS, 'WIN', 3)) {
if (!strncasecmp(PHP_OS, 'WIN', 3)) {
// The Bad
if (substr(PHP_OS, 0, 3) == 'WIN') {
if (strtolower(substr(PHP_OS, 0, 3))) == 'win') {
// And The Ugly
if (preg_match('!^WIN!', PHP_OS)) {
if (preg_match('!^WIN!i', PHP_OS)) {
Quick Benchmark
0
5
10
15
20
8.67 9.59
13.07
10.42
8.73
13.29
13.06
15.71
strcmp()
substr()
PCRE
EREG
Case Sensetive Non-Case Sensetive
Comparing From An Offset
• As of PHP 5, you don’t need to substr()
string segments from non-start position to
compare them thanks to substr_compare().
if (substr($class, -15) != 'text')
/* == */
if (substr_compare($class, 'text', -15))
Don’t Mis-use Constants
One of my biggest pet-peeves in PHP is
this kind of nonsense:
$foo = array("bar"=>0);
$foo[bar] = 1;
Why is this bad?
๏ 1 strtolower
๏ 2 hash lookups
๏ E_NOTICE error message generated
๏ temporary string being created on the
fly.
Performance Check
$foo[bar] = 1; /* vs */ $foo['bar'] = 1;
0
6.25
12.50
18.75
25.00
15.52
16.70
21.35
2.50
2.70
3.07
3 chars
6 chars
17 charsconstant
string
700% difference on average!!!
Fix “harmless” error messages
‣ Each error results in:
๏ Generation of a complex error string
๏ Output to stdout/stderr
๏ Potential write to a file or syslog
๏ In pre-5.2 releases may leak memory
in some rare instances.
Simplify for() loop
Avoid function calls within for() loop
control blocks.
<?php
for ( $i = 1; $i < sizeof($array); $i++ ) {}
for ( $i = 0; $i < count($array); $i++ ) {}
for ( $i = 0; $i < strlen($string); $i++ ) {}
Otherwise function is called for every loop
iteration.
Speed Check
for ($j = 0; $j < strlen('foo'); $j++) {}
/* vs */
$c = strlen('foo'); for ($j = 0; $j < $c; $j++) {}
for ($j = 0; $j < count($_SERVER); $j++) {}
/* vs */
$c = count($_SERVER); for ($j = 0; $j < $c; $j++){}
0 0.4 0.8 1.2 1.6 2.0
0.21
1.53
0.11
0.42
count()
strlen()
Before
After
Don’t Re-invent the Wheel
• It is surprising how frequently people try
to re-invent the wheel.
• Now a days PHP has
✓ 2,700 functions
✓ 80 core extensions
✓ 154 PECL extensions
• Chances are what you need already exists!
Use Full File Paths
• While it is convenient(??) to do require
“foo.php” and have it work, internally
it leads to significant overhead.
• Whenever possible you should use full
paths, that require no resolution in PHP.
The internals of file ops.
stat64("./b.php", {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
getcwd("/tmp", 4096) = 5
lstat64("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=18008, ...}) = 0
lstat64("/tmp/b.php", {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
open("/tmp/b.php", O_RDONLY)
The issue can be further exasperated by
the use of include_path.
66
References can be used to simply & accelerate access
to multi-dimensional arrays.
Reference Tricks
$a['b']['c'] = array();
// slow 2 extra hash lookups per access
for($i = 0; $i < 5; $i++)
$a['b']['c'][$i] = $i;
// much faster reference based approach
$ref =& $a['b']['c'];
for($i = 0; $i < 5; $i++)
$ref[$i] = $i;
Optimization Myths
✦ Removing comments makes code faster
✦ Using ‘ is faster than “
✦ Passing things by-reference makes code
faster
✦ Objects make code faster
✦ Ternary ? : is faster then if () { } else {}
68
Caching is the recognition and exploitation of
the fact that most "dynamic" data does not
change every time you request it.
Caching Approaches
• Complete page content caching
• Content pre-generation
• On-Demand caching
• Partial page caching
• SQL query caching
• Browser caching
“Blog” Scenario
<?php
require “/blog.inc”;
load_header();
$qry = mysql_query(“SELECT * FROM blog_entries
ORDER BY date DESC LIMIT 15”);
while ($entry = mysql_fetch_assoc($qry)) {
show_blog_entry($entry);
}
load_footer();
Cache Handler
function cache() {
list(,$dt) = mysql_fetch_row(mysql_query(“SELECT
MAX(date) FROM blog_entries”));
if (filemtime(“/blog/cache/index.html”) > $dt) {
// cache hit
readfile(“/blog/cache/index.html”);
exit;
}
init_cache();
}
function init_cache() {
ob_start();
register_shutdown_function(‘write_cache’);
}
function write_cache() {
echo $data = ob_get_clean();
$fname = “/blog/cache/index.html”;
$tmp_fname = tempnam(“/blog/cache”, “blog”);
file_put_contents($tmp_fname, $data);
rename($tmp_fname, $fname);
}
Cache Placement
<?php
require “/blog.inc”;
require “/cache.inc”;
cache();
load_header();
$qry = mysql_query(“SELECT * FROM blog_entries
ORDER BY date DESC LIMIT 15”);
while ($entry = mysql_fetch_assoc($qry)) {
show_blog_entry($entry);
}
load_footer();
Quick benchmark
Before After
Page Size 31,117 bytes 31,117 bytes
Latency 8.73 msec. 4.62 msec.
Req./Second 451 665
Serendipity Test
Before After
Page Size 25,853 bytes 25,853 bytes
Latency 199.3 msec. 42.37 msec.
Req./Second 24.7 112.2
Compressed Page Cache
if (!empty($_SERVER["HTTP_ACCEPT_ENCODING"])
&& strpos($_SERVER["HTTP_ACCEPT_ENCODING"],
'gzip') !== false) {
header('Content-Encoding: gzip');
readfile("/tmp/index.html.gz");
} else {
readfile(“ /blog/cache/index.html”);
}
function write_cache() {
echo $data = ob_get_clean();
$fname = “/blog/cache/index.html”;
$tmp_fname = tempnam(“/blog/cache”, “blog”);
file_put_contents($tmp_fname, $data);
rename($tmp_fname, $fname);
$tmp_name = tempnam(“/blog/cache”, “blog”);
copy("/tmp/index.html",
"compress.zlib://" . $tmp_name);
rename($tmp_name, "/tmp/index.html.gz");
}
Content Pre-generation
• Simplifies caching code
• No real-time work
• Entire cache can be easily rebuilt
• Can be used to bypass PHP entirely
• Predictable operation
Let’s Avoid PHP
• Concept
• Make product pages be .html pages
• Generate .html pages via PHP
• Static pages are served by the web
server, skipping the PHP overhead.
function content_generate($s, $e)
{
while ($s <= $e) {
$url = "http://store.com/product.php?id=".$s;
$file = "/cache/product_".$s;
$data = file_get_contents($url);
file_put_contents($file, $data);
copy($file, "compress.zlib://" . $file . ".gz");
$s++;
}
}
Livedocs Test
Before After
Page Size 30,896 bytes 30,896 bytes
Latency 611.2 msec. 2.37 msec.
Req./Second 5.29 1284.6
Pre-Generation Problems
• Disk utilization
• 2 files per-page X number of pages
• Generates pages no one may visit
• Generating all pages at once may take
too long.
On Demand Caching
• Advantages
• Generate what you need, when you
need it.
• Simple to setup
• Has all the speed advantages of pre-
generation.
404 Handler
• Concept
• Make all links lead to .html pages
• When page does not exist, have PHP
404 handler be triggered.
• The handler script generates the
missing page
• All future visitors access static content.
ErrorDocument 404 /generate_html.php
// sample URL http://site.com/products/123.html
$id = (int) basename($_SERVER[‘REDIRECT_URL’]);
if (!$id || $id < 0) { exit; }
$url = "http://store.com/product.php?id=".$id;
$file = "./products/".$id.”.html”;
$data = file_get_contents($url);
file_put_contents($file, $data, LOCK_EX);
copy($file, "compress.zlib://" . $file . ".gz");
Caching Quandary
My pages always have an ever
changing content and cannot be cached
in their entirety.
*Dynamic Content **Semi-Dynamic Content
APC to the Rescue!
Alternative PHP Cache (APC) is an
open source opcode cache. It happens
to provide handy PHP variable storage
mechanism we can use.
APC API
• apc_store([key], [variable], [time to live])
• key - cache entry identifier
• variable - PHP variable to store
• time to live - for long to store the data
• [variable] = apc_fetch([key])
• apc_delete([key])
if (!($promo = apc_fetch(‘promo’))) {
$promo = fetch_all_promos();
apc_store(‘promo’, $promo, 3600); // 1 hour
}
if (!($deals = apc_fetch(‘deal’))) {
$deals = fetch_all_deals();
apc_store(‘promo’, $promo, 600); // 10 mins
}
if (!($final_tmpl = apc_fetch(‘main_template’))) {
$final_tmpl = generate_front_page();
apc_store(‘main_template’, $final_tmpl, 86400);
} // 1 day
// fetch one promo & deal to display
$data[0] = $promo[array_rand($promo)];
$data[1] = $deals[array_rand($deals)];
// get the always dynamic sections
$data[2] = get_shopping_cart();
$data[3] = generate_greeting_msg();
// in the finalized page substitute semi-static content
echo str_replace(
array(
‘%%deals%%’, ‘%%promo%%’,
‘%%cart%%’, ‘%%greeting%%’
), $data, $final_tmpl);
SQL Caching
• In most applications the primary
bottleneck can often be traced to
“database work”.
• Caching of SQL can drastically reduce
the load caused by unavoidable,
complex queries.
Cache Tables
CREATE TABLE search_cache
(
skey CHAR(32) PRIMARY KEY,
rec_id INT NOT NULL,
age INT UNSIGNED,
INDEX(skey),
INDEX(age)
);
$key = md5(“user supplied search query”);
$tm = time(); $max_age = $tm - 3600 * 4; // 4h
$qry = “SELECT count(*) FROM search_cache
WHERE key=’{$key}’ AND age>”.$max_age;
if (!$pdo->query($qry)->fetchColumn()) {
// cache generation code is here
}
// Standard join against search_cache table to get
// the relevant records
Basic Search Cache
// clear old cache entries
$pdo->exec(“DELETE FROM search_cache
WHERE key=’{$key}’
AND age<=”.$max_age);
$qry = “INSERT INTO search_cache”;
$qry .= “ (key,age,rec_id) ”;
$qry .= “ SELECT ‘{$key}’, {$tm}, rec_id”;
$qry .= “ FROM [search qry] LIMIT 1000”;
$pdo->exec($qry);
Cache Generation Code
Browser Cache
• Advantages
• Reduces data sent to virtually zero
• Requires next to no server resources
• Disadvantages
• Flimsy control over cache age
• Not guaranteed to work
How to implement?
// Time to Cache
header(“Expires: ”.date(DATE_RFC822));
// Based on modification date
header(“Last-Modified: ”.date(DATE_RFC822));
// Content hash
header(“Etag: “.md5_file(“./page_cache”));
98
Most applications will end up using databases
for information storage. Improper use of this
resource can lead to significant and
continually increasing performance loss.
99
Most databases offers tools for analyzing
query execution.
EXPLAIN select * from users where login LIKE '%ilia%';
+----------+------+---------------+------+---------+------+-------+------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+----------+------+---------------+------+---------+------+-------+------------+
| mm_users | ALL | NULL | NULL | NULL | NULL | 27506 | where used |
+----------+------+---------------+------+---------+------+-------+------------+
EXPLAIN select * from users where login LIKE 'ilia%';
+----------+-------+---------------+-------+---------+------+------+------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+----------+-------+---------------+-------+---------+------+------+------------+
| mm_users | range | login | login | 50 | NULL | 2 | where used |
+----------+-------+---------------+-------+---------+------+------+------------+
Check Your Queries
100
Rather then creating a column for every Boolean
option, you can pack 32 of them into a single integer
field.
CREATE TABLE users (
is_active INT,
is_banned INT,
is_admin INT,
...
);
CREATE TABLE users (
user_opt INT,
...
);
user_opt & 1 // active
user_opt & 2 // banned
user_opt & 4 // admin
Bitwise Option Packing
101
• The simpler the code, the faster it runs,
it really is that simple.
• Syntactic sugar.
• Unnecessary wrappers.
• Wrapping one liners in functions.
• OO for the sake of OO.
KISS = Performance
Thank You For Listening!
• These slides
• http://www.ilia.ws/
• APC
• http://pecl.php.net/apc
• XDebug
• http://www.xdebug.org/
Optimizer (Why?)
• The opcodes generated by Zend
Engine are often inefficient.
• Some operations can be avoided
• A lot of temporary vars are not
necessary.
• Every compiler needs an
optimizer ;-)
i
Optimizer (How?)
PHP Script
Zend Compile
Zend Execute
@
OptimizerKinda Slow
What Can It Do?
• opt. heredoc
• print to echo
• GLOBALS[foo] to
foo
• inline known
constants
• eliminate NOP
• resolve partial file
paths.
• optionally inline
define() calls
• 60+ function calls
with static values
resolved.
• Much more...
Any other ideas?

More Related Content

What's hot

VUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareVUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareCosimo Streppone
 
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...Willian Molinari
 
Ansible presentation
Ansible presentationAnsible presentation
Ansible presentationKumar Y
 
Ansible for beginners
Ansible for beginnersAnsible for beginners
Ansible for beginnersKuo-Le Mei
 
Ansible presentation
Ansible presentationAnsible presentation
Ansible presentationJohn Lynch
 
Ansible roles done right
Ansible roles done rightAnsible roles done right
Ansible roles done rightDan Vaida
 
How we use and deploy Varnish at Opera
How we use and deploy Varnish at OperaHow we use and deploy Varnish at Opera
How we use and deploy Varnish at OperaCosimo Streppone
 
Hadoop meet Rex(How to construct hadoop cluster with rex)
Hadoop meet Rex(How to construct hadoop cluster with rex)Hadoop meet Rex(How to construct hadoop cluster with rex)
Hadoop meet Rex(How to construct hadoop cluster with rex)Jun Hong Kim
 
Setting up your Multi Engine Environment - Apache Railo and ColdFusion
Setting up your Multi Engine Environment - Apache Railo and ColdFusionSetting up your Multi Engine Environment - Apache Railo and ColdFusion
Setting up your Multi Engine Environment - Apache Railo and ColdFusionGavin Pickin
 
#OktoCampus - Workshop : An introduction to Ansible
#OktoCampus - Workshop : An introduction to Ansible#OktoCampus - Workshop : An introduction to Ansible
#OktoCampus - Workshop : An introduction to AnsibleCédric Delgehier
 
Ansible leveraging 2.0
Ansible leveraging 2.0Ansible leveraging 2.0
Ansible leveraging 2.0bcoca
 
My Opera meets Varnish, Dec 2009
My Opera meets Varnish, Dec 2009My Opera meets Varnish, Dec 2009
My Opera meets Varnish, Dec 2009Cosimo Streppone
 
Caching the Uncacheable
Caching the UncacheableCaching the Uncacheable
Caching the Uncacheabledanrot
 
A tour of Ansible
A tour of AnsibleA tour of Ansible
A tour of AnsibleDevOps Ltd.
 
Automation with ansible
Automation with ansibleAutomation with ansible
Automation with ansibleKhizer Naeem
 
Ansible Automation to Rule Them All
Ansible Automation to Rule Them AllAnsible Automation to Rule Them All
Ansible Automation to Rule Them AllTim Fairweather
 
Herd your chickens: Ansible for DB2 configuration management
Herd your chickens: Ansible for DB2 configuration managementHerd your chickens: Ansible for DB2 configuration management
Herd your chickens: Ansible for DB2 configuration managementFrederik Engelen
 

What's hot (20)

VUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareVUG5: Varnish at Opera Software
VUG5: Varnish at Opera Software
 
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
 
Ansible presentation
Ansible presentationAnsible presentation
Ansible presentation
 
Ansible for beginners
Ansible for beginnersAnsible for beginners
Ansible for beginners
 
Ansible intro
Ansible introAnsible intro
Ansible intro
 
Ansible presentation
Ansible presentationAnsible presentation
Ansible presentation
 
Ansible roles done right
Ansible roles done rightAnsible roles done right
Ansible roles done right
 
How we use and deploy Varnish at Opera
How we use and deploy Varnish at OperaHow we use and deploy Varnish at Opera
How we use and deploy Varnish at Opera
 
Hadoop meet Rex(How to construct hadoop cluster with rex)
Hadoop meet Rex(How to construct hadoop cluster with rex)Hadoop meet Rex(How to construct hadoop cluster with rex)
Hadoop meet Rex(How to construct hadoop cluster with rex)
 
Setting up your Multi Engine Environment - Apache Railo and ColdFusion
Setting up your Multi Engine Environment - Apache Railo and ColdFusionSetting up your Multi Engine Environment - Apache Railo and ColdFusion
Setting up your Multi Engine Environment - Apache Railo and ColdFusion
 
#OktoCampus - Workshop : An introduction to Ansible
#OktoCampus - Workshop : An introduction to Ansible#OktoCampus - Workshop : An introduction to Ansible
#OktoCampus - Workshop : An introduction to Ansible
 
Ansible leveraging 2.0
Ansible leveraging 2.0Ansible leveraging 2.0
Ansible leveraging 2.0
 
My Opera meets Varnish, Dec 2009
My Opera meets Varnish, Dec 2009My Opera meets Varnish, Dec 2009
My Opera meets Varnish, Dec 2009
 
Caching the Uncacheable
Caching the UncacheableCaching the Uncacheable
Caching the Uncacheable
 
Ansible best practices
Ansible best practicesAnsible best practices
Ansible best practices
 
A tour of Ansible
A tour of AnsibleA tour of Ansible
A tour of Ansible
 
Automation with ansible
Automation with ansibleAutomation with ansible
Automation with ansible
 
Ansible Automation to Rule Them All
Ansible Automation to Rule Them AllAnsible Automation to Rule Them All
Ansible Automation to Rule Them All
 
FreeBSD: Dev to Prod
FreeBSD: Dev to ProdFreeBSD: Dev to Prod
FreeBSD: Dev to Prod
 
Herd your chickens: Ansible for DB2 configuration management
Herd your chickens: Ansible for DB2 configuration managementHerd your chickens: Ansible for DB2 configuration management
Herd your chickens: Ansible for DB2 configuration management
 

Viewers also liked

Last train to php 7
Last train to php 7Last train to php 7
Last train to php 7Damien Seguy
 
Hunt for dead code
Hunt for dead codeHunt for dead code
Hunt for dead codeDamien Seguy
 
Php 7.2 compliance workshop php benelux
Php 7.2 compliance workshop php beneluxPhp 7.2 compliance workshop php benelux
Php 7.2 compliance workshop php beneluxDamien Seguy
 
Php in the graph (Gremlin 3)
Php in the graph (Gremlin 3)Php in the graph (Gremlin 3)
Php in the graph (Gremlin 3)Damien Seguy
 
Review unknown code with static analysis - bredaphp
Review unknown code with static analysis - bredaphpReview unknown code with static analysis - bredaphp
Review unknown code with static analysis - bredaphpDamien Seguy
 
Static analysis saved my code tonight
Static analysis saved my code tonightStatic analysis saved my code tonight
Static analysis saved my code tonightDamien Seguy
 
Google Analytics Campaign Tracking Fundamentals
Google Analytics Campaign Tracking FundamentalsGoogle Analytics Campaign Tracking Fundamentals
Google Analytics Campaign Tracking FundamentalsKayden Kelly
 
當六脈神劍遇上 PhpStorm
當六脈神劍遇上 PhpStorm當六脈神劍遇上 PhpStorm
當六脈神劍遇上 PhpStormOomusou Xiao
 
symfony: Simplify your professional web development with PHP (Symfony PHP Que...
symfony: Simplify your professional web development with PHP (Symfony PHP Que...symfony: Simplify your professional web development with PHP (Symfony PHP Que...
symfony: Simplify your professional web development with PHP (Symfony PHP Que...Fabien Potencier
 
Machine learning in php php con poland
Machine learning in php   php con polandMachine learning in php   php con poland
Machine learning in php php con polandDamien Seguy
 
Machine learning in php
Machine learning in phpMachine learning in php
Machine learning in phpDamien Seguy
 
S3 Overview Presentation
S3 Overview PresentationS3 Overview Presentation
S3 Overview Presentationbcburchn
 
A la recherche du code mort
A la recherche du code mortA la recherche du code mort
A la recherche du code mortDamien Seguy
 
Reactive Laravel - Laravel meetup Groningen
Reactive Laravel - Laravel meetup GroningenReactive Laravel - Laravel meetup Groningen
Reactive Laravel - Laravel meetup GroningenJasper Staats
 

Viewers also liked (20)

Last train to php 7
Last train to php 7Last train to php 7
Last train to php 7
 
Hunt for dead code
Hunt for dead codeHunt for dead code
Hunt for dead code
 
Php 7.2 compliance workshop php benelux
Php 7.2 compliance workshop php beneluxPhp 7.2 compliance workshop php benelux
Php 7.2 compliance workshop php benelux
 
Php in the graph (Gremlin 3)
Php in the graph (Gremlin 3)Php in the graph (Gremlin 3)
Php in the graph (Gremlin 3)
 
Review unknown code with static analysis - bredaphp
Review unknown code with static analysis - bredaphpReview unknown code with static analysis - bredaphp
Review unknown code with static analysis - bredaphp
 
Static analysis saved my code tonight
Static analysis saved my code tonightStatic analysis saved my code tonight
Static analysis saved my code tonight
 
Google Analytics Campaign Tracking Fundamentals
Google Analytics Campaign Tracking FundamentalsGoogle Analytics Campaign Tracking Fundamentals
Google Analytics Campaign Tracking Fundamentals
 
當六脈神劍遇上 PhpStorm
當六脈神劍遇上 PhpStorm當六脈神劍遇上 PhpStorm
當六脈神劍遇上 PhpStorm
 
symfony: Simplify your professional web development with PHP (Symfony PHP Que...
symfony: Simplify your professional web development with PHP (Symfony PHP Que...symfony: Simplify your professional web development with PHP (Symfony PHP Que...
symfony: Simplify your professional web development with PHP (Symfony PHP Que...
 
Machine learning in php php con poland
Machine learning in php   php con polandMachine learning in php   php con poland
Machine learning in php php con poland
 
Machine learning in php
Machine learning in phpMachine learning in php
Machine learning in php
 
Php performance-talk
Php performance-talkPhp performance-talk
Php performance-talk
 
S3 Overview Presentation
S3 Overview PresentationS3 Overview Presentation
S3 Overview Presentation
 
A la recherche du code mort
A la recherche du code mortA la recherche du code mort
A la recherche du code mort
 
Functional programming with php7
Functional programming with php7Functional programming with php7
Functional programming with php7
 
Reactive Laravel - Laravel meetup Groningen
Reactive Laravel - Laravel meetup GroningenReactive Laravel - Laravel meetup Groningen
Reactive Laravel - Laravel meetup Groningen
 
Design patterns in PHP
Design patterns in PHPDesign patterns in PHP
Design patterns in PHP
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
What's new with PHP7
What's new with PHP7What's new with PHP7
What's new with PHP7
 
(Have a) rest with Laravel
(Have a) rest with Laravel(Have a) rest with Laravel
(Have a) rest with Laravel
 

Similar to php & performance

Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalabilityWim Godden
 
Caching with Memcached and APC
Caching with Memcached and APCCaching with Memcached and APC
Caching with Memcached and APCBen Ramsey
 
PHP Performance with APC + Memcached
PHP Performance with APC + MemcachedPHP Performance with APC + Memcached
PHP Performance with APC + MemcachedFord AntiTrust
 
Php through the eyes of a hoster phpbnl11
Php through the eyes of a hoster phpbnl11Php through the eyes of a hoster phpbnl11
Php through the eyes of a hoster phpbnl11Combell NV
 
Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalabilityWim Godden
 
Caching and tuning fun for high scalability @ FOSDEM 2012
Caching and tuning fun for high scalability @ FOSDEM 2012Caching and tuning fun for high scalability @ FOSDEM 2012
Caching and tuning fun for high scalability @ FOSDEM 2012Wim Godden
 
Securing Your Webserver By Pradeep Sharma
Securing Your Webserver By Pradeep SharmaSecuring Your Webserver By Pradeep Sharma
Securing Your Webserver By Pradeep SharmaOSSCube
 
Zendcon scaling magento
Zendcon scaling magentoZendcon scaling magento
Zendcon scaling magentoMathew Beane
 
Php through the eyes of a hoster confoo
Php through the eyes of a hoster confooPhp through the eyes of a hoster confoo
Php through the eyes of a hoster confooCombell NV
 
Northeast PHP - High Performance PHP
Northeast PHP - High Performance PHPNortheast PHP - High Performance PHP
Northeast PHP - High Performance PHPJonathan Klein
 
Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011Wim Godden
 
Profiling PHP with Xdebug / Webgrind
Profiling PHP with Xdebug / WebgrindProfiling PHP with Xdebug / Webgrind
Profiling PHP with Xdebug / WebgrindSam Keen
 
Php through the eyes of a hoster
Php through the eyes of a hosterPhp through the eyes of a hoster
Php through the eyes of a hosterCombell NV
 
Apc presentation
Apc presentationApc presentation
Apc presentationguestef8544
 
Scaling python webapps from 0 to 50 million users - A top-down approach
Scaling python webapps from 0 to 50 million users - A top-down approachScaling python webapps from 0 to 50 million users - A top-down approach
Scaling python webapps from 0 to 50 million users - A top-down approachJinal Jhaveri
 
Bottom to Top Stack Optimization with LAMP
Bottom to Top Stack Optimization with LAMPBottom to Top Stack Optimization with LAMP
Bottom to Top Stack Optimization with LAMPkatzgrau
 
Bottom to Top Stack Optimization - CICON2011
Bottom to Top Stack Optimization - CICON2011Bottom to Top Stack Optimization - CICON2011
Bottom to Top Stack Optimization - CICON2011CodeIgniter Conference
 
Heavy Web Optimization: Backend
Heavy Web Optimization: BackendHeavy Web Optimization: Backend
Heavy Web Optimization: BackendVõ Duy Tuấn
 
Performance tuning with zend framework
Performance tuning with zend frameworkPerformance tuning with zend framework
Performance tuning with zend frameworkAlan Seiden
 
Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalabilityWim Godden
 

Similar to php & performance (20)

Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalability
 
Caching with Memcached and APC
Caching with Memcached and APCCaching with Memcached and APC
Caching with Memcached and APC
 
PHP Performance with APC + Memcached
PHP Performance with APC + MemcachedPHP Performance with APC + Memcached
PHP Performance with APC + Memcached
 
Php through the eyes of a hoster phpbnl11
Php through the eyes of a hoster phpbnl11Php through the eyes of a hoster phpbnl11
Php through the eyes of a hoster phpbnl11
 
Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalability
 
Caching and tuning fun for high scalability @ FOSDEM 2012
Caching and tuning fun for high scalability @ FOSDEM 2012Caching and tuning fun for high scalability @ FOSDEM 2012
Caching and tuning fun for high scalability @ FOSDEM 2012
 
Securing Your Webserver By Pradeep Sharma
Securing Your Webserver By Pradeep SharmaSecuring Your Webserver By Pradeep Sharma
Securing Your Webserver By Pradeep Sharma
 
Zendcon scaling magento
Zendcon scaling magentoZendcon scaling magento
Zendcon scaling magento
 
Php through the eyes of a hoster confoo
Php through the eyes of a hoster confooPhp through the eyes of a hoster confoo
Php through the eyes of a hoster confoo
 
Northeast PHP - High Performance PHP
Northeast PHP - High Performance PHPNortheast PHP - High Performance PHP
Northeast PHP - High Performance PHP
 
Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011
 
Profiling PHP with Xdebug / Webgrind
Profiling PHP with Xdebug / WebgrindProfiling PHP with Xdebug / Webgrind
Profiling PHP with Xdebug / Webgrind
 
Php through the eyes of a hoster
Php through the eyes of a hosterPhp through the eyes of a hoster
Php through the eyes of a hoster
 
Apc presentation
Apc presentationApc presentation
Apc presentation
 
Scaling python webapps from 0 to 50 million users - A top-down approach
Scaling python webapps from 0 to 50 million users - A top-down approachScaling python webapps from 0 to 50 million users - A top-down approach
Scaling python webapps from 0 to 50 million users - A top-down approach
 
Bottom to Top Stack Optimization with LAMP
Bottom to Top Stack Optimization with LAMPBottom to Top Stack Optimization with LAMP
Bottom to Top Stack Optimization with LAMP
 
Bottom to Top Stack Optimization - CICON2011
Bottom to Top Stack Optimization - CICON2011Bottom to Top Stack Optimization - CICON2011
Bottom to Top Stack Optimization - CICON2011
 
Heavy Web Optimization: Backend
Heavy Web Optimization: BackendHeavy Web Optimization: Backend
Heavy Web Optimization: Backend
 
Performance tuning with zend framework
Performance tuning with zend frameworkPerformance tuning with zend framework
Performance tuning with zend framework
 
Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalability
 

Recently uploaded

Benefits & Challenges of Inclusive Education
Benefits & Challenges of Inclusive EducationBenefits & Challenges of Inclusive Education
Benefits & Challenges of Inclusive EducationMJDuyan
 
Patterns of Written Texts Across Disciplines.pptx
Patterns of Written Texts Across Disciplines.pptxPatterns of Written Texts Across Disciplines.pptx
Patterns of Written Texts Across Disciplines.pptxMYDA ANGELICA SUAN
 
How to Manage Cross-Selling in Odoo 17 Sales
How to Manage Cross-Selling in Odoo 17 SalesHow to Manage Cross-Selling in Odoo 17 Sales
How to Manage Cross-Selling in Odoo 17 SalesCeline George
 
How to Make a Field read-only in Odoo 17
How to Make a Field read-only in Odoo 17How to Make a Field read-only in Odoo 17
How to Make a Field read-only in Odoo 17Celine George
 
The Stolen Bacillus by Herbert George Wells
The Stolen Bacillus by Herbert George WellsThe Stolen Bacillus by Herbert George Wells
The Stolen Bacillus by Herbert George WellsEugene Lysak
 
DUST OF SNOW_BY ROBERT FROST_EDITED BY_ TANMOY MISHRA
DUST OF SNOW_BY ROBERT FROST_EDITED BY_ TANMOY MISHRADUST OF SNOW_BY ROBERT FROST_EDITED BY_ TANMOY MISHRA
DUST OF SNOW_BY ROBERT FROST_EDITED BY_ TANMOY MISHRATanmoy Mishra
 
Maximizing Impact_ Nonprofit Website Planning, Budgeting, and Design.pdf
Maximizing Impact_ Nonprofit Website Planning, Budgeting, and Design.pdfMaximizing Impact_ Nonprofit Website Planning, Budgeting, and Design.pdf
Maximizing Impact_ Nonprofit Website Planning, Budgeting, and Design.pdfTechSoup
 
In - Vivo and In - Vitro Correlation.pptx
In - Vivo and In - Vitro Correlation.pptxIn - Vivo and In - Vitro Correlation.pptx
In - Vivo and In - Vitro Correlation.pptxAditiChauhan701637
 
PISA-VET launch_El Iza Mohamedou_19 March 2024.pptx
PISA-VET launch_El Iza Mohamedou_19 March 2024.pptxPISA-VET launch_El Iza Mohamedou_19 March 2024.pptx
PISA-VET launch_El Iza Mohamedou_19 March 2024.pptxEduSkills OECD
 
5 charts on South Africa as a source country for international student recrui...
5 charts on South Africa as a source country for international student recrui...5 charts on South Africa as a source country for international student recrui...
5 charts on South Africa as a source country for international student recrui...CaraSkikne1
 
HED Office Sohayok Exam Question Solution 2023.pdf
HED Office Sohayok Exam Question Solution 2023.pdfHED Office Sohayok Exam Question Solution 2023.pdf
HED Office Sohayok Exam Question Solution 2023.pdfMohonDas
 
How to Solve Singleton Error in the Odoo 17
How to Solve Singleton Error in the  Odoo 17How to Solve Singleton Error in the  Odoo 17
How to Solve Singleton Error in the Odoo 17Celine George
 
Patient Counselling. Definition of patient counseling; steps involved in pati...
Patient Counselling. Definition of patient counseling; steps involved in pati...Patient Counselling. Definition of patient counseling; steps involved in pati...
Patient Counselling. Definition of patient counseling; steps involved in pati...raviapr7
 
Prescribed medication order and communication skills.pptx
Prescribed medication order and communication skills.pptxPrescribed medication order and communication skills.pptx
Prescribed medication order and communication skills.pptxraviapr7
 
3.21.24 The Origins of Black Power.pptx
3.21.24  The Origins of Black Power.pptx3.21.24  The Origins of Black Power.pptx
3.21.24 The Origins of Black Power.pptxmary850239
 
What is the Future of QuickBooks DeskTop?
What is the Future of QuickBooks DeskTop?What is the Future of QuickBooks DeskTop?
What is the Future of QuickBooks DeskTop?TechSoup
 
P4C x ELT = P4ELT: Its Theoretical Background (Kanazawa, 2024 March).pdf
P4C x ELT = P4ELT: Its Theoretical Background (Kanazawa, 2024 March).pdfP4C x ELT = P4ELT: Its Theoretical Background (Kanazawa, 2024 March).pdf
P4C x ELT = P4ELT: Its Theoretical Background (Kanazawa, 2024 March).pdfYu Kanazawa / Osaka University
 
Philosophy of Education and Educational Philosophy
Philosophy of Education  and Educational PhilosophyPhilosophy of Education  and Educational Philosophy
Philosophy of Education and Educational PhilosophyShuvankar Madhu
 
Education and training program in the hospital APR.pptx
Education and training program in the hospital APR.pptxEducation and training program in the hospital APR.pptx
Education and training program in the hospital APR.pptxraviapr7
 
How to Add a many2many Relational Field in Odoo 17
How to Add a many2many Relational Field in Odoo 17How to Add a many2many Relational Field in Odoo 17
How to Add a many2many Relational Field in Odoo 17Celine George
 

Recently uploaded (20)

Benefits & Challenges of Inclusive Education
Benefits & Challenges of Inclusive EducationBenefits & Challenges of Inclusive Education
Benefits & Challenges of Inclusive Education
 
Patterns of Written Texts Across Disciplines.pptx
Patterns of Written Texts Across Disciplines.pptxPatterns of Written Texts Across Disciplines.pptx
Patterns of Written Texts Across Disciplines.pptx
 
How to Manage Cross-Selling in Odoo 17 Sales
How to Manage Cross-Selling in Odoo 17 SalesHow to Manage Cross-Selling in Odoo 17 Sales
How to Manage Cross-Selling in Odoo 17 Sales
 
How to Make a Field read-only in Odoo 17
How to Make a Field read-only in Odoo 17How to Make a Field read-only in Odoo 17
How to Make a Field read-only in Odoo 17
 
The Stolen Bacillus by Herbert George Wells
The Stolen Bacillus by Herbert George WellsThe Stolen Bacillus by Herbert George Wells
The Stolen Bacillus by Herbert George Wells
 
DUST OF SNOW_BY ROBERT FROST_EDITED BY_ TANMOY MISHRA
DUST OF SNOW_BY ROBERT FROST_EDITED BY_ TANMOY MISHRADUST OF SNOW_BY ROBERT FROST_EDITED BY_ TANMOY MISHRA
DUST OF SNOW_BY ROBERT FROST_EDITED BY_ TANMOY MISHRA
 
Maximizing Impact_ Nonprofit Website Planning, Budgeting, and Design.pdf
Maximizing Impact_ Nonprofit Website Planning, Budgeting, and Design.pdfMaximizing Impact_ Nonprofit Website Planning, Budgeting, and Design.pdf
Maximizing Impact_ Nonprofit Website Planning, Budgeting, and Design.pdf
 
In - Vivo and In - Vitro Correlation.pptx
In - Vivo and In - Vitro Correlation.pptxIn - Vivo and In - Vitro Correlation.pptx
In - Vivo and In - Vitro Correlation.pptx
 
PISA-VET launch_El Iza Mohamedou_19 March 2024.pptx
PISA-VET launch_El Iza Mohamedou_19 March 2024.pptxPISA-VET launch_El Iza Mohamedou_19 March 2024.pptx
PISA-VET launch_El Iza Mohamedou_19 March 2024.pptx
 
5 charts on South Africa as a source country for international student recrui...
5 charts on South Africa as a source country for international student recrui...5 charts on South Africa as a source country for international student recrui...
5 charts on South Africa as a source country for international student recrui...
 
HED Office Sohayok Exam Question Solution 2023.pdf
HED Office Sohayok Exam Question Solution 2023.pdfHED Office Sohayok Exam Question Solution 2023.pdf
HED Office Sohayok Exam Question Solution 2023.pdf
 
How to Solve Singleton Error in the Odoo 17
How to Solve Singleton Error in the  Odoo 17How to Solve Singleton Error in the  Odoo 17
How to Solve Singleton Error in the Odoo 17
 
Patient Counselling. Definition of patient counseling; steps involved in pati...
Patient Counselling. Definition of patient counseling; steps involved in pati...Patient Counselling. Definition of patient counseling; steps involved in pati...
Patient Counselling. Definition of patient counseling; steps involved in pati...
 
Prescribed medication order and communication skills.pptx
Prescribed medication order and communication skills.pptxPrescribed medication order and communication skills.pptx
Prescribed medication order and communication skills.pptx
 
3.21.24 The Origins of Black Power.pptx
3.21.24  The Origins of Black Power.pptx3.21.24  The Origins of Black Power.pptx
3.21.24 The Origins of Black Power.pptx
 
What is the Future of QuickBooks DeskTop?
What is the Future of QuickBooks DeskTop?What is the Future of QuickBooks DeskTop?
What is the Future of QuickBooks DeskTop?
 
P4C x ELT = P4ELT: Its Theoretical Background (Kanazawa, 2024 March).pdf
P4C x ELT = P4ELT: Its Theoretical Background (Kanazawa, 2024 March).pdfP4C x ELT = P4ELT: Its Theoretical Background (Kanazawa, 2024 March).pdf
P4C x ELT = P4ELT: Its Theoretical Background (Kanazawa, 2024 March).pdf
 
Philosophy of Education and Educational Philosophy
Philosophy of Education  and Educational PhilosophyPhilosophy of Education  and Educational Philosophy
Philosophy of Education and Educational Philosophy
 
Education and training program in the hospital APR.pptx
Education and training program in the hospital APR.pptxEducation and training program in the hospital APR.pptx
Education and training program in the hospital APR.pptx
 
How to Add a many2many Relational Field in Odoo 17
How to Add a many2many Relational Field in Odoo 17How to Add a many2many Relational Field in Odoo 17
How to Add a many2many Relational Field in Odoo 17
 

php & performance

  • 1. PHP & Performance By: Ilia Alshanetsky
  • 2. 2 • This cycle happens for every include file, not just for the "main" script. • Compilation can easily consume more time than execution. PHP Script Zend Compile Zend Execute @ include/require method function call
  • 3. Compiler/Opcode Caches • Each PHP script is compiled only once for each revision. • Reduced File IO, opcodes are being read from memory instead of being parsed from disk. • Opcodes can optimized for faster execution.
  • 4. Quick Comparison 0 50 100 150 200 FUDforum Smarty phpMyAdmin Stock PHP 4.4.0 APC PHP Accelerator eAccelerator Zend Platform
  • 5. 5 • For absolute maximum performance, ensure that all of the software is compiled to take advantage of the available hardware. • Enable all compiler optimizations with -O3 • Tune the code to your CPU via -march –mcpu • CPU specific features -msse –mmmx -mfpmath=sse • Drop debug data -fomit-frame-pointer export CFLAGS="-O3 -msse -mmmx -march=pentium3 -mcpu=pentium3 -funroll-loops -mfpmath=sse -fomit-frame-pointer" Compiler Optimizations
  • 6. Web Server: File IO ✓ Keep DirectoryIndex file list as short as possible. ✓ Whenever possible disable .htaccess via AllowOverride none. ✓ Use Options FollowSymLinks to simplify file access process in Apache. ✓ If logs are unnecessary disable them. ✓ If logging is a must, log everything to 1 file and break it up during the analysis stage.
  • 7. 7 • Syscall is function executed by the Kernel. The goal is to minimize the number of these calls needed to perform a request. • Do not enable ExtendedStatus. • For Deny/Allow rules use IPs rather then domains. • Do not enable HostnameLookups. • Set ServerToken=prod Web Server: Syscalls
  • 8. 8 • In theory KeepAlive is supposed to make things faster, however if not used carefully it can cripple the server. • In Apache set KeepAlive timeout, KeepAliveTimeout as low as possible. Suggested value: 10 seconds. • If the server is only serving dynamic requests, disable KeepAlive all together. Web Server: KeepAlive
  • 9. 9 • The goal is to pass off as much work to the kernel as efficiently as possible. • Optimizes PHP to OS Communication • Reduces Number Of System Calls Matching Your IO Sizes PHP Apache OS Client
  • 10. 10 • Efficient • Flexible • In your script, with ob_start() • Everywhere, with output_buffering = On • Improves browser’s rendering speed PHP: Output Control PHP Apache
  • 11. Apache: Output Control • The idea is to hand off entire page to the kernel without blocking. • Set SendBufferSize = PageSize Apache OS
  • 12. OS: Output Control OS (Linux) /proc/sys/net/ipv4/tcp_wmem 4096 16384 maxcontentsize min default max /proc/sys/net/ipv4/tcp_mem (maxcontentsize * maxclients) / pagesize ✴ Be careful on low memory systems! OS Client
  • 13. 13 • While Apache is great for dynamic requests, static requests can be served WAY FASTER by other web servers. ๏ lighttpd ๏ Boa ๏ Tux ๏ thttpd • For static requests these servers are easily 300-400% faster then Apache 1 or 2. Static Content Serving
  • 14. Less Output == Faster • Saves server bandwidth (saves $$ too). • Reduces server resource usage (CPU/ Memory/Disk) • Pages load faster for clients. • Reduces network IO high traffic sites, where it is the primary bottleneck in most cases.
  • 15. 15 • Most browsers support content compression. • Compressed pages are on average are 6-8 times smaller. ๏ Apache 1 (mod_gzip / mod_deflate) ๏ Apache 2 (mod_deflate) ๏ PHP ‣ From PHP configuration zlib.output_compression=1 ‣ From inside the script ob_start(“ob_gzhandler”) ✴ Compression will utilize 3%-5% of CPU. Content Compression
  • 16. Content Reduction • Use a post- processor like Tidy to remove formatting, comments and CCSify the code. <?php $o = array("clean" => true, "drop-proprietary-attributes" => true, "drop-font-tags" => true, "drop-empty-paras" => true, "hide-comments" => true, "join-classes" => true, "join-styles" => true ); $tidy = tidy_parse_file("php.html", $o); tidy_clean_repair($tidy); echo $tidy; ?>
  • 17. 17 ➡ register_globals = Off ** ➡ magic_quotes_gpc = Off ➡ expose_php = Off ➡ register_argc_argv = Off ➡ always_populate_raw_post_data = Off ** ➡ session.use_trans_sid = Off ** ➡ session.auto_start = Off ** ➡ session.gc_divisor = 1000 or 10000 Tuning PHP Configuration
  • 18. 18 • Identify Bottlenecks • Track Resource Usage • Generate Call Trees • Create Progress Tracking Data Profiling & Benchmarking
  • 19. 19 • Apache Bench ‣ ab utility bundled with Apache • Siege ‣ http://www.joedog.org/JoeDog/Siege • http_load (Excellent for latency tests) ‣ http://www.acme.com/software/http_load/ Testing Web Servers
  • 20. Web Server Testing Concurrency Level: 10 Time taken for tests: 0.265 seconds Complete requests: 100 Failed requests: 0 Broken pipe errors: 0 Total transferred: 5077082 bytes HTML transferred: 5061168 bytes Requests per second: 377.36 [#/sec] (mean) Time per request: 26.50 [ms] (mean) Time per request: 2.65 [ms] (mean) Transfer rate: 19158.80 [Kbytes/sec]
  • 21. Latency Test 1000 fetches, 5 max parallel, 2.9648e+07 bytes, in 0.813035 seconds 29648 mean bytes/connection 1229.96 fetches/sec, 3.64658e+07 bytes/sec msecs/connect: 0.463202 mean, 12.082 max, 0.045 min msecs/first-response: 3.12969 mean, 50.783 max, 0.811 min HTTP response codes: code 200 -- 1000 1 msec = 0.0001 seconds
  • 22. 22 • APD (Pure profiler) ‣ http://pecl.php.net/apd • XDebug (Profiler & Debugger) ‣ http://xdebug.org/ • DBG (Profiler & Debugger) ‣ http://dd.cron.ru/dbg/ Profiling PHP Code
  • 23. Profiling with APD • Installation Steps • pecl install apd • Modify php.ini zend_extension=apd.so Zend Execute APD Start APD Finish Process repeated for every function/method call
  • 24. 24 • Profiling of a script starts from the point when the apd_set_pprof_trace() function is called. • All code executed prior, will not be profiled. $parts = preg_split("!s!", "a b c"); function test(&$var) { $var = base64_encode(trim($var)); } apd_set_pprof_trace(); array_walk($parts, 'test'); ✴ Use the auto_prepend_file php.ini setting to activate profiling for an entire application. Generating A Trace
  • 25. Interpreting the Results Real User System secs cumm. %Time (excl/cumm) (excl/cumm) (excl/cumm) Calls call s/call Name ----------------------------------------------------------------------------------------- 82.4 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0007 0.0007 apd_set_pprof_trace 10.2 0.00 0.00 0.00 0.00 0.00 0.00 3 0.0000 0.0000 trim 4.3 0.00 0.00 0.00 0.00 0.00 0.00 3 0.0000 0.0000 base64_encode 1.9 0.00 0.00 0.00 0.00 0.00 0.00 3 0.0000 0.0000 test 0.6 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0000 0.0001 array_walk 0.6 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0000 0.0008 main
  • 26. 26 • Hard-drive is in most cases the slowest part of the system, yet all the data eventually comes from it. • By adjust the drive configuration parameters you can help your OS get the most out of it. Drive Tuning
  • 27. 27 • Use the hdparm utility to adjust settings. • -c1 - set IDE 32-bit I/O setting • -d1 - enable DMA • -u1 - enable IRQ unmasking • -m16 - turn on multicount • -X 34|66|100|133 - transfer mode Drive Tuning Parameters
  • 28. Validating Changes Benchmark the affect of the changes using: hdparm -tT /dev/[drive]
  • 29. 29 • One way to accelerate File IO operations is by moving the files and directories to a RAM disk. • On Linux this is extremely simple to do using via tmpfs. # Speed Up /tmp Directory mount --bind -ttmpfs /tmp /tmp # Accelerate Scripts Directory mount --bind -ttmpfs /home/webroot /home/webroot RAM Disk
  • 30. 30 • PHP’s session extension by default stores each session inside a separate file. • Many files in one directory reduce access speed. ➡ Assign each user their own session directory ➡ Split sessions into multiple directories session.save_path = "N;/path" Session Storage
  • 31. Session Storage Alternatives • File system is slow, lets use memory • mm - native shared memory storage • apc - use APC’s store/fetch/delete • memcache - memory storage daemon
  • 32. Now let’s tune PHP code
  • 33. OOP Tips • Always declare your static methods! • Cleaner & Faster code <?php class bench {     public function a() { return 1; }     public static function b() { return 1; } } $s = microtime(1); for ($i = 0; $i < 100000; $i++) bench::a(); $e = microtime(1); echo "Dynamic Static Method: ".($e - $s)."n"; $s = microtime(1); for ($i = 0; $i < 100000; $i++) bench::b(); $e = microtime(1); echo "Declared Static Method: ".($e - $s)."n";
  • 35. Use Class Constants • Parsed at compile time, no execution overhead. • Faster lookups due to a smaller hash. • “Namespacing” & shorter hash names. • Cleaner code speeds up debugging ;-)
  • 36. Avoid Magic • Magic methods such as __get()/__set() • Magic loading functions such as __autoload() • Dynamic methods via __call()
  • 37. require_once() is once too many lstat64("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=7368, ...}) = 0 lstat64("/tmp/a.php", {st_mode=S_IFREG|0644, st_size=6, ...}) = 0 open("/tmp/a.php", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0 fstat64(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0 lstat64("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=7368, ...}) = 0 lstat64("/tmp/a.php", {st_mode=S_IFREG|0644, st_size=6, ...}) = 0 open("/tmp/a.php", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0 fstat64(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0 <?php require_once "./a.php"; require_once "./a.php";
  • 38. • If you absolutely cannot avoid require_once and include_once use full paths. • In PHP 5.2>= this will allow PHP to avoid opening the file twice.
  • 39. ๏ php_version() ✓ PHP_VERSION constant ๏ php_uname(‘s’) ✓ PHP_OS constant ๏ php_sapi_name() ✓ PHP_SAPI constant Avoid Pointless Function Calls
  • 41. Fastest Win32 Detection in the West • Does not use functions • Does not care about WinXP, WinNT, Windows, Windows98, NT 5.0, etc... • Always available $isWindows =  DIRECTORY_SEPARATOR == '';
  • 42. What time is it? Rather then calling time(), time() and time() again, use $_SERVER[‘REQUEST_TIME’] Provides a timestamp, with a second precision, without any function calls.
  • 44. Use non-capturing patterns • Placing ?: at the start of a sub-pattern makes it non-capturing. • This means PHP/PCRE does not need to allocate memory to store the matched content block. $text = preg_replace( '/=?(?:[^?]+)?/', '=?iso-8859-1?', $origtext ); $text = preg_replace(  '"/(?:n|t|rn|s)+/"', ' ', $origtext );
  • 45. End Result 0 8.75 17.50 26.25 35.00 30.92 26.38 Seconds A 15% performance improvement, with a 2 character change. Capuring Non-Capturing
  • 46. If Possible Avoid Regex <?php // Slow if (preg_match("!^foo_!i", "FoO_")) { } // Much faster if (!strncasecmp("foo_", "FoO_", 4)) { } // Slow if (preg_match("![a8f9]!", "sometext")) { } // Faster if (strpbrk("a8f9", "sometext")) { } // Slow if (preg_match("!string!i", "text")) {} // Faster if (stripos("text", "string") !== false) {} 
  • 47. More Regex Avoidance $text = preg_replace( "/n/", "n", $text); In this case it would be simpler and to mention faster to use a regular str_replace() $text = str_replace( "/n/", "n", $text);
  • 48. Speed Comparison 0 11.25 22.50 33.75 45.00 1 to 1 1 to 2 1 to 3 2 to 2 preg_replace str_replace strtr
  • 49. Use strtr() Properly! Any ideas on how we can make this code 10 times faster? $rep = array( '-' => '*', '.' => '*' ); if ( sizeof( $globArr ) > 1 ) { $glob = "-" . strtr( $globArr[1], $rep ); } else { $glob = strtr( $globArr[0], $rep ); }
  • 50. Use Strings! Elimination of array operations speeds up the code and simplifies the internal work in strtr() function. if ( sizeof( $globArr ) > 1 ) { $glob = "-" . strtr( $globArr[1], '-.', '**' ); } else { $glob = strtr( $globArr[0], '-.', '**' ); } 0 15 30 45 60 4.29 55.70 Seconds strtr(string) strtr(array)
  • 51. Don’t Replace When you • Any replacement operation requires memory, if only to store the “modified” result. • A quick strpos() to determine if any replacement is actually needed can save memory and improve performance!
  • 53. @ operator is evil! • The error blocking operator, is the most expensive character in PHP’s alphabet. • This seemingly innocuous operator actually performs fairly intensive operations in the background. @action(); $old = ini_set(“error_reporting”, 0); action(); ini_set(“error_reporting”, $old);
  • 56. Comparing From An Offset • As of PHP 5, you don’t need to substr() string segments from non-start position to compare them thanks to substr_compare(). if (substr($class, -15) != 'text') /* == */ if (substr_compare($class, 'text', -15))
  • 57. Don’t Mis-use Constants One of my biggest pet-peeves in PHP is this kind of nonsense: $foo = array("bar"=>0); $foo[bar] = 1;
  • 58. Why is this bad? ๏ 1 strtolower ๏ 2 hash lookups ๏ E_NOTICE error message generated ๏ temporary string being created on the fly.
  • 60. Fix “harmless” error messages ‣ Each error results in: ๏ Generation of a complex error string ๏ Output to stdout/stderr ๏ Potential write to a file or syslog ๏ In pre-5.2 releases may leak memory in some rare instances.
  • 61. Simplify for() loop Avoid function calls within for() loop control blocks. <?php for ( $i = 1; $i < sizeof($array); $i++ ) {} for ( $i = 0; $i < count($array); $i++ ) {} for ( $i = 0; $i < strlen($string); $i++ ) {} Otherwise function is called for every loop iteration.
  • 63. Don’t Re-invent the Wheel • It is surprising how frequently people try to re-invent the wheel. • Now a days PHP has ✓ 2,700 functions ✓ 80 core extensions ✓ 154 PECL extensions • Chances are what you need already exists!
  • 64. Use Full File Paths • While it is convenient(??) to do require “foo.php” and have it work, internally it leads to significant overhead. • Whenever possible you should use full paths, that require no resolution in PHP.
  • 65. The internals of file ops. stat64("./b.php", {st_mode=S_IFREG|0644, st_size=6, ...}) = 0 getcwd("/tmp", 4096) = 5 lstat64("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=18008, ...}) = 0 lstat64("/tmp/b.php", {st_mode=S_IFREG|0644, st_size=6, ...}) = 0 open("/tmp/b.php", O_RDONLY) The issue can be further exasperated by the use of include_path.
  • 66. 66 References can be used to simply & accelerate access to multi-dimensional arrays. Reference Tricks $a['b']['c'] = array(); // slow 2 extra hash lookups per access for($i = 0; $i < 5; $i++) $a['b']['c'][$i] = $i; // much faster reference based approach $ref =& $a['b']['c']; for($i = 0; $i < 5; $i++) $ref[$i] = $i;
  • 67. Optimization Myths ✦ Removing comments makes code faster ✦ Using ‘ is faster than “ ✦ Passing things by-reference makes code faster ✦ Objects make code faster ✦ Ternary ? : is faster then if () { } else {}
  • 68. 68 Caching is the recognition and exploitation of the fact that most "dynamic" data does not change every time you request it.
  • 69. Caching Approaches • Complete page content caching • Content pre-generation • On-Demand caching • Partial page caching • SQL query caching • Browser caching
  • 70. “Blog” Scenario <?php require “/blog.inc”; load_header(); $qry = mysql_query(“SELECT * FROM blog_entries ORDER BY date DESC LIMIT 15”); while ($entry = mysql_fetch_assoc($qry)) { show_blog_entry($entry); } load_footer();
  • 71. Cache Handler function cache() { list(,$dt) = mysql_fetch_row(mysql_query(“SELECT MAX(date) FROM blog_entries”)); if (filemtime(“/blog/cache/index.html”) > $dt) { // cache hit readfile(“/blog/cache/index.html”); exit; } init_cache(); }
  • 72. function init_cache() { ob_start(); register_shutdown_function(‘write_cache’); } function write_cache() { echo $data = ob_get_clean(); $fname = “/blog/cache/index.html”; $tmp_fname = tempnam(“/blog/cache”, “blog”); file_put_contents($tmp_fname, $data); rename($tmp_fname, $fname); }
  • 73. Cache Placement <?php require “/blog.inc”; require “/cache.inc”; cache(); load_header(); $qry = mysql_query(“SELECT * FROM blog_entries ORDER BY date DESC LIMIT 15”); while ($entry = mysql_fetch_assoc($qry)) { show_blog_entry($entry); } load_footer();
  • 74. Quick benchmark Before After Page Size 31,117 bytes 31,117 bytes Latency 8.73 msec. 4.62 msec. Req./Second 451 665
  • 75. Serendipity Test Before After Page Size 25,853 bytes 25,853 bytes Latency 199.3 msec. 42.37 msec. Req./Second 24.7 112.2
  • 76. Compressed Page Cache if (!empty($_SERVER["HTTP_ACCEPT_ENCODING"]) && strpos($_SERVER["HTTP_ACCEPT_ENCODING"], 'gzip') !== false) { header('Content-Encoding: gzip'); readfile("/tmp/index.html.gz"); } else { readfile(“ /blog/cache/index.html”); }
  • 77. function write_cache() { echo $data = ob_get_clean(); $fname = “/blog/cache/index.html”; $tmp_fname = tempnam(“/blog/cache”, “blog”); file_put_contents($tmp_fname, $data); rename($tmp_fname, $fname); $tmp_name = tempnam(“/blog/cache”, “blog”); copy("/tmp/index.html", "compress.zlib://" . $tmp_name); rename($tmp_name, "/tmp/index.html.gz"); }
  • 78. Content Pre-generation • Simplifies caching code • No real-time work • Entire cache can be easily rebuilt • Can be used to bypass PHP entirely • Predictable operation
  • 79. Let’s Avoid PHP • Concept • Make product pages be .html pages • Generate .html pages via PHP • Static pages are served by the web server, skipping the PHP overhead.
  • 80. function content_generate($s, $e) { while ($s <= $e) { $url = "http://store.com/product.php?id=".$s; $file = "/cache/product_".$s; $data = file_get_contents($url); file_put_contents($file, $data); copy($file, "compress.zlib://" . $file . ".gz"); $s++; } }
  • 81. Livedocs Test Before After Page Size 30,896 bytes 30,896 bytes Latency 611.2 msec. 2.37 msec. Req./Second 5.29 1284.6
  • 82. Pre-Generation Problems • Disk utilization • 2 files per-page X number of pages • Generates pages no one may visit • Generating all pages at once may take too long.
  • 83. On Demand Caching • Advantages • Generate what you need, when you need it. • Simple to setup • Has all the speed advantages of pre- generation.
  • 84. 404 Handler • Concept • Make all links lead to .html pages • When page does not exist, have PHP 404 handler be triggered. • The handler script generates the missing page • All future visitors access static content.
  • 85. ErrorDocument 404 /generate_html.php // sample URL http://site.com/products/123.html $id = (int) basename($_SERVER[‘REDIRECT_URL’]); if (!$id || $id < 0) { exit; } $url = "http://store.com/product.php?id=".$id; $file = "./products/".$id.”.html”; $data = file_get_contents($url); file_put_contents($file, $data, LOCK_EX); copy($file, "compress.zlib://" . $file . ".gz");
  • 86. Caching Quandary My pages always have an ever changing content and cannot be cached in their entirety.
  • 88. APC to the Rescue! Alternative PHP Cache (APC) is an open source opcode cache. It happens to provide handy PHP variable storage mechanism we can use.
  • 89. APC API • apc_store([key], [variable], [time to live]) • key - cache entry identifier • variable - PHP variable to store • time to live - for long to store the data • [variable] = apc_fetch([key]) • apc_delete([key])
  • 90. if (!($promo = apc_fetch(‘promo’))) { $promo = fetch_all_promos(); apc_store(‘promo’, $promo, 3600); // 1 hour } if (!($deals = apc_fetch(‘deal’))) { $deals = fetch_all_deals(); apc_store(‘promo’, $promo, 600); // 10 mins } if (!($final_tmpl = apc_fetch(‘main_template’))) { $final_tmpl = generate_front_page(); apc_store(‘main_template’, $final_tmpl, 86400); } // 1 day
  • 91. // fetch one promo & deal to display $data[0] = $promo[array_rand($promo)]; $data[1] = $deals[array_rand($deals)]; // get the always dynamic sections $data[2] = get_shopping_cart(); $data[3] = generate_greeting_msg(); // in the finalized page substitute semi-static content echo str_replace( array( ‘%%deals%%’, ‘%%promo%%’, ‘%%cart%%’, ‘%%greeting%%’ ), $data, $final_tmpl);
  • 92. SQL Caching • In most applications the primary bottleneck can often be traced to “database work”. • Caching of SQL can drastically reduce the load caused by unavoidable, complex queries.
  • 93. Cache Tables CREATE TABLE search_cache ( skey CHAR(32) PRIMARY KEY, rec_id INT NOT NULL, age INT UNSIGNED, INDEX(skey), INDEX(age) );
  • 94. $key = md5(“user supplied search query”); $tm = time(); $max_age = $tm - 3600 * 4; // 4h $qry = “SELECT count(*) FROM search_cache WHERE key=’{$key}’ AND age>”.$max_age; if (!$pdo->query($qry)->fetchColumn()) { // cache generation code is here } // Standard join against search_cache table to get // the relevant records Basic Search Cache
  • 95. // clear old cache entries $pdo->exec(“DELETE FROM search_cache WHERE key=’{$key}’ AND age<=”.$max_age); $qry = “INSERT INTO search_cache”; $qry .= “ (key,age,rec_id) ”; $qry .= “ SELECT ‘{$key}’, {$tm}, rec_id”; $qry .= “ FROM [search qry] LIMIT 1000”; $pdo->exec($qry); Cache Generation Code
  • 96. Browser Cache • Advantages • Reduces data sent to virtually zero • Requires next to no server resources • Disadvantages • Flimsy control over cache age • Not guaranteed to work
  • 97. How to implement? // Time to Cache header(“Expires: ”.date(DATE_RFC822)); // Based on modification date header(“Last-Modified: ”.date(DATE_RFC822)); // Content hash header(“Etag: “.md5_file(“./page_cache”));
  • 98. 98 Most applications will end up using databases for information storage. Improper use of this resource can lead to significant and continually increasing performance loss.
  • 99. 99 Most databases offers tools for analyzing query execution. EXPLAIN select * from users where login LIKE '%ilia%'; +----------+------+---------------+------+---------+------+-------+------------+ | table | type | possible_keys | key | key_len | ref | rows | Extra | +----------+------+---------------+------+---------+------+-------+------------+ | mm_users | ALL | NULL | NULL | NULL | NULL | 27506 | where used | +----------+------+---------------+------+---------+------+-------+------------+ EXPLAIN select * from users where login LIKE 'ilia%'; +----------+-------+---------------+-------+---------+------+------+------------+ | table | type | possible_keys | key | key_len | ref | rows | Extra | +----------+-------+---------------+-------+---------+------+------+------------+ | mm_users | range | login | login | 50 | NULL | 2 | where used | +----------+-------+---------------+-------+---------+------+------+------------+ Check Your Queries
  • 100. 100 Rather then creating a column for every Boolean option, you can pack 32 of them into a single integer field. CREATE TABLE users ( is_active INT, is_banned INT, is_admin INT, ... ); CREATE TABLE users ( user_opt INT, ... ); user_opt & 1 // active user_opt & 2 // banned user_opt & 4 // admin Bitwise Option Packing
  • 101. 101 • The simpler the code, the faster it runs, it really is that simple. • Syntactic sugar. • Unnecessary wrappers. • Wrapping one liners in functions. • OO for the sake of OO. KISS = Performance
  • 102. Thank You For Listening! • These slides • http://www.ilia.ws/ • APC • http://pecl.php.net/apc • XDebug • http://www.xdebug.org/
  • 103. Optimizer (Why?) • The opcodes generated by Zend Engine are often inefficient. • Some operations can be avoided • A lot of temporary vars are not necessary. • Every compiler needs an optimizer ;-) i
  • 104. Optimizer (How?) PHP Script Zend Compile Zend Execute @ OptimizerKinda Slow
  • 105. What Can It Do? • opt. heredoc • print to echo • GLOBALS[foo] to foo • inline known constants • eliminate NOP • resolve partial file paths. • optionally inline define() calls • 60+ function calls with static values resolved. • Much more...