Development speed is more valuable than processing speed to a PHP developer.
Touche
As for why count isn't optimized. Loops are optimized based on the ability to unwind a loop into a linear structure
While this is true in compiled languages, I'm not sure PHP itself would perform this kind of optimization analsys, as it would cause more harm than good...perhaps Zend optimizer does this when compiling to byte code, but...I can't see PHP interpreter doing this...
some really good compilers would see that the whole loop was pointless and just assign 3 to $blah. If you embed the count() in the for definition, it HAS to call that function every iteration
While I agree a good compiler would likely do this, I would argue that, any interpreted language wouldn't go that far, and likely just interpret code as is, leaving architechure specific optimizations to the programmer...
When dealing with compiled languages there are many caveats which a compiler can and will take care of, such as loop unwinding, using shifts in place of normal DIV instructions, etc...but often these are ignored in interpreted environments, because they are machine agnostic, so optimizations like this *might* not make sense...
Here is an article I wrote on the subject:
http://www.codeproject.com/cpp/profiler.asp#xx1444259xx
Ignore the comments by people informing me that a good compiler would perform these optimizations automatically, as they clearly didn't get the *point* of the article
It was intended to be an overall introduction into optimizing, etc...obviously I was aware of compilers abilities to auto-optimize
Anyways, many of those principles could likely be applied to interpreted languages as again I would argue that interpreters likely don't optimize to much, as it would require a fare amount of code analsys...best left for a compilation step, not interpretation...
The point is, I agree count() performs poorly but it's not because PHP doesn't unwind loops (cuz clearly it never does) but rather because every iteration of a loop must execute it's expressions, in this case count().
After some thought, I've come to the conclusion this is impossible to optimize at the interpreter level because there is no way of telling whether the programmer really meant to cache the value of count().
What if inside the loop, elements are added to the array count() is counting? That value must change, so trivial caching anyways, simply wouldn't work...
Thus the reason I'm willing to bet PHP developers haven't bothered to optimize it any...
Optimization is hard without knowing the underlying structure.
Not sure what you meant here, but I assume you mean system architecture, in which case...PHP would be impossible to perform low-level optimizations, as it's capable of running on *almost* any computer on the planet, from Mainframes to 286's in my basement
I was just wondering how this optimizes? Do you have a code example that performs some empirical testing
I'm sure your tired of hearing me talk so i'll make it breif as possible
Me and Feyd has a disscussion a while back about how PHP allocates memory, etc...
From that disscussion and doing some research I concluded that:
1) unset() deallocates the memory previously used, so other parts of the script can now use that memory. How this de-allocation works is beyond me as I was not interested in reading the PHP C source and learning first hand.
From what I read it seemed people where having positive experiences calling unset on large arrays *before* functions returned...however this was determined (from what I could tell) by people using Windows resource moniter to observe memory usage...
They were saying that by calling unset() before returns, resource monitor indicated reduced memory consumption...
This suggests that unset() is calling the systems underlying malloc, free, etc functions
However I am also under the impression that PHP likely uses it's own memory allocation functions as PHP has built in garbage collection facilities, so I wonder that PHP's unset() perhaps might call it's own zend_free() type function, which (to my understanding) doesn't actually free memory so anything else on the system can use it, but rather marks it as availble space only under the context of the currently executing script.
I'm starting to loose myself here, as this topic is rather complex, especially as no one but the PHP develoeprs really know whats oging on with memory allocation, etc...
Anyways, my reasoning as to why calling array_filter() instead of unset() goes like this, while understanding what I said above:
unset() does actually free memory...as in...the system can use it, not just the script...
Freeing memory, requires re-adjusting memory descriptor tables, etc...which is a potentially an intensive process...but then the rest of the system can use it, which is generally a good idea...but not always
Assigning a element to FALSE requires very little outside of an assignment operation...as it's not likely freeing memory under PHP's context or under the systems context...it's only marking as potentially free as you can change FALSE back to something else if desired...(I assume)
array_filter() however free's the memory, atleast under the context of PHP, not sure if it's system wide like I assume unset() is...
So...
In a loop, if you are calling unset() every iteration and it is indeed freeing memory system wide, that is taxing on the system...
Even if it is freeing it under only the context of PHP...thats going to require more managment than a trivial assignment.
Marking an elelement as FALSE and then at the end of script execution calling a single array_filter() is likley going to be much faster, as it just makes sense from a technical standpoint...so I likley wasn't day dreaming when I profiled that code and noticed the difference...
All databases that I know of, in fact use this
flag and continue technique whenever they can...as it's much faster than removing a record from disk, recalculating offsets and indicies, etc...
you can consider array_filter() the likely faster equivelant of doing this:
Code: Select all
$cnt = count($arr);
for($i=0; $i<$cnt; $i++){
if($arr[$i] === FALSE)
unset($arr[$i]);
}
It's just faster than calling unset inside the loop, by nature of what unset actually does
This is my take on the subject anyways
Cheers
