hosted by liquidweb


Go Back   Web Hosting Talk : Web Hosting Main Forums : Programming Discussion : Programming Tutorials : [HOW TO] Speeding up PHP
Reply

Programming Tutorials How-Tos related to programming, databases, and the like.
Forum Jump

[HOW TO] Speeding up PHP

Reply Post New Thread In Programming Tutorials Subscription
 
Send news tip View All Posts Thread Tools Search this Thread Display Modes
  #1  
Old 04-12-2005, 04:20 AM
JustinH JustinH is offline
Web Hosting Master
 
Join Date: Nov 2000
Posts: 3,042

[HOW TO] Speeding up PHP


I've seen far too many articles with "gimmicks" for speeding up your run-time for PHP applications, and thought I'd chime in on what not to do, and what you should do.

echo "Don't"; print('bother');

The two most common gimmicks for decreasing run-time are the single vs double quote issue and the echo vs print issue. The idea here: don't even bother.

$string = 'Here is my value';
$string = "Here is my value";

Neither of these strings contain anything for PHP to parse/escape. Processing time is going to be virtually identical... we are talking maybe a fraction of a millisecond. No benchmarking application can properly "benchmark" the differences between the two and as such, the time savings will be negligent for any single page.

The second is echo vs print... use whatever happens to be comfortable. How many times do you use echo or print on a single page? For the sake of argument I ran a script that used print and echo 1000 times in one page... the result? Inconclusive... they both averaged to approximately 0.0008 seconds each. When's the last time you used echo OR print 1000 times in one page?

On to the real stuff.

do { Smart control structures } while { programming }

What takes the most processing time out of a script? Loooooooooooping. Control structures vary signifigantly on speed. As of PHP5 my test results produced the following control structures in order of fastest for looping:

for ()
foreach ()
while()
do {} while()

for() is the fastest for obvious reasons, the loop is doing a numerical operation, which, computers were designed for in the first place, no arrays, true/false, return values, just pure math.

foreach() is secondary for a less obvious reason. While it is slower then for(), since an actual iteration occurs, it's faster than while() because no return value is required.

do-while() is obviously going to be the slowest. It inherits the requirements of while() which is just above it in speed, and requires PHP interperet a second construct "do".

You're probably starting to wonder what the heck I'm talking about, since each of these control structures are used for different purposes. The idea here, is designing your code in a way that is most optimal for speed. If you are using a lot of loops in your program, try to stick with indexed arrays so you can use the considerably faster for().

A final note on control structures: switch is faster then if/else nests, without question. It's easy to understand why:

PHP Code:
if ($variable == true)
{
    
// do something
} elseif ($variable == false)
    
// do something else

In this example, PHP has to read each statement seperately... so PHP will read:

$variable == true then $variable == false

Whereas a switch statement:

