Same Code, Different Servers, Different Results...

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
Inkyskin
Forum Contributor
Posts: 282
Joined: Mon Nov 19, 2007 10:15 am
Location: UK

Same Code, Different Servers, Different Results...

Post by Inkyskin »

Hey all,

I have some code that works brilliantly on my local server, but behaves totally differently on the live server. Heres a bit of the code:

Code: Select all

$categories_data = $categories->get_cats();
$categories_html = '';
function generate_list($parent){
    $has_childs = false;
    global $categories;
    global $categories_data;
    global $categories_html;
    global $html_website_path;
    
    foreach($categories_data as $key => $value){
    
        if ($value['parent_id'] == $parent) {          
 
            if ($has_childs == false){
                $has_childs = true;
                $categories_html .= '
                <ul>
                ';
            }
            
            $categories_html .= '<li>'.htmlentities($value['category_title']);
 
            // THIS IS MY LITTLE BIT OF DEBUG DATA
            echo $value['parent_id'].' - '.$key.' ('.$parent.')<br />';
            
            generate_list($key);
            $categories_html .= '</li>
            ';
            
        }
        
    }
 
    if ($has_childs === true) {
        $categories_html .= '
        </ul>
        ';
    }
 
    return $categories_html;
}
I call the code with generate_list(0); further down the page where I need it. Now, on the local server, the outputted debug data looks like so:

Code: Select all

0 - 38 (0)
38 - 39 (38)
39 - 40 (39)
39 - 41 (39)
39 - 42 (39)
39 - 43 (39)
39 - 44 (39)
39 - 45 (39)
39 - 46 (39)
39 - 47 (39)
39 - 48 (39)
0 - 49 (0)
49 - 50 (49)
50 - 51 (50)
50 - 52 (50)
50 - 53 (50)
50 - 54 (50)
54 - 55 (54)
50 - 56 (50)
50 - 57 (50)
50 - 58 (50)
49 - 59 (49)
59 - 60 (59)
59 - 61 (59)
...
That's all good, but on the live server, I get something like the following:

Code: Select all

0 - 38 (0)
0 - 38 (38)
38 - 39 (38)
0 - 38 (39)
38 - 39 (39)
39 - 40 (39)
0 - 38 (40)
38 - 39 (40)
39 - 40 (40)
39 - 41 (40)
39 - 42 (40)
39 - 43 (40)
39 - 44 (40)
39 - 45 (40)
39 - 46 (40)
39 - 47 (40)
39 - 48 (40)
0 - 49 (40)
...
Which is not correct... Is there anything I'm doing that blatantly wrong? Both servers are PHP 5 (local, 5.2.8 - Live, 5.1.6)
User avatar
omniuni
Forum Regular
Posts: 738
Joined: Tue Jul 15, 2008 10:50 pm
Location: Carolina, USA

Re: Same Code, Different Servers, Different Results...

Post by omniuni »

Although it is possible that there was a bug with rounding or something fixed since your live servers PHP release, I would check your get_cats() code and make sure that your function is GETTING the same input. Guessing that this comes from a DB of some sort, are the DB's themselves the same? Put in some code to dump what get_cats() is generating before you run this function, and see what it is. Let us know!

-OmniUni
User avatar
Inkyskin
Forum Contributor
Posts: 282
Joined: Mon Nov 19, 2007 10:15 am
Location: UK

Re: Same Code, Different Servers, Different Results...

Post by Inkyskin »

Hey there, both DB's are identical, right down to the ID's, and so are the array's being passed - everything matches up - really stumped with this one!
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Same Code, Different Servers, Different Results...

Post by Weirdan »

Running multiple foreach loops on the same array simultaneously (like you do in your code) is not wise - foreach uses internal array pointer and even though it's said to operate on array copy, different versions of PHP may use either internal pointer of that copy or internal pointer of original array.
User avatar
Inkyskin
Forum Contributor
Posts: 282
Joined: Mon Nov 19, 2007 10:15 am
Location: UK

Re: Same Code, Different Servers, Different Results...

Post by Inkyskin »

Thanks - I'm thinking of re-writing it all anyway as it's only an early version. I had to cache it as it is anyway as it goes through 2500 rows, and is slooooooow. Any better way for recursive stuff that you folk know of?
User avatar
php_east
Forum Contributor
Posts: 453
Joined: Sun Feb 22, 2009 1:31 pm
Location: Far Far East.

Re: Same Code, Different Servers, Different Results...

Post by php_east »

i think the recursion is fundamentally flawed ( unless you want that on purpose ). i think also the server is right in that it is of much higher speed that your local and hence fetches the second (recursed) values before the output of the next iteration ( foreach ) and dumps this value out, which is what you are getting. that you not get this value from your local is because the iteration is executed first, and the function call result comes a little later. in the server, this function call comes through much faster, and you get the result higher up in the output.

it has not to do with version variations or no variations, it has to do with processor speed, the ability of the processor to perform in a memory hungry recursive algorithm.

the foreach has to be out of the recursive loop, and the recursive function called from within this external loop, rather than internally. which also means you would have a $key for the internal interation, but a different variable assigned as the key for the topmost external iteration. in that way, you do not confuse computer which key is the iterator key and which is the recursive key value.

what i'm saying is that you need two mechanisms to surf through the category, one to iterate and the other to recurse and output values.

