Intro:
The main topic I will try to convey is that PHP is a language parser, much like how we rely on simple yet concise language, interpreted lanugages like PHP will rely on the most simple of syntax to speed things up.
One of the first things I will discuss are about quotes, these silly " or ' things you may had been using for quite some time. It was once a rumor that double quotes were slower or single quotes were faster, but they are basically the same thing in recent versions.
The only thing you will wish to optimize here is to try to avoid "cramming" variables into a string, such as "$a plays $b and $c = $d" as this will be hard for the interpreter to recover from, especially cramming arrays into a string. Single quotes are generally more simple to read by the parser and should be used unless you require escapes such as \r \n \t \" to be used in your text.
A simple hint: You will want to stay away from heredoc syntax for this reason, breaking out of PHP will be much faster to write HTML blocks or non-dynamic data, an example is this:
<?php
$title = "Home Page";
?>
<html>
<head>
<title><?php echo $title; ?></title>
</head>
<body>
...As most of this is not with PHP blocks, the interpreter will skip it completely making the page loading process much more streamlined.Natural language functions:
You may often use certain functions within PHP that will be slightly heavy, when there are more natural options you can choose. These every day functions may be:
if(!empty($a)) { ...
if(preg_match("/[a-zA-Z]/", $username)) { ...
if(in_array($array, $object)) { ...There are a variety of resources PHP provides in its natural syntax to just as effectively perform the same tasks without the larger load work.!empty($a) can be replaced with $a != "", or in_array($array, $obj).. with isset($array[$obj]) -- What a simple change? Here is where we talk about the problems some optimizations can bring. Optimization should be embraced, but in such a manner it does not conflict with code and does not cause unforseen problems in the future of your project.
This is a very common problem with some coders where they optimize a function or algorithm all too well, and then break the application once a new feature is added. I will bring up a often overused but true saying: "Premature optimization is the root of all evil" - C.A.R. Hoare.
This is not true for certain things we take for granted (or do not) in a language, one often overused set of functions are regular expressions. In our previous (and simple) code example up there we had ran the regular expression [a-zA-Z] to check if a user's name was valid, this will often be unneeded and can be performed by much faster functions that are native to C itself (what PHP is based on), what is it? You guessed it:Ctype!
The ctype functions were often used to check if a character were decimal (alphanumeric), a letter (alphabetic), a hex digit or normal digit. These functions are available within PHP to use and can replace many regular expressions:
if (!ctype_alpha($username)) {
echo "username invalid."
}This can be combined with the strlen() function to check for length, and beat a regular expression anyday. In fact, it may often take 1/2000th the time to execute than running a regular expression engine. A lot for a little bit extra, eh?The next thing I will talk about are some basic syntaxes. A few little tips on gaining extra speed (and also sanity). One common thing people do to cut code is omit braces in if/while/for statements, this causes confusion for the user and this includes the interpreter. It requires the interpreter to check bounds of the current and next line, that extra work added up (especially in a loop body) may wrack up a few milliseconds each time it runs -- this is not much but can show you where it can go wrong. Let us move to our next example,
- Loops:
Loops are always fun, and they are often the basis of all algorithms. Here we will be creating a little encryption program in PHP. It does not actually encrypt much yet but it will teach the importance of optimization.
Let us start with the data we will be encrypting, it is your simple password: secret123
You will notice it is a string, and may notice to loop through it you must iterate it as a character array to access each letter.
We will naturally define a function to parse through the array and extract each character to apply our little cypher:
function myencrypt($string) {
$out = '';
for($i = 0; $i <= strlen($string) - 1; $i++ ) {
$out .= ord($string[$i]);
}
return $out;
}There is one fundamental problem in this code: The loop body: "strlen($string) - 1" is run X times until the loop is satisfied. This is a common issue people face in their code and do not know it, expensive calls if at all should remain out of loop. We can recify this issue by removing the offending code prior to the running loop like so.function myencrypt($string) {
$out = '';
$len = strlen($string) - 1;
for($i = 0; $i <= $len; $i++ ) {
$out .= ord($string[$i]);
}
return $out;
}Syntax and structures in these languages are powerful in its simplicity, so you must notice and be curious about how many of these syntactical elements work in order to gain the ability to optimize these things. Optimization can be a little more interactive and impactful than these minor changes, let us move on to the meat of the optimizations.- Benchmarking:
Here we may look to the basics of profiling your code in hopes to find out what you need to optimize/fix in the first place. The most simple function PHP hands to you to use is the function microtime() - This function returns the current time in microseconds, or 1/1000 of a millisecond in granularity.
We may benchmark our program as thus:
$start = microtime(true); //true returns as float aLongFunction(); $elasped = microtime(true) - $start; print "Ran in $elasped seconds";You may had figured after running this that aLongFunction() returns a fairly big work load and takes 3.5 seconds to run. This will by any means be a priority if your page loading time is suffering, it can be run in many different scenarios to test executions -- two types of database calls or two new algorithms to show you in real time what works and what does not cut it.
There is a PEAR module called PEAR::Benchmark() which can be used with multiple time markers and display a tabled report at the end, it may be found here: PEAR::Benchmark
For databases, you can use MySQL's reporting features to gain insight on the last query, what it had touched and the time it ran within its engine -- not only the time it took to get back to PHP. This can be done with MySQL's profiling function. The syntax is quite simple, you can perform a profiling of multiple queries like so:
mysql_query("SET profiling = 1");
mysql_query("DROP TABLE IF EXISTS tbl_junk");
mysql_query("SELECT (a,b,c,d,e) FROM tbl_good WHERE `uid` = 0");
$profile = mysql_query("SHOW PROFILES");
while($row = mysql_fetch_assoc($profile)) {
print 'Query: ' . $row['Query'] . ' Duration ' . $row['Duration'];
}It may dump some data like the following.Query: DROP TABLE IF EXISTS tbl_junk Duration: 0.87 Query: SELECT(a,b,c,d,e) FROM tbl ...Duration: 0.42These are silly example but they show the fundamental performance in each underlaying query, so it would be wise during the testing cycle to turn profiling on and see which queries are performing in the mental time limits you assign.
More information about database profiling functions may be found at the MySQL manual. A further helpful function to turn on would be slow query logs, they can log slow queries and you can check them as need be.
We had done all we could to juice out the performance in optimizing, so let us move to caching -- rather a method to store dynamic results so they do not need to be formed again and again statically.
- Caching:
An often very simple and fast way to increase performance in a dynamic site is to add a caching mechanism to it. The most simple example implementations for these are for a staff page, credits page or maybe a list of your recent software products that you wish to sell and they are all updated each week in your database.
You will generate the page a-new each time, but that is the point! We wish for the user to have fresh information each visit -- but this can often be a hassel for if you are running one-second-long queries with hundreds of views a day.
We can implement caching. I know, you may say "I do not want to install a huge library to my server!" We will not, in this case we may use a simple and secure caching library from PEAR named PEAR::Cache_Lite, the intentional misspelling of "light" brings a fresh ring to my ears.
Instead of example database queries for our sample application, lets pretend the page query is defined within the function somequery() and it returns the row of information, here we will print the products list:
require_once("Cache/Lite.php");
$page = 'products_page';
$cache = new Cache_Lite();
if($listings = $cache->get($page)) {
echo $listings;
} else {
$res = somequery();
while($row = mysql_fetch_assoc($res)) {
$listings .= "Product ID {$row['uid']} - Description: {$row['desc']} - Price: {$row['price_usd']}<br/>";
}
print $listings;
$cache->setLifeTime = 1 * 60 * 60 ; // Cache for (one) hour
$cache->save($listings);
}That will take care of all the rest, as you will notice this was a painless use of caching with an ID, of which we only had to put the PEAR Cache folder in our working directory or an accessable location we can use in all our scripts.You may wish to capture the entire page and store it in cache, you can do this painlessly with ob_start() and ob_get_contents() to store the contents into the output buffer, thus saving what the contents of the page. PHP has great examples on how to accomplish this and it is often done.
This is the prelude of the article. If there are any questions of things or myths of optimizations or anything no matter how simple you had heard (maybe a question about op codes? a library's performance?), feel free to ask me and I will respond in a day's notice of what I know! I had written the content for example and may not had tested it thoroughly, feel free to try it out and I will correct it as so.
Thank you.
Edited by Alexander, 23 November 2010 - 10:03 AM.


Sign In
Create Account

Back to top










