Hall of Famer Posted March 17, 2013 Share Posted March 17, 2013 (edited) Well I'm thinking about replacing most of my arrays with known size by PHP's SplFixedArray since it's faster and more efficient. I tested it on my site, the result is not surprising, SplFixedArray is indeed faster in most occasions. What astonished me was that after I created this subclass called NumericArray by extending PHP's SplFixedArray, the child class turns out to be even faster. Here's the code I used to generate the result, which is similar to what the sample code from PHP.net: <?php class NumericArray extends SplFixedArray{ } for($size = 100; $size <= 102400; $size *= 2) { echo "<br>"; echo PHP_EOL . "Testing size: $size" . PHP_EOL; echo "<br>"; for($s = microtime(true), $container = Array(), $i = 0; $i < $size; $i++) $container[$i] = NULL; echo "Array(): " . (microtime(true) - $s) . PHP_EOL; echo "<br>"; for($s = microtime(true), $container = new SplFixedArray($size), $i = 0; $i < $size; $i++) $container[$i] = NULL; echo "SplArray(): " . (microtime(true) - $s) . PHP_EOL; echo "<br>"; for($s = microtime(true), $container = new NumericArray($size), $i = 0; $i < $size; $i++) $container[$i] = NULL; echo "NumericArray(): " . (microtime(true) - $s) . PHP_EOL; echo "<br>"; } ?> And here are the results for the smallest, median and largest array size: Testing size: 100Array(): 3.09944152832E-5SplArray(): 2.28881835938E-5 NumericArray(): 1.19209289551E-5 Testing size: 3200Array(): 0.000507116317749SplArray(): 0.000546216964722NumericArray(): 0.000308036804199 Testing size: 102400Array(): 0.0228500366211SplArray(): 0.0149321556091NumericArray(): 0.0126581192017 Perhaps the results will be different if I run at even larger size such as 1000000, but my server apparently runs out of memory at that stage so I cannot justify this statement. Anyway, the result does not seem to make sense. To my understanding the subclass should always be slower than the parent class. The result is not much different even if I add a constructor method for the child class, although this will somewhat reduce the gap between the performance of two classes. Maybe the test code I ran had flaws in it? I am not quite sure since thats what people on PHP.net runs the test code. I did carry out multiple test runs, there were slight variations but in all test runs the NumericArray was always faster. The only possible explanation is that the child class loses part of the functionality from this parent class, but I dunno if this is true. Sure there is a good chance that the operation on array elements is slower for the child class, but it is still difficult to interpret why the child class is faster to construct. Can anyone explain this phenomenon that I find absurd? Edited March 17, 2013 by Hall of Famer Quote Link to comment Share on other sites More sharing options...
salathe Posted March 17, 2013 Share Posted March 17, 2013 Change the order of SplFixedArray and NumericArray in your test. See what happens. Quote Link to comment Share on other sites More sharing options...
Hall of Famer Posted March 17, 2013 Author Share Posted March 17, 2013 Change the order of SplFixedArray and NumericArray in your test. See what happens. lol it does change quite a bit, thanks for pointing this out. So guess the order of testing actually matters? If so, how do we figure out which one is faster than the other? Quote Link to comment Share on other sites More sharing options...
Jessica Posted March 17, 2013 Share Posted March 17, 2013 You can test them on their own and compare the numbers. Quote Link to comment Share on other sites More sharing options...
kicken Posted March 17, 2013 Share Posted March 17, 2013 (edited) Can anyone explain this phenomenon that I find absurd?Best guess without looking at how the class is implemented: Future instances of SplFixedArray (or subclasses there of) re-use already allocated memory. Allocating a chunk of memory takes time as the system has to search for a block big enough to fulfill the request and also update allocation tables. There may also be some paging/swapping involved that slows things down. Since you are re-using the same variable name when you assign new instances of SplFixedArray and it's subclasses the previous instance can be destructed and it's memory released. The way PHP works though is it does not actually "release" the memory, it just goes into a pool that PHP itself will manage so that future allocations for variables won't (generally) have to allocate memory from the system, resulting in faster performance. So in your first loop, each time you make a bigger and bigger SplFixedArray class PHP will have to allocate from the system enough memory to handle that request. In your second loop though, all that memory is still allocated (just unused), allowing the new class instances to just quickly grab a chunk of memory and skip the allocation process. Edited March 17, 2013 by kicken Quote Link to comment Share on other sites More sharing options...
Hall of Famer Posted March 18, 2013 Author Share Posted March 18, 2013 Best guess without looking at how the class is implemented: Future instances of SplFixedArray (or subclasses there of) re-use already allocated memory. Allocating a chunk of memory takes time as the system has to search for a block big enough to fulfill the request and also update allocation tables. There may also be some paging/swapping involved that slows things down. Since you are re-using the same variable name when you assign new instances of SplFixedArray and it's subclasses the previous instance can be destructed and it's memory released. The way PHP works though is it does not actually "release" the memory, it just goes into a pool that PHP itself will manage so that future allocations for variables won't (generally) have to allocate memory from the system, resulting in faster performance. So in your first loop, each time you make a bigger and bigger SplFixedArray class PHP will have to allocate from the system enough memory to handle that request. In your second loop though, all that memory is still allocated (just unused), allowing the new class instances to just quickly grab a chunk of memory and skip the allocation process. Interesting, thanks for your comment. I guess performance test indeed can get a bit tricky if done in an inappropriate way, I will create two different script files and run the tests separately in future then, for any types of performance tests I mean. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.