Hey all I am new at php,
I have just given a while loop a go and
its locking up firefox in an infinite loop,
I really cannot see what is wrong with it.
[COLOR=“Black”]
I personally have found while loops to be faster, someone ones gave me their code, in the places where they used for loops i switched them over to while loops which helped to speed up the script execution time. I’ve also read that while loops don’t take up as much memory, that is something that i’ve yet to test myself.
I found that somewhere between 1,000 loops and 10,000 loops a point is reached when a for loop becomes faster.
With regard to:
I don’t see how there is any more or less to break, the only difference being the number of lines it’s spread over and the use of one less ; with the for loop.
One statement optimized for looping off a single var vs. three separate statements that are not. Giving it all the values up front means faster execution. I’d only use while if I could do so by using one less variable in the loop.
NOT that C style “for” loops are particularly efficient – since without stating a range there’s little way to optimize it down to a single register for the proper ASM “loop” command… It’s still gonna be faster than a while even when said while performs the same general operations. Right tool for the right job. A fixed number of loops is what “for” is … for…
Programming 101 – “while” is for when the condition is not a fixed set of results that can vary depending on what goes on inside the loop, “for” is for when the condition is always a fixed number of iterations.
Besides, three lines of code instead of five? Less code you use, the less there is to break.
Don’t know if I’d call that intuition – It’s common sense if you understand machine language, and then think about what’s involved in trying to make something like a PHP interpreter to run atop it. Interpreters start way way out from how machine language works in the first place – PHP with the lack of typecasting ends up just that much more convoluted.
But then I still do assembly inlined into both C and Pascal, so I understand how values are passed to functions – either on the stack (making a copy) or by a pointer on the stack (what php calls a reference). With PHP it’s even heavier in that regard given the lack of strict typecasting and the rather complex objects they must use under the hood to handle that.
There’s a lot of low level stuff that if people in high level languages understood – ESPECIALLY interpreted languages like Perl or PHP – they’d probably write their code in an entirely different manner.
Though I’ll freely admit, I sometimes overthink that part given I still write code where a 4.7mhz 8088 is my minimum target.
I can’t see in the code in post #12 where you’re adding anything to the $result array (presumably that’s happening elsewhere in another nit of code elsewhere.
Just using as an example the fetching of a result set from a database and doing something with it:
<?php
// connect to database here
// send query off to db server, result resource stored in $result
$result_set=array(); // create an empty array for the result set
// function db_fetch_array would be whatever function is actually being used to fetch an array
while ( $row = db_fetch_array($result)) {
$result_set[]=$row;
}
foreach ( $result_set AS $result_row) {
// do something such as display as a row in a table
}
?>
My own personal preference is to define a variable that i’m going to use as an array as an empty array before I start to add anything to that array then if the array is empty the foreach loop will see an empty array instead of a normal “non-array” variable.
I would suspect more a memory issue for that – that typecast effectively makes a second copy in memory of the element – if that’s a really large string or worse, an object instead of an array, that could end up sucking down RAM like it was candy.
But a lot of people don’t think about that in their code a whole lot; See UBBThreads for a great example of that in action – where it uses ten times as much memory as any other forum software on the same number of posts and users JUST because of code decisions like this one.
I wasn’t aware that could work to be honest. I’m still hesitant to change it over though for this reason: Results are either responder objects or event objects. Responder objects implement ArrayAccess, and if PHP ever core supports a magic __toArray method I would implement that method to return the responder’s current storage array in the next version of the framework (the object already has a non-magic toArray method). That would create a problem here. Then again, maybe I’m overthinking it.
Also, as Jason points out, recasting can have negative consequences. I try to avoid casting when I can. His intuition is right - responder objects can be some of the largest in terms of memory footprint that the framework asks PHP to handle, especially right after parsing their templates.
Since live examples help, here’s an example of a do while loop that shouldn’t be handled with another loop type…
// Let the heartbeat commence.
do {
// Get an event.
$event = array_shift($this->queue);
try {
// If the event is a page, assign it and clear the queue and responses.
if ( $event instanceof Page ) {
$this->startPage($event);
}
$result = $event( $this->page );
} catch ( Exception $e ) { // Uh oh - error page time.
/*
* If the page is an error page, we need to elevate to fatal
* exception or run the risk of getting caught in a loop.
*/
if ($this->page instanceof ErrorPage ) {
throw new FatalException($e->getMessage);
} else {
/*
* Resolve gracefully. Note that these errors can be cause
* by user interaction - 404 not found pages pass through
* this mechanism.
*/
$ep = $this->dataDispatcher->getSetting('core', 'errorPage');
$this->startPage (
new $ep( $e, $event, $this )
);
}
}
// An event may return multiple events, especially pages.
if (is_array($result)) {
foreach ( $result as $r ) {
$this->route($r);
}
} else { // Handle just the one result.
$this->route($result);
}
} while( count($this->queue) > 0);
The function this is in is resolving a page, and pages are broken into a chain of events. Once all the events are done the loop is done.
Without going into too much detail, the reason this is a do…while and not a foreach is that $this->queue will be changing. As the events resolve they may add one or more additional events to the event queue. They might even clear the event queue out to start a new one. You can’t (well, shouldn’t) change the contents of an array while iterating over it with foreach, and the functions called in this loop can add more events to the queue. The term queue is used because we are resolving the events in Last In Last Out (LILO) order. The reverse of this would be a stack (Last In First Out - LIFO).
It has to do with how the PHP interpreter handles it I guess.
For is meant for strict iteration counts. Use for when you want the computer to iterate I number of times.
While is used to loop, indefinitely, based on a condition. It is possible for that condition to never be true and the loop never be entered as a result. For example
Here the while never runs at all because it’s condition is never met. It’s checked before execution. On occassion you will want the code in the loop to run at least once, so you want to check the condition at the end of the loop. For this use do…while
$input = 12;
do {
echo $input;
$input++;
} while ($input < 10);
This second example will echo 12. Input will be incremented and we exit the loop.
Rarest of all are loops which break due to multiple conditions arising out of their parsing. For this reason the break statement exists, allowing you to break from the loop at that point. Similarly, sometimes you need to go back to the start, so there exists a continue statement.
All of these options are flexible enough that you have a choice. But knowing their purpose allows you to choose the one best suited.
And don’t forget foreach, which iterates over the members of an array, object or other iterator. Indeed, objects can have very sophisticated iteration behavior when necessary, but that is out of the scope for this post.
Sorry to join the looping conversation, but surely:
for (INIT; CONDITIONS; UPDATE) {
BODY
}
Is no different to this?
INIT
while (CONDITIONS) {
BODY
UPDATE
}
There may be small micro-optimisations that one can do with proper benchmarking, but I’d be willing to bet that there are plenty of other areas where you can improve performance outside of what loop to use. Either way, deathshadow60 is right in that you should know what loop fits what style of programming and what makes your code more concise and readable.
My own personal preference is to define a variable that i’m going to use as an array as an empty array before I start to add anything to that array then if the array is empty the foreach loop will see an empty array instead of a normal “non-array” variable.
As is mine, but that isn’t done here for a couple reasons.
First, most events return only one response, one other event, or null. The use case of multiple events bundled in an array is the minority. Maybe 1 in 10 events sends back multiple events to the dispatcher. In light of this, requiring the response to be wrapped in an array would be an annoyance.
Second, events will be written frequently and by many programmers. Applications written using this framework are divided up into events. It is important that the API be easy to use - and requiring programmers to always wrap their response in an array isn’t user friendly to the other programmers who might use this.