Jump to content

A weird Phenomenon: Subclasses of SplFixedArray is even faster than SplFixedArray itself?


Recommended Posts

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: 100
Array(): 3.09944152832E-5
SplArray(): 2.28881835938E-5

NumericArray(): 1.19209289551E-5

 

Testing size: 3200
Array(): 0.000507116317749
SplArray(): 0.000546216964722
NumericArray(): 0.000308036804199

 

Testing size: 102400
Array(): 0.0228500366211
SplArray(): 0.0149321556091
NumericArray(): 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 by Hall of Famer

Change the order of SplFixedArray and NumericArray in your test. See what happens. :shy:

 

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?

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 by kicken

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.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.