PHP Code:
switch ($variable)
{
    case 
'true':
        
// do something
        
break;
    case 
'false':
        
// do something else
        
break;

Now PHP will read:

$variable == true OR false
Since PHP is only working with one variable, it doesn't have to parse the statement twice.

Remember, using gimmicks are artifical means to produce almost negligent speed increases. Using proper coding techniques (and keeping the amount of code to a minimum) will produce the best results.

More to come when I'm not so tired .

Reply With Quote


Sponsored Links
  #2  
Old 04-12-2005, 06:28 AM
adaml adaml is offline
Web Hosting Guru
 
Join Date: Oct 2002
Location: York, United Kingdom
Posts: 260
Thanks,

I can hopefully make my php even faster!

You said about double quotes sometimes for variables you have to use them such as:

PHP Code:
echo '$variable';
echo 
"$variable"
you cant use a vairable inside ' ' you have to use " "

Just to let you all know

Reply With Quote
  #3  
Old 04-12-2005, 07:58 AM
error404 error404 is offline
Web Hosting Master
 
Join Date: Dec 2004
Location: Canada
Posts: 1,076
I'm not sure where you're getting your information on control structures from. With the exception of foreach, they all serve identical purposes and do identical things in a different order. On my machine, for is marginally (~ 5%) slower than while, which is itself about 5% slower than do/while.

There is certainly 'true/false' involved in a for loop. For example, for (;is_numeric($i);$i++); is a perfectly valid for loop, and will execute forever until you stick something non-numeric into $i. Further, for (;;) is often called the 'forever' loop. for loops are composed of three parts, all of which are regular statements (which always return some value, be it true/false, a number, an array, whatever), only one of which whose return value is actually considered. The first part before the first ; is executed only once, before the first time the loop body is executed, and it's return value is ignored. The second part, between the two ;, is executed *before* each loop body execution, and if it returns a value that evaluates to true (in PHP, anything other than [unset], 0, the empty string, and an empty array), the loop body is executed, otherwise the loop breaks. The final portion, after the last ;, is executed once at the end of the loop body *before* the check statement (the middle part). All of these statements can be *any* valid statement in the language; an assignment, a comparison, a mathematical operation, a function call..pretty much anything other than a language construct or code block. The following two loops are exactly identical in every user-visible aspect:
PHP Code:
// This happens to be an endless loop, but you get the idea
for ($a 0$a 2$a += 2)
{
   
do_something($a);
}
// Does exactly the same operations as:
$a 0;
while (
$a 2)
{
   
do_something($a);
   
$a += 2;

Comparing the three identical loops (for is really just a while loop with a pre-loop statement and a post-body statement as in the loop below) below on my machine (PHP 4.3.10 on Linux 2.4.27) yields the following times, averaged over 3 runs (though they're consistent to +/- 1/100th second each run):
PHP Code:
for ($i 0$i 10000000$i++)
   ; 
11.953s
PHP Code:
$i 0;
while (
$i 10000000)
   
$i++; 
11.46s
PHP Code:
$i 0;
do
{
   
$i++;
} while (
$i <= 10000000); 
11.1s

Unless you can omit the increment or something, the underlying code being executed should be essentially identical (at least between the while() and for() variants). The slight difference is probably due to internal function call overhead from the for() construct as opposed to the iteration being done inline. do/while getting a lead is somewhat puzzling, but the internals of the language are unknown. In any case, all the operations have extremely similar time constants, and all are O(n) in complexity.

Now, to further your own argument about print/echo..how often do you loop 10 million times in the same script? By an exceedingly large majority, your execution time will be bounded by the actual code being executed, not the language constructs. As is almost always the case, good design prevails over any syntax rules or other such nonsense. Things like hitting the database once for every returned row instead of using a JOIN, or executing the same code dozens of times instead of caching the results are things that will slow your code down, not using the wrong control structure (the performance of which is bound to change between revisions anyway).

I'm not going to post results here, but they were similarly opposite of what you said for foreach vs. for. Iterating through a 1000-element array with foreach 10,000 times took about 7.3s while iterating through the same array using for and an integer index took about 12.0s.

These results are highly likely to be machine and PHP-version dependant, so I'm not going to dispute the correctness of your post. I don't think the differences are even worth talking about though; it's doubtful that any real-world improvement could be gained from any of these techniques, and unless your application is absolutely time-critical, the scale of improvement you could conceivably get is so small as to not be worth the time. It's like trying to optimize C code with assembly - 99% of the time the gain is so small it's absolutely not worth the trouble - and the other 1% of the time it's debatable whether it was worth it or not.

Instead of changing all your loops to use for, perhaps it's better advice to examine them to see if they're looping too much, or if unnecessary computation can be cut out in places. Keep in mind that copying data is expensive, often moreso than operating on the data in-place, try to avoid unnecessarily copying things (though I believe PHP does copy-on-write, so this shouldn't be a huge concern either). Cache where it's prudent, hit your database as little as possible and let it do as much work as possible (sorting, filtering, joining, etc). Make sure you're using database indexes wherever possible.

Basically: use the language however you want, it's unlikely anything you do will be significantly slower than anything else (well, with PHP that's a bit iffy, using foreach (array_range(1,1000)) is certainly slower than a generic for loop and uses tons more ram..I haven't benchmarked the functional stuff like array_map, but it's not too mature so it's probably quite a bit slower too, but still negligible). Just don't do anything stupid with it and you probably won't speed your code up much :P.


Last edited by error404; 04-12-2005 at 08:10 AM.
Reply With Quote
Sponsored Links
  #4  
Old 04-12-2005, 01:45 PM
JustinH JustinH is offline
Web Hosting Master
 
Join Date: Nov 2000
Posts: 3,042
Quote:
Originally posted by error404
[B]I'm not sure where you're getting your information on control structures from. With the exception of foreach, they all serve identical purposes and do identical things in a different order. On my machine, for is marginally (~ 5%) slower than while, which is itself about 5% slower than do/while.
They can be used for the same purpose. I'm talking about proper coding techniques. Using a while loop to increment is using it outside the purpose it was intended for. While loops were initially developed for the purpose of checking for a true/false statement and continuing based on the result set:

PHP Code:
$i 0;
while (
$i <= 10)
{
    / do 
something
    $i
++;

Bad coding technique as a for() loop is intended for this purpose.

I'm guessing for your testing you used the typical ($seconds = microtime(true)). That's a poor method for benchmarking because it relies on PHP to parse the time string. Using a proper benchmarking tool is neccesary to get actual time for processing.

Quote:
There is certainly 'true/false' involved in a for loop. For example, for (;is_numeric($i);$i++); is a perfectly valid for loop, and will execute forever until you stick something non-numeric into $i. Further, for (; is often called the 'forever' loop. for loops are composed of three parts, all of which are regular statements (which always return some value, be it true/false, a number, an array, whatever), only one of which whose return value is actually considered. The first part before the first ; is executed only once, before the first time the loop body is executed, and it's return value is ignored. <SNIP>
Thanks for the tutorial but I'm well aware what you can do with loops, including the fact that they can be used for the same purpose. But again, this is about proper coding techniques, and using for() in the method you described is absurd... however, to comment on one aspect: the only true/false value for() looks for in a proper loop is numeric. As long as you stick to numeric values in a for loop, which is exactly what I pointed to in my post, it will be faster then while and do-while.

Quote:
Comparing the three identical loops (for is really just a while loop with a pre-loop statement and a post-body statement as in the loop below) below on my machine (PHP 4.3.10 on Linux 2.4.27) yields the following times, averaged over 3 runs (though they're consistent to +/- 1/100th second each run):
Again what benchmarking tool did you use?

Quote:
Unless you can omit the increment or something, the underlying code being executed should be essentially identical (at least between the while() and for() variants). The slight difference is probably due to internal function call overhead from the for() construct as opposed to the iteration being done inline. do/while getting a lead is somewhat puzzling, but the internals of the language are unknown. In any case, all the operations have extremely similar time constants, and all are O(n) in complexity.
The complexity factor (O(n)) isn't the only portion that can increase run-time for heavens sake. The underlying alothigrams that Zend/PHP uses is the primary concern for speed and in my benchmarking.

Take a look at:
http://ormestech.com/benchmark_suite...Ghz/loops.html

Their analysis shows far more detail then mine, but when looking at it, it gives you an idea of exactly when to use for and foreach. In that example it shows up to a 25% difference in speed depending on which function call you make. I'd say that's valuable, and certainly something to take into consideration when coding.

Quote:
Now, to further your own argument about print/echo..how often do you loop 10 million times in the same script? By an exceedingly large majority, your execution time will be bounded by the actual code being executed, not the language constructs. As is almost always the case, good design prevails over any syntax rules or other such nonsense. Things like hitting the database once for every returned row instead of using a JOIN, or executing the same code dozens of times instead of caching the results are things that will slow your code down, not using the wrong control structure (the performance of which is bound to change between revisions anyway).
That's absurd, the loops we are doing are abitrary. Once you actually add content inside the loop you are talking about a different ball game all together. That is when the cost of looping truly shows. A simply increment or echo statement won't show anything, and perhaps, that's the benchmarking that really needs to be done.

Quote:
I'm not going to post results here, but they were similarly opposite of what you said for foreach vs. for. Iterating through a 1000-element array with foreach 10,000 times took about 7.3s while iterating through the same array using for and an integer index took about 12.0s.

These results are highly likely to be machine and PHP-version dependant, so I'm not going to dispute the correctness of your post. I don't think the differences are even worth talking about though; it's doubtful that any real-world improvement could be gained from any of these techniques, and unless your application is absolutely time-critical, the scale of improvement you could conceivably get is so small as to not be worth the time. It's like trying to optimize C code with assembly - 99% of the time the gain is so small it's absolutely not worth the trouble - and the other 1% of the time it's debatable whether it was worth it or not.
I would agree, but it appears the above example received test results much like yours, so it appears mine is the blacksheep.

Keep in mind, looping is the most costly part of programming an interupted language for obvious reasons. By making loops as effective as possible (especially in the test that showed a 25% difference) you could increase the speed of your application considerably.

Quote:
Instead of changing all your loops to use for, perhaps it's better advice to examine them to see if they're looping too much, or if unnecessary computation can be cut out in places. Keep in mind that copying data is expensive, often moreso than operating on the data in-place, try to avoid unnecessarily copying things (though I believe PHP does copy-on-write, so this shouldn't be a huge concern either). Cache where it's prudent, hit your database as little as possible and let it do as much work as possible (sorting, filtering, joining, etc). Make sure you're using database indexes wherever possible.
That is exactly what I eluded to with the last sentence:
Using proper coding techniques (and keeping the amount of code to a minimum) will produce the best results.

But I felt that my test results were of interest as well, and posted them. Unfortunately, it appears loops are more machine dependant then one would expect, but the results are valid regardless. I don't think a 25% increase in every loops is something to write-off as not worth it. The bottom line: test, test, test.

Reply With Quote
  #5  
Old 04-12-2005, 07:08 PM
error404 error404 is offline
Web Hosting Master
 
Join Date: Dec 2004
Location: Canada
Posts: 1,076
Quote:
Originally posted by JustinH
They can be used for the same purpose. I'm talking about proper coding techniques. Using a while loop to increment is using it outside the purpose it was intended for. While loops were initially developed for the purpose of checking for a true/false statement and continuing based on the result set:
There is no intended purpose whatsoever. They're language constructs, they do a specific thing, and as long as that's what you want, you should use them for whatever you want. Imposing strict rules on structures is silly and just limits the programmer. Look at some C code sometime, you'll see for loops 'abused' all the time. The whole concept of iterators in C++, for example, relies on function calls to perform iteration over a collection. Certainly it's still iteration, but any function call is valid. While loops are even more frequently used where iteration is being performed. Use whatever tool you want to, they're absolutely interchangable.

Quote:
PHP Code:
$i 0;
while (
$i <= 10)
{
    
// do something
    
$i++;

Bad coding technique as a for() loop is intended for this purpose.
What if you're doing something more complicated that involves some pre-loop code and some post-block code and a test? Is it then bad to use a for loop because it's not iteration? These rules are silly. for loops are intended to initialize some variable(s), and test the boolean value of an expression, then execute some other expression each loop iteration. while and for are equivalent, just use whatever floats your boat and seems the simplest to you. Of course nobody would use a while loop as above, but there are all sorts of conditions in real code where a while loop is generally used when a for loop could be substituted and result in less LOC.

Quote:
I'm guessing for your testing you used the typical ($seconds = microtime(true)). That's a poor method for benchmarking because it relies on PHP to parse the time string. Using a proper benchmarking tool is neccesary to get actual time for processing.
I used the bash 'time' command and the PHP command line interpreter. The execution times are long enough that process setup/timing/code parsing is definitely not a factor; these things take on the order of 100ths of seconds, while the differences are clearly larger than that.

Quote:
Thanks for the tutorial but I'm well aware what you can do with loops, including the fact that they can be used for the same purpose. But again, this is about proper coding techniques, and using for() in the method you described is absurd... however, to comment on one aspect: the only true/false value for() looks for in a proper loop is numeric. As long as you stick to numeric values in a for loop, which is exactly what I pointed to in my post, it will be faster then while and do-while.
Your post was about speed, not pragmatism. I've simply shown that when performing identical operations, it's at least possible for while to be faster. That leads to the conclusion that doing any sort of optimization is useless because it depends heavily on the individual implementation of the language and the machine that it's running on, at the very least.

My point is simply that these factors are so infintesimally small that it's just a waste of time to bother with any sort of optimization in this area at all.
Quote:
The complexity factor (O(n)) isn't the only portion that can increase run-time for heavens sake. The underlying alothigrams that Zend/PHP uses is the primary concern for speed and in my benchmarking.

Take a look at:
http://ormestech.com/benchmark_suite...Ghz/loops.html
Of course there's more to optimization than the complexity of the operations, I simply tried to show that the overhead difference between the constructs is very, very small (5% at max), and since their complexity is the same, that tiny difference is the only one. Loop overhead itself is absolutely dwarfed by the actual code you're running inside the loop.

Your analysis URL does benchmarks using deceptively short loops. I suspect that we're talking about different things here. I'm more concerned about the cost of each iteration than the cost of setup/teardown of the loop. These examples, being so short, focus more on the setup cost - and don't compare for and while anyway. Mostly they mirror my own results.

Quote:
That's absurd, the loops we are doing are abitrary. Once you actually add content inside the loop you are talking about a different ball game all together. That is when the cost of looping truly shows. A simply increment or echo statement won't show anything, and perhaps, that's the benchmarking that really needs to be done.
That's exactly the point. If empty loops running to huge counts show virtually no difference in execution time, by the time you add real code into them, the difference will become even smaller. If I make a simple test to retrieve a single row from the database 100 times, the difference is not measurable. The 25% difference you show is basically all in loop overhead. With real code running, that code is going to be the large majority of the time spent in the loop; the loop overhead itself will be negligible when compared to the work that needs to be done, and that's my point. Who cares if while() is 5% faster than for() when your application only spends 0.1% of it's time actually processing the loop construct?
Quote:
But I felt that my test results were of interest as well, and posted them. Unfortunately, it appears loops are more machine dependant then one would expect, but the results are valid regardless. I don't think a 25% increase in every loops is something to write-off as not worth it. The bottom line: test, test, test.
Test results are always worthwhile information to have, but it's important that people understand the implications of the results before they go rewriting all their code. Machine dependance is actually pretty reasonable; different CPUs use different branch prediction methods etc., and as PHP relies on the C compiler for much of it's code generation, I'd expect to see different results depending on compiler version/architecture as well. There's far from a definitive 'fastest' way to do things, so just do things the most pragmatic way possible and be done with it. If it's really important to you, test it, but I'd wager cold hard cash that with any real application the difference will be so negligible that it's irrelevant.

Reply With Quote
Reply

Related posts from TheWhir.com
Title Type Date Posted
QTS Implements Government Cloud Test Lab at Richmond Data Center Web Hosting News 2013-05-10 12:18:40
Digital Realty Trust Updates POD Architecture Design for Data Centers Web Hosting News 2013-01-31 16:55:11
CloudFlare CDN Offers Web Hosts Reseller Opportunities via Parallels Partnership Web Hosting News 2012-12-04 17:05:10
Web Host NaviSite Adds to Cloud Management Portal Web Hosting News 2011-12-13 15:46:43
Parting the Clouds, Finding True Business Value with Steve Cumings of Dell Web Hosting News 2011-08-08 22:14:39


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes
Postbit Selector

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump
Login:
Log in with your username and password
Username:
Password:



Forgot Password?
Advertisement:
Web Hosting News:



 

X

Welcome to WebHostingTalk.com

Create your username to jump into the discussion!

WebHostingTalk.com is the largest, most influentual web hosting community on the Internet. Join us by filling in the form below.


(4 digit year)

Already a member?