// Echo the output string echo implode‘’, $output; } ?> This script demonstrates four versions of a method v1, v2, v3, and v4, each of which performs the same task, but with progressive
Trang 1// Echo the output string echo implode(‘’, $output);
}
?>
This script demonstrates four versions of a method (v1, v2, v3, and v4), each of which performs the same task, but with progressive efficiency
The script calls a method called doBenchmark(), which runs each version of the function under benchmark conditions using the Benchmark/Iterate.php class for MAX_RUN times The result of each benchmark is printed using a printf() state-ment Following is a sample of output from the script:
v1 ran 100 times where average exec time 1.60087 ms v2 ran 100 times where average exec time 1.05392 ms v3 ran 100 times where average exec time 0.55139 ms v4 ran 100 times where average exec time 0.27371 ms
Here, you can see that v1()ran the slowest Lets look at what v1()does This function receives an array as an argument and loops through each element of the array using a forloop Notice that the loop uses the sizeof()function to deter-mine the size of the array The sizeof()function is called each time the loop iter-ates This degrades the speed of the loop substantially, as function calls are expensive in terms of execution time Inside the loop, only an echo() function prints an HTML comment statement
Now let’s look at the v2()function This function does the same task of v1(), but it is a bit faster (0.54695 ms), as it stores the size of the $myArrayin the $max
variable outside the loop and therefore avoids the penalty of calling sizeof()for each iteration
Looking at the v3()version of the same function, you can see that this version
is significantly faster than v2()because it not only does what v2() does, it also removes from the loop the iterative call to the expensive I/O function echo() by storing the output in a variable called $output This improves its performance greatly, as it uses only a single echo()call to print the contents stored in $output
as the last statement of the function
Finally, v4()does everything v3()does except that instead of storing output in
a $outputstring variable that is appended using the dot operator (as done in v4), it uses a faster array_push()function to store output as a series of sequential array elements in $outputarray Finally, it appends the contents of the $output array using the implode() function, which is passed to a single echo() function This appears to be the fastest of the four implementations
Trang 2How do you learn to make such improvements to your own code? The simple answer is experimentation and lots of practice Study PHP’s built-in functions in great detail, as they are faster than anything you will write in PHP Use of built-in functions in comparable situations can improve your code speed significantly For example, consider this listing:
function v5($myArray = null){
echo “<! ”, implode(“ > <! ”, $myArray), “ > “;
}
Stress-testing your PHP applications using ApacheBench
The Apache server comes with a tool called ApacheBench (ab), which is installed by default in the bin directory of your Apache installation directory By using this nifty tool, you can stress-test your application to see how it behaves under heavy load conditions
Make an estimate of how many requests you want your application to be able to service from your Web server Write it down in a goal statement such as “I wish to
service N requests per second.”
Restart your Web server and from a system other than the Web server, run the ab command as follows:
./ab -n number_of_total_requests \ -c number_of_simultaneous_requests \ http://your_web_server/your_php_app.php
For example:
./ab -n 1000 -c 50 http://www.domain.com/myapp.php
The ApacheBench tool will make 50 concurrent requests, and a total of 1,000 requests Sample output is shown here:
Server Software: Apache/2.0.16 Server Hostname: localhost Server Port: 80
Document Path: /myapp.php Document Length: 1311 bytes Concurrency Level: 50
Time taken for tests: 8.794 seconds Complete requests: 1000
Failed requests: 0
Trang 3Total transferred: 1754000 bytes HTML transferred: 1311000 bytes Requests per second: 113.71
Transfer rate: 199.45 kb/s received Connection Times (ms)
min avg max Connect: 0 0 5 Processing: 111 427 550 Total: 111 427 555
Notice that Requests per second is 113.71 for accessing the myapp.php PHP script Change the concurrent request count to a higher number and see how the server handles additional concurrent load
Tune your application as finely as possible using the techniques discussed ear-lier You might have to also tune Apache using MaxClients, ThreadsPerChild,
MaxThreadsPerChild, and so on, based on your MPM module choice in httpd.conf
Visit www.apache.org for in-depth documentation on Apache, including modules and third-party applications to improve performance.
If you make changes to the Apache configuration file (httpd.conf), make sure you restart Apache, and apply the same benchmark tests by using ab as before
You should see your Requests per second increase or decrease based on the num-bers you try As you tweak the numnum-bers by changing the directive values, make sure you record the values and the performance so that you can determine the best setting for you
Buffering Your PHP Application Output
Once you are sure that you have optimized your application to the best of your
abilities, it is time to consider other techniques, such as output buffering.
Output buffering is very effective for scripts that use numerous I/O functions such
as echo(), print, printf(), and so on If you use these functions often, you might find output buffering to be a speed booster For example, Listing 21-4 shows a script called buffer.php that benchmarks (using the PEAR Benchmark/Timer discussed ear-lier in the section, “ Benchmarking your code”) a function called doSomething(), which prints the ‘x’ character in a loop, using the echo()function
Trang 4Listing 21-4: buffer.php
<?php define(MAX, 1024 * 10);
// If you have installed PEAR packages in a different // directory than %DocumentRoot%/pear change the // setting below.
$PEAR_DIR = $_SERVER[‘DOCUMENT_ROOT’] ‘/pear’ ;
$PATH = $PEAR_DIR;
ini_set( ‘include_path’, ‘:’ $PATH ‘:’
ini_get(‘include_path’));
require_once ‘Benchmark/Timer.php’;
$timer = new Benchmark_Timer();
$kb = MAX / 1024;
// No output buffering
$timer->start();
doSomething();
$timer->stop();
printf(“Buffer: OFF Size: %d KB Time elapsed: %.3f<br>”,
$kb,
$timer->timeElapsed());
// Enable output buffering ob_start();
$timer->start();
doSomething();
$timer->stop();
printf(“Buffer: ON Size: %d KB Time elapsed: %.3f<br>” ,
$kb,
$timer->timeElapsed());
exit;
function doSomething() {
$output = ‘’;
Trang 5for($i=0;$i<=MAX;$i++) {
echo ‘x’;
} }
?>
The first call to doSomething()in the script is made without output buffering, whereas the second call is made after output buffering is enabled using the
ob_start() function Sample benchmark results of the two calls to
doSomething()are shown here:
xxxxxxxxxxxxxx [ shortened for brevity] xxxxxxxxxxxxxxxxxxxxx Buffer: OFF Size: 10 KB Time elapsed: 10.939
xxxxxxxxxxxxxx [ shortened for brevity] xxxxxxxxxxxxxxxxxxxxx Buffer: ON Size: 10 KB Time elapsed: 0.071
As you can see, the unbuffered call to doSomething(), which uses echo()in a loop, required a significant amount of time vs the buffered call This means that
ob_start()is an excellent choice to improve performance of this script
Therefore, whenever it is possible for you to enable output buffering, try it and measure the performance gain If the gain is significant, you can use ob_start()
in your code
Compressing Your PHP Application Output
You can also compress your PHP-generated HTML output or image output using GZIP compression You must enable GZIP compression while compiling PHP This is done using the option with-zlib-dir=/usr/local/libin the source code con-figuration step
Not all Web browsers can handle compressed output Therefore, this method might not be applicable for all situations.You can take advantage of compression when you know that the Web browsers used by your visitors support compression Because Microsoft Internet Explorer is a popular Web browser that supports compression, it is often worth trying.