efritz
efritz

Reputation: 5203

PHP Serialization Alternative

I'm looking for a good cache key for APC that represents some complied information about an object, using the "object" as the key. I have a compilation method that does something like this:

function compile(Obj $obj)
{
    if ($this->cache)
    {
        $cachekey = serialize($obj);

        if ($data = $this->cache->get($obj))
        {
            return $data
        }
    }

    // compute result here

    if ($this->cache)
    {
        $this->cache->set($cachekey, $result);
    }

    return $result;
}

If it's not obvious, $this->cache is an implementation of an interface with the methods get and set.

Is there a quicker alternative to creating a key that's unique to some of the properties of this object? I can extract the relevant bits out, but then they are still arrays, which would have the same problem with serialization that I had with the objects in the first place.

Serialize works, from a "correctness" position, but it seems wasteful (both in size of outputted key, and in computational complexity).

EDIT: I would also like to add, if it's not obvious, that I will not be needing to unserialize this object. My verbatim code for the current cache key is actually:

$cachekey = 'compile.' . sha1(serialize($obj));.

EDIT 2: The object I'm working with has the following definition:

class Route
{
    protected $pattern;
    protected $defaults = array();
    protected $requirements = array();
}

Pattern and requirements are the values of the object that will change the output of this method, therefore a hash of these values must be present in the cache key.

Also, someone suggested uniqid(), which would defeat the purpose of a general cache lookup key, as you could not reliably regenerate the same ID from the same information.

EDIT 3: I guess I'm not giving enough context. Here's a link to the code so far:

https://github.com/efritz/minuet/blob/master/src/Minuet/Routing/Router.php#L160

I guess I'm really only trying to avoid expensive calls to serialize (and I guess sha1, which is also a bit expensive). It's possible that the best I can do is try to reduce the size of what I'm serializing...

Upvotes: 4

Views: 3312

Answers (3)

Tom
Tom

Reputation: 1701

I would suggest the spl_object_hash function that seems to fit perfectly for your needs.

Upvotes: 1

Pauly
Pauly

Reputation: 299

One way to do it might be to generate a key based simply from the values you use to compute the result..

Here is a rough example.

function compile(Obj $obj)
{
    if ($this->cache)
    {
        $cachekey = 'Obj-result-' . sha1($obj->pattern . '-' . serialize($obj->requirements));
        // You could even try print_r($obj->requirements, true)
        // or even json_encode($obj->requirements)
        // or implode('-', $obj->requirements)
        // Can't say for sure which is slowest, or fastest.
        if ($data = $this->cache->get($cachekey))
        {
            return $data
        }
    }

    // compute result here
    $result = $obj->x + $obj->y; // irrelevant, and from original answer.

    if ($this->cache)
    {
        $this->cache->set($cachekey, $result);
    }

    return $result;
}

Since you use an array of data, you'd still need to turn it into something that makes sense as a key.. However this way you're now only serializing a part of the object, rather then the whole thing. See how it goes. :)

Upvotes: 1

Rifat
Rifat

Reputation: 7748

Actually it is very hard to suggest any viable solution without knowing how the whole system works.

But, Why don't you just simply add a cache_key property with a uniqid() value in your object?

Upvotes: 0

Related Questions