6

Example:

$arr = array();

for($i = 5; $i < 300000; $i++)
    $arr[$i] = 'foo';

apc_store('data', $arr);

It takes like 15 seconds. To get the data it takes around 0.7s.

But if I serialize the data with php and store it like that with apc_store('data', serialize($arr)); it takes only 1 second.

To get the serialized data and then unserialize it, it takes a little more than 0.6s

Why is APC so slow?

Alex
  • 66,732
  • 177
  • 439
  • 641
  • `apc_store()` triggers the `__sleep()` function, right? If that's true, then the [function is run prior to serialization](http://php.net/manual/en/oop4.magic-functions.php). Maybe that cuts down on the efficiency. It also sounds like `apc_store()` overwrites existing entries... granted I'm still learning PHP so I could be way off. – Rob Oct 14 '12 at 23:00
  • @MikeDtrick: APC doesn't use serialization. It just copies entire `zval` structure (on C level). – Crozin Oct 14 '12 at 23:02
  • @Crozin Wait, what? Is this in regards to `apc_store()` triggering `__sleep()`? Is that incorrect? – Rob Oct 14 '12 at 23:07
  • @MikeDtrick Sorry, my mistake. APC *triggers* `__sleep()` method. – Crozin Oct 14 '12 at 23:20
  • @Alex Could you check your code on different platform? On my PC (i3, Windows 7 x64 - not the best env. for APC) version without serialization works ~30% **faster**. – Crozin Oct 14 '12 at 23:21
  • 1
    APC does serialize whatever userdata it stores: in the case of objects, this triggers __sleep().... pre-serializing before calling apc_store will create a string to be stored; and APC will reserialize it. Using the igbinary extension can improve performance because it's a more efficient serialization method – Mark Baker Oct 14 '12 at 23:22

1 Answers1

2

apc_sma_info() provides one interesting information which, maybe, could explain why happens.

Executing apc_store() with a non-serialized data produces to me, in block_lists index the following values:

Array
(
    [0] => Array
        (
            [size] => 608
            [offset] => 33152
        )

    [1] => Array
        (
            [size] => 5589032
            [offset] => 11211992
        )

    [2] => Array
        (
            [size] => 2175976
            [offset] => 31378408
        )
)

While serializing them manually produces:

Array
    (
        [0] => Array
            (
                [size] => 11178232
                [offset] => 33760
            )

        [1] => Array
            (
                [size] => 1210040
                [offset] => 16801024
            )

        [2] => Array
            (
                [size] => 15542104
                [offset] => 18012280
            )
    )

It's curious, but seems that with a manual serialization, APC splits the first and last pieces of data in a larger blocks, doing a better disposition of content.

Doesn't seem to be something trivial because I ran this test a couple times and I got similar results everytime.

BenMorel
  • 34,448
  • 50
  • 182
  • 322