I have a php script that loops many times. Is there a way in PHP to tell whether it was the last iteration ? Script is rather complex (1700 lines) and I can't locate the snippet responsible for running the script from the beginning.
Ideally I'm looking for a function (put in the end of the file) which predicts whether or not the script is going to run again from the beginning (as it does). Sure, other solutions are welcomed. The amount of iteration depends.
UPD:
Sorry, it's not loop that causes script to start over. There is something else (that I can't define) that makes the page to run from the beginning.
I assume you mean something like this:
$max = 10;
for($i = 0; $i <= $max; $i++) {
if($i == $max) {
//last iteration
}
}
Related
This is not a question about principles or common coding procedures, it is a question about how PHP processes code, or more precisely, doesn't process code that it should ignore, in the name of better understanding how PHP works
Scenario 1:
if (1==2) { echo rand(0,99); }
Obviously, the code above will not have any output, and that's not what the question is about; but rather, about whether or not PHP even considers making any output. As PHP goes through the page, does it entirely skip the code assigned to the failed if-check, or does it get allocated any sort of resources beyond simply what the filesize does?
Scenario 2:
if (1==2) { for ($x = 0; $x <= 999999; $x++) { echo rand(0,99); } }
Similar to scenario 1 but with a key difference to clarify the point, considering that 1==2 is always going to be false, does this code use any more resources than the previous one or will they both be equally "cheap" to process? Or are there any "hidden" actions that add up even if the code in the loop is as minimal as this?
Scenario 3:
for ($x = 0; $x <= 999999; $x++) { if (1==2) { echo rand(0,99); } }
Now, this one should see a false statement a million times, but how significant is that really in terms of resources? Will it keep checking if 1 is 2 or does PHP "learn" from the first time it checks? And does it spend any resources beyond that, or is a simple if-check like this inside a loop the only thing PHP will process? Will it "read" echo rand(0,99); a million times, even though 1 is not 2?
Scenario 4:
for ($x = 0; $x <= 999999; $x++) { if (1==2) { for ($x = 0; $x <= 999999; $x++) { echo rand(0,99); } } }
Finally, a combination of them all, will this example be a massive loop-in-a-loop-level of resource wasting or will the inner loop be completely ignored from processing? In other words, will 1!=2 cause PHP to entirely skip processing the inner loop, or will it waste memory on code that it should ignore? And how different is this scenario compared to the previous three in terms of processing and resources?
Thanks in advance for any PHP and memory-usage expertise on the matter, it is my hope that the answer to this question will bring better understanding about how PHP processes code to me and others
EDIT:
Another somewhat relevant example would be that of having a large amount of comments within a loop compared to outside of it; would comments inside of a loop affect performance differently in any way (regardless of how "unnoticeable" you might consider it to be) than the same amount of comments outside of the loop?
1 & 2) Everything inside these if blocks is not evaluated
3) PHP doesnt learn anything, it will perform 1 million if checks. This isn't significant but it's not insignificant either. As one commenter suggested, try it and see the page time hit.
4) This generates the same amount of processing as #3
After reading branch predication, I tried to understand how it works.
I wrote a basic test (below).
I think after the first loop php knows how array is structured and predicts the result of condition ($items[$i] <= 150000), but the time of second loop is the same as the first loop and it does not seem to benefit from branch predication.
Some questions:
Maybe php does not support branch predication?
Maybe I did not understand branch predication?
My test is wrong/has other performance issues?
My test:
$count = 300000;
$items = array();
$found = 0;
// build array
for ($i = 0; $i <= $count; $i++) {
array_push($items, rand(0, $i));
}
// first loop with no predication benefit
// ------------------------------------
$time_start = microtime(true);
for($i = 0; $i <= $count; $i++) {
$found = ($items[$i] <= 150000) ? $found+1 : $found;
}
$time_end = microtime(true);
$time = $time_end - $time_start;
// ------------------------------------
echo "first loop\r\n";
echo 'Found:'. $found . "\r\n";
echo 'End:' . $time . "\r\n";
// reset counter
$found = 0;
// second loop with predication benefit
// ------------------------------------
$time_start = microtime(true);
for($i = 0; $i <= $count; $i++) {
$found = ($items[$i] <= 150000) ? $found+1 : $found;
}
$time_end = microtime(true);
$time = $time_end - $time_start;
// ------------------------------------
echo "second loop\r\n";
echo 'Found:'. $found . "\r\n";
echo 'End:' . $time . "\r\n";
output
first loop
Found:254052
End:0.093052864074707
second loop
Found:254052
End:0.092923879623413
http://codepad.org/Zni0b5rS
TL;TR
Branch prediction is a hardware feature.
The programming language which benefits from hardware features is C in this case. (PHP is written in C). Or truly spoken the machine code compiled from PHP's C sources. So yes, you already benefiting from branch prediction, but not it the way you might think of.
Benefiting from branch prediction happens on a far lower level. Basically you need to know that subsequent machine(!) commands are loaded into the CPU's pipeline before getting executed. But loading commands takes time.
If there is a conditional jump command to be executed, the subsequent commands in the pipeline might not being up to date any more if the condition evaluates to true, since the jump commands tells the CPU to go on loading commands from a complete different location in the (machine(!)) code - the jump target - in that case.
This means the CPU needs to flush the existing pipeline and refill it with commands starting a the jump target's location. If at the location there is another jump target the same would happen again. Note that conditional jumps are one of the most seen machine code commands.
That said, the performance of the command pipe line would basically not being sufficient.
What if the CPU might be smart and guess if the condition evaluates to true even before it get's evaluated? It could load commands from that jump target immediately after it loads a jump command into the pipeline. Note that loads is not equal to executes! Again, the CPU tries to guess that before the condition gets evaluated. If the guess should be wrong, the CPU will of course still need to flush the pipeline and refill it with the correct commands. But chances that flushing isn't necessary are better than compared to not guessing it.
There are multiple algorithms that implements the guess, from static to dynamic approaches which take into account what the code has been doing so far. They are pretty sophisticated and reach amazingly high success rates. Check back to Wikipedia, algorithms are explained there:
https://en.wikipedia.org/wiki/Branch_predictor
Returning back to your PHP code; Even the first loop might likely benefit from branch prediction.
Yes, it is obvious that both loops are doing the same and are therefore only needed to be executed once. However, PHP as an interpreted programming language is a far too high level to analyze such hardware features because too many things happen behind the scenes. (Probably even a task switch between the loops).
Btw, if you would have written comparable code in C, the C compiler would have likely opted this out. gcc for example can detect a lot of such situation. (Amazing!) However, this would already happen at compile time, even before run time.
If you are willing to analyze branch prediction, using the Assembler language and the GDB debugger can show it working in practice.
I am at a complete loss. I've searched this site extensively and others as to why my for loop, among many other working loops, will not execute, and tried many suggestions. I have checked that it is in fact not executing and not failing to meet a condition for its execution. This is the loop:
if (count($bunnyList)>100){
echo "Too many bunnies! Initiating mass cull.</br>";
for ($i=0; $i===50; $i++){
echo 'something';
unset ($bunnyList[rand(0,(count($bunnyList)))]);
array_values($bunnyList);
}
echo 'Number of bunnies: '.(count($bunnyList));
The if condition executes; the first echo statement executes, and then the echo statement following the loop also executes. If the loop had been executed, then I should get a number of "something"s printed to the page, and yet I never have, even after trying tons of suggestions for other people's failed for loops. After staring at this particular piece of code for hours I'm reasonably sure I haven't messed up a piece of syntax. Please help me, I've already pulled too many chunks of my hair ou
:(
The entire code is over a hundred lines long and I didn't think it prudent to post the whole thing. In addition, all the other for loops within the program work just fine, while endless variations of this one do not.
I apologize if this is a redundant question or if it has been asked before. Other answers to questions similar to mine were not able to fix the problem. Please help me D:
TL;DR Why does only this for loop not execute within my program containing many functioning loops? The echo statements within the if condition do execute.
Try:
for ($i = 0; $i < 50; $i++) {
Instead of:
for ($i = 0; $i === 50; $i++) {
In a for loop, the second part is NOT the ending condition, but the continuation condition. In your case it's checking if $i is equals to 50, and because it is not, it will never go in the loop.
I'm not too familiar with php, more java, but shouldn't it for each time 'I' is less than 50, increment by 1?
for ($i=0; $i < 50; $i++){
...
}
I am assuming that is the syntax.
Try like this:
for ($i=0; $i<=50; $i++){
echo 'something';
unset ($bunnyList[rand(0,(count($bunnyList)))]);
array_values($bunnyList);
}
I was looking through some code at work and found something I've not encountered before:
for (; ;)
{
// Some code here
break;
}
We call the function that contains this all the time, I only recently got in there to see how it works. Why does this work and is it documented somewhere?
It seems as though a while loop would have been more appropriate in this instance...
It's essentially the same as while(true). It doesn't have any initialisation, doesn't change anything between iterations, and in the absence of anything to make it false the condition is assumed to be true.
It's an infinite loop.
Normally you would have something like:
for ($i=0; $i<10; $i=$i+1)
But you can omit any of the parts.
These are all valid:
for ($i=0; ; $i=$i+1)
for (; $i<10; $i=$i+1)
for (; $i<10;)
However, if you omit the second part, there will be no condition for exiting the loop. This can be used if you do not know how many times you want to run the loop. You can use a break instruction to exit the loop in that case
for (;;)
{
// some code
if (some condition)
break;
}
Note that if you do not put a break the page will just get stuck and run indefinitely
The first blank statement is executed at the beginning.
The second blank expression (which determines whether you exit the loop or not) evaluates to TRUE implicitly:
http://php.net/manual/en/control-structures.for.php
The third blank statement executes after each iteration.
So any condition that kicks out of the loop will need to be in the loop itself.
So what I am trying to do is process an array. The array contains one thing: photo urls.
When I use foreach()I get a limit error (500 internal error). It seems that it started happening after I rewrote the script. But that doesnt make any sense as there are no errors in the script and it was working perfectly before. The script still works, it can only process about 30 photos before the error pops up. Is it possible to use while() to process the array? Would it get rid of my 500 error for some reason?
Thanks for the input!
Brandon
If you're getting timeout (infinite loops) errors, neither while or foreach will do. You're better off looking at limiting how much your array is processed, and do it step by step (Pagination..?).
for ($i = 0; $i < 100; $i++)
{
//Do your thing. Don't use for each, use $array[$i]
}
if it's not numeric, use a while with two statements:
while ($test = current($array) && $i < 50)
{
//xxxx
next($array);
$i++;
}
For performance is better foreach cycle.
Visit this site with some benchmark of php and see which cycle is better for you:
http://www.phpbench.com/