todo:
Tools Boxaroo used
- dBug
- stack trace - customized
- poor man's profiling
- wanted to use xDebug but was never critical
Compilation
-
configure with –-enable-inline-optimization
- Compile with
-O3, -march, -msse3, -mfpmath=sse, -funroll-loops
- Compile only essential modules, rarely used ones as shared objs for scripts that need them
- Compile statically into Apache (up to 20% gain)
- PHP:
./configure --with-apache=/path/to/apache_source
- Apache:
./configure --activate-module=src/modules/php4/libphp4.a
-
strip symbols out (saves 20-30%)
Config
- Disable...
-
magic_quotes_* directives. (but be extra careful with escaping)
- Turn off
expose_php
- Turn off
register_argc_argv for non-cli SAPIs
- Unless absolutely necessary do not enable
always_populate_raw_post_data
- Put
php.ini where PHP will look first
-
hdparm
- compress
ob_start("ob_gzhandler");
Apache
-
StartServers to avg simult. requests expected
-
MaxSpareServers set high to handle spikes
-
MaxClients ~2/5 max processes server can handle
-
MaxRequestsPerChild ideally unlimited (0) but realistically a large number
- Avoid
mod_rewrite if possible
- Tune logging setup
- Use IPs, not names for Deny/Allow rules
- Carefully set
KeepAlive and KeepAliveTimeout to avoid crippling the server yet not to waste reconnection overhead - though probably disable for PHP / dynamic pages
- look into using
lingerd to manage TCP stuff after page has been sent
- Use one group of servers just for static / css stuff; use another for dynamic - different tuning parameters
- Tux / thttpd
Coding tricks
- Compression - 10% CPU load, lower B/W
- CSS - 20-30% smaller pages than old HTML (esp tables)
-
tidy extension, though CPU expensive, worth it maybe if cached
- Always use full path for
include, esp with opcode cache
- Sometimes worth it to force type conversion
- watch for funcs (e.g.
sizeof) being part of a loop construct! Eval'd each iteration!
- initialize variables! Incrementing undefined local 9-10x slower than pre-initialized one.
- methods in derived classes run faster than ones in the base class
- Replace regexps with normal string processing if possible. PCRE (perl compat) faster than ereg.
- Regexp's can be faster than DOM for XML parsing
Sessions
- Use RAM disk
- Implement your own session reader/writer like we did. Maybe to RAM disk. Or (?) mmcache
- enable shared memory (
configure --with-mm), session.save_handler=mm in php.ini
Caching
- Tuck MMCache - like Zend - Using
mmcache_cache_output(file, ???func???, ttl);
- Pear Cache
- Cache-lite (newer, more recommended)
Tuning / Benchmarking
-
ab - Apachebench
-
flood
-
vmstat 1
-
microtime()
- when load avg > # of procs, system is overloaded! In vmstat/top it's 1 / 5 / 15 mins
- In top, R = runnable, S = sleeping, W = swapped out
SQL
- Adodb might be faster than the built-in database abstraction system
- Use
explain before queries to identify slow ones - queries not using keys
- Query chaining (separation by
is faster
- Watch lock usage
- Row level better than table level (try!)
- Joins just might be slower since there's a read lock on all tables involved
- Use non-persistent database connections to avoid running out of Mysql max # connections
- (try!) doing a temp table
mysql_query("CREATE TEMPORARY TABLE mtmp AS
SELECT id FROM msg WHERE
thread_id={$_GET['th']} AND apr=1
ORDER BY id ASC LIMIT {$count}, {$_GET['start']}");
// Retrieve needed data by using the temporary table as base
$result = mysql_query("SELECT * FROM mtmp mt
INNER JOIN msg m ON m.id=mt.id
INNER JOIN thread t ON m.thread_id=t.id
INNER JOIN forum f ON t.forum_id=f.id
LEFT JOIN users u ON m.poster_id=u.id
LEFT JOIN level l ON u.level_id=l.id
LEFT JOIN poll p ON m.poll_id=p.id
LEFT JOIN poll_opt_track pot ON pot.poll_id=p.id
AND pot.user_id="._uid."
ORDER BY m.id ASC");
--
MattWalsh - 23 Oct 2008