Category Archives: Performance / Optimization

PHP Benchmark: count() vs. empty()

In my experience, PHP is not a very “fast” language. Opcode and memory caching are important to many large projects, but they will not make up for poor decisions made when writing code. In recent years, we’ve seen the PHP team integrate opcode cache into PHP 5.5, and Facebook investing in HipHop. These are welcome improvements, but we need to be smart about what functions and language constructs we use.

Given an empty array, empty() will return false, and count() will return zero. Given an array with one or more values, empty() will return true, and count() will return the number of values. Either method will produce an effective result in a conditional checking for a boolean value (==), but how do they perform? First, let’s look at the code used for the benchmark.

The Code

The code is simple. In both files, we executed each function/construct one million times and measured the results with Linux’s time command. In addition to testing with an empty array, I also benchmarked count() and empty() on an array with 1,000 values. There was no measurable variance between the performance of an empty array and an array with 1,000 values.

empty.php

$array = array();
//$array = range(0, 1000);
for ($i = 0; $i < 1000000; $i++) {
    empty($array);
}

count.php

$array = array();
//$array = range(0, 1000);
for ($i = 0; $i < 1000000; $i++) {
    count($array);
}

The Results

I ran the benchmark about 10 times, and each result confirmed that empty() was roughly 20-30 times faster than count().

empty()

% time ./empty.php

real    0m0.122s
user    0m0.094s
sys     0m0.009s

count()

% time ./count.php

real    0m2.630s
user    0m0.118s
sys     0m2.494s

Benchmark: Amazon EC2 vs. GoDaddy VPS

I recented started looking into Amazon EC2 as a potential replacement for my GoDaddy VPS servers, specifically for serving basic PHP-driven web sites. I used the standard ./Run command for UnixBench to obtain the results.  The GoDaddy VPS seems to deliver benchmark results closer to the dedicated server numbers I’ve seen, so I’m a little skeptical.  Also, remember that these tests do not consider network or database performance.  The results merely show raw performance metrics for general system functions, the filesystem, and processing.  The pricing for the AWS m1.small on-demand instance is close to that of the m1.medium high utilization reserved instance, and GoDaddy’s Value VPS.

Amazon EC2 (m1.small)

1 CPU; 1 parallel process

Test Score Unit Time Iters. Baseline Index
Dhrystone 2 using register variables 10319739.8 lps 10.0 s 7 116700.0 884.3
Double-Precision Whetstone 598.2 MWIPS 10.0 s 7 55.0 108.8
Execl Throughput 503.4 lps 29.9 s 2 43.0 117.1
File Copy 1024 bufsize 2000 maxblocks 99004.0 KBps 30.0 s 2 3960.0 250.0
File Copy 256 bufsize 500 maxblocks 26650.5 KBps 30.0 s 2 1655.0 161.0
File Copy 4096 bufsize 8000 maxblocks 320858.3 KBps 30.0 s 2 5800.0 553.2
Pipe Throughput 136761.9 lps 10.0 s 7 12440.0 109.9
Pipe-based Context Switching 27738.9 lps 10.0 s 7 4000.0 69.3
Process Creation 995.9 lps 30.0 s 2 126.0 79.0
Shell Scripts (1 concurrent) 798.2 lpm 60.0 s 2 42.4 188.2
Shell Scripts (8 concurrent) 107.8 lpm 60.1 s 2 6.0 179.6
System Call Overhead 114607.8 lps 10.0 s 7 15000.0 76.4
System Benchmarks Index Score: 164.4

Amazon EC2 (m1.medium)

1 CPU; 1 parallel process

Test Score Unit Time Iters. Baseline Index
Dhrystone 2 using register variables 20679983.9 lps 10.0 s 7 116700.0 1772.1
Double-Precision Whetstone 1203.0 MWIPS 10.0 s 7 55.0 218.7
Execl Throughput 1007.9 lps 29.8 s 2 43.0 234.4
File Copy 1024 bufsize 2000 maxblocks 200955.9 KBps 30.0 s 2 3960.0 507.5
File Copy 256 bufsize 500 maxblocks 52142.0 KBps 30.0 s 2 1655.0 315.1
File Copy 4096 bufsize 8000 maxblocks 645663.0 KBps 30.0 s 2 5800.0 1113.2
Pipe Throughput 271624.2 lps 10.0 s 7 12440.0 218.3
Pipe-based Context Switching 49830.7 lps 10.0 s 7 4000.0 124.6
Process Creation 2039.6 lps 30.0 s 2 126.0 161.9
Shell Scripts (1 concurrent) 1635.5 lpm 60.0 s 2 42.4 385.7
Shell Scripts (8 concurrent) 221.6 lpm 60.2 s 2 6.0 369.4
System Call Overhead 221863.8 lps 10.0 s 7 15000.0 147.9
System Benchmarks Index Score: 327.1