if you look at the setup as it is, you can see that the value of $key, passed to the recursive function, will be reset each time it passes through the recursion, and you start the recursion all over again with the a fresh new key values, i.e. starting from the first key again. and this is exactly what you get from the server. and i presume this is not what you want, you want the recursor function to process the next key.

i'm suprised it does not time out. that it behaves very slowly is an indication of a seemingly endless loop, which is what the codes does, nearly endless but not quite so.

i would not advise using this sort of codes, you would find huge performance problems.
that you are rewriting it again is perhaps all the better, recursions are slow but not *that* slow.

2500 records is nothing. it ought to process in less than a second somewhat.
hope this helps.
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Same Code, Different Servers, Different Results...

Post by Weirdan »

Inkyskin wrote:I had to cache it as it is anyway as it goes through 2500 rows, and is slooooooow.
ur... do you understand that your implementation is scanning ~6 250 000 rows (in other words, it's O(n^2), maybe O((n^2)/2) in the best case)? If you could guaranty that parent element always comes right before its children in $categories_data, you could unwind the recursion and turn it into a single loop over 2500 rows.
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Same Code, Different Servers, Different Results...

Post by Weirdan »

php_east wrote:i think also the server is right in that it is of much higher speed that your local and hence fetches the second (recursed) values before the output of the next iteration ( foreach ) and dumps this value out, which is what you are getting. that you not get this value from your local is because the iteration is executed first, and the function call result comes a little later. in the server, this function call comes through much faster, and you get the result higher up in the output.

PHP is single threaded and thus the effect you describe is not possible in PHP. The order of execution is strictly defined here.
php_east wrote: it has not to do with version variations or no variations, it has to do with processor speed, the ability of the processor to perform in a memory hungry recursive algorithm.
It's not memory hungry. There's just a simple array of 2500 elements, plus about 2500 references to it (it's true as long as InkySkin does not write anything to the array while iterating over it).
php_east wrote: i'm suprised it does not time out. that it behaves very slowly is an indication of a seemingly endless loop, which is what the codes does, nearly endless but not quite so.
It's not endless. Just long enough :D, like a loop over >6M records.
User avatar
Inkyskin
Forum Contributor
Posts: 282
Joined: Mon Nov 19, 2007 10:15 am
Location: UK

Re: Same Code, Different Servers, Different Results...

Post by Inkyskin »

Weirdan wrote:
Inkyskin wrote:I had to cache it as it is anyway as it goes through 2500 rows, and is slooooooow.
ur... do you understand that your implementation is scanning ~6 250 000 rows (in other words, it's O(n^2), maybe O((n^2)/2) in the best case)? If you could guaranty that parent element always comes right before its children in $categories_data, you could unwind the recursion and turn it into a single loop over 2500 rows.
At the moment i cant guarantee - recursion hurts my head lol
User avatar
php_east
Forum Contributor
Posts: 453
Joined: Sun Feb 22, 2009 1:31 pm
Location: Far Far East.

Re: Same Code, Different Servers, Different Results...

Post by php_east »

Weirdan wrote: PHP is single threaded and thus the effect you describe is not possible in PHP. The order of execution is strictly defined here.
exactly. the order of exection means the first recursive call with a value of $key will be called inside of the iteration, and *that* is the order. so being single threaded, which i have no notion of, is insignificant and does not have bearing on the output. even if it is multi threaded, the same behaviour would be exhibited and the right order still prevails as you say, meaning the code itself specifically does so. so i guess in a multi-thread environment, it would only be worst, in the sense that the output may be unpredictably jumbled. in this case, i assert that the output is very predictable, and is dependent on processor speed.

in the slower pc, the output of the iteration gets out first. it is buffer speed, which gets flushed out first. i encounter this many a times, at HTTP level, when i incorrectly respond to my own posts. the results are predictable and verifiable.

so what i am saying is it does change the output, depending on processor. i am willing to take a professional bet on that, just for the sake of argument. the order of output of the first (local) version is wrong, as the processor is not fast enough. the second output, which Inkyskin thinks is wrong is actually correct, if we are to assume that a processor should in theory have infinite speed. relatively speaking, relative to his home pc, the remote server is much faster. the behavior is much like a memory leaking program.

but just let say you, are right, what explanation can you offer for the different values he has on two computers running same PHP ? i'd be keen to know. recursion is one thing, getting different output on different server is another.
Weirdan wrote: It's not memory hungry. There's just a simple array of 2500 elements, plus about 2500 references to it (it's true as long as InkySkin does not write anything to the array while iterating over it).
it is. if it has to call a function carrying the load of a whole array the 6 million times you calculated. each time it assigns a new set of pointers to the recursed function, no ?
and the pointers must be preserved, stacked, because the show is not over yet.

but you are right, it did not reach a point where PHP demands more memory. but that isnt the same as saying it is not memory hungry.
php_east wrote: i'm suprised it does not time out. that it behaves very slowly is an indication of a seemingly endless loop, which is what the codes does, nearly endless but not quite so.
Weirdan wrote: It's not endless. Just long enough :D, like a loop over >6M records.
well that is what i said. nearly endless, seemingly endless, but not quite so as there is a finite number of elements in the array, fortunately, so it will end....someday :)
Post Reply