GoDaddy VPS (Value)

8 CPUs; 1 parallel process

Test Score Unit Time Iters. Baseline Index
Dhrystone 2 using register variables 9835137.0 lps 10.0 s 7 116700.0 842.8
Double-Precision Whetstone 1950.9 MWIPS 10.0 s 7 55.0 354.7
Execl Throughput 2848.4 lps 29.5 s 2 43.0 662.4
File Copy 1024 bufsize 2000 maxblocks 349825.6 KBps 30.0 s 2 3960.0 883.4
File Copy 256 bufsize 500 maxblocks 110633.5 KBps 30.0 s 2 1655.0 668.5
File Copy 4096 bufsize 8000 maxblocks 826791.7 KBps 30.0 s 2 5800.0 1425.5
Pipe Throughput 729108.2 lps 10.0 s 7 12440.0 586.1
Pipe-based Context Switching 139871.3 lps 10.0 s 7 4000.0 349.7
Process Creation 6944.0 lps 30.0 s 2 126.0 551.1
Shell Scripts (1 concurrent) 2804.8 lpm 60.0 s 2 42.4 661.5
Shell Scripts (8 concurrent) 1118.6 lpm 60.0 s 2 6.0 1864.4
System Call Overhead 574243.2 lps 10.0 s 7 15000.0 382.8
System Benchmarks Index Score: 674.6

8 CPUs; 8 parallel processes

Test Score Unit Time Iters. Baseline Index
Dhrystone 2 using register variables 64631491.4 lps 10.0 s 7 116700.0 5538.3
Double-Precision Whetstone 15359.3 MWIPS 10.2 s 7 55.0 2792.6
Execl Throughput 13342.2 lps 29.5 s 2 43.0 3102.8
File Copy 1024 bufsize 2000 maxblocks 299406.7 KBps 30.0 s 2 3960.0 756.1
File Copy 256 bufsize 500 maxblocks 91395.5 KBps 30.0 s 2 1655.0 552.2
File Copy 4096 bufsize 8000 maxblocks 720403.8 KBps 30.0 s 2 5800.0 1242.1
Pipe Throughput 4444252.9 lps 10.0 s 7 12440.0 3572.6
Pipe-based Context Switching 1509897.0 lps 10.0 s 7 4000.0 3774.7
Process Creation 32437.4 lps 30.0 s 2 126.0 2574.4
Shell Scripts (1 concurrent) 13964.5 lpm 60.0 s 2 42.4 3293.5
Shell Scripts (8 concurrent) 1931.7 lpm 60.3 s 2 6.0 3219.5
System Call Overhead 2955368.4 lps 10.0 s 7 15000.0 1970.2
System Benchmarks Index Score: 2263.1

Optimize PHP, Apache & MySQL for performance

Two MySQL tuner scripts

MySQLTuner (Perl) and MySQL Performance Tuning Primer (Shell) are two scripts that can help diagnose MySQL database performance issues, and provide recommendations on how to solve them.  While both scripts output similar information, the diagnosis can be slightly different with each script, so I like to use both.  Below are directions on how to use them, as well as a few screenshots.

# Download MySQLTuner and MySQL Performance Tuning Primer to ~/scripts.
# To avoid having to invoke Perl/SH each time, make both files executable.
chmod +x ~/scripts/mysqltuner.pl
chmod +x ~/scripts/tuning-primer.sh

# After that, give them a go!
~/scripts/mysqltuner.pl
~/scripts/tuning-primer.sh

Continue reading Optimize PHP, Apache & MySQL for performance

Using memcached with WordPress

wp-settings.php
wp-settings.php

Today, I decided to implement a popular distributed caching system called memcached.  Memcached allows PHP objects and variables to be stored in memory, which when used properly, can decrease page load time and server load.  Memcached can also work as a central cache for a cluster of servers.  File-based caching systems work by generating static files, and storing them in a local directory to be served in place of the dynamic content.  This can reduce the number of database queries, and help avoid having to process the script with each new request; however, there is a downside. Continue reading Using memcached with WordPress