2011-10-27 30 views
4

我正在寻找一个APC的好缓存键,它代表了一些关于对象的编译信息,使用“对象”作为键。我有一个编制方法,做这样的事情:PHP序列化替代

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; 
} 

如果不是很明显,$this->cache是一个接口与方法getset的实现。

有没有更快的方法来创建一个对于而言是唯一的密钥该属性的这个对象?我可以提取出相关的数据,但是它们仍然是数组,这与序列化中的问题相同,我首先使用了这些对象。

序列化从“正确性”的位置起作用,但看起来很浪费(输出密钥的大小和计算复杂度)。

编辑:我还想补充,如果不是很明显,我会而不是需要反序列化这个对象。我对当前缓存键的逐字代码实际上是:

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

编辑2:我正在使用该对象具有以下定义:

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

Patternrequirements是,将改变该方法的输出对象的值,因此这些值的散列必须存在于缓存键中。

另外,有人提出uniqid(),它会打败一般缓存查找键的目的,因为您无法可靠地从相同的信息中重新生成相同的ID。

编辑3:我想我没有给予足够的上下文。下面是该代码的链接至今:

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

我想我真的只是想避免昂贵的调用序列化(我猜SHA1,这也是一个有点贵)。我可以做的最好的事情是尽量减少我正在序列化的大小......

+0

“计算复杂度”有什么问题? –

+0

它比我实际需要的运行更多的周期;)当存在缓存命中时,serialize是目前比apc_fetch本身花费更多时间的唯一方法。 – efritz

+0

所以你想根据数据项的值检索数据项,或者存储数据项?这是没有意义的 - 为了检索价值,你必须已经知道它是什么! – symcbean

回答

1

一种方法可能是根据您用来计算结果的值生成密钥。

这里是一个rough的例子。

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; 
} 

由于您使用的数据数组,你仍然需要把它变成东西是有意义的关键。但是这样一来,你就只会序列化对象的一部分,而不是整个东西。看看它是如何发展的。 :)

+0

但$ obj-> x和$ obj-> y实际上是数组结构,然后需要序列化....我将编辑关于对象结构。 – efritz

+0

它出现在你的例子中$ pattern不是一个数组。无论如何,我更新了我的答案。 – Pauly

+0

这是迄今为止最好的解决方案~~ – efritz

0

事实上,很难在不知道整个系统如何工作的情况下提出任何可行的解决方案。

但是,您为什么不简单地在对象中添加一个cache_key属性和uniqid()值?

+0

然后我不能生成相同的uniqid()来从缓存中拉... – efritz

+0

是的,这就是为什么我们需要知道你的obj包含什么。 – Rifat

+0

我不明白随机和非重复性如何适合这种情况。看到我上面的编辑了解更多关于对象的信息。 – efritz

1

我会建议spl_object_hash功能,似乎完全适合您的需求。

+0

这个函数在请求之间保持一致哈希值吗? – efritz

+0

“对每个当前存在的对象都是唯一的字符串,并且对于每个对象始终是相同的。”查看PHP手册页面上的评论。 – Tom

+1

“请注意,对象的内容(属性)不是由函数散列的,而仅仅是它的内部句柄和处理程序表指针。”每个进入的请求可能在堆栈上有不同的起点。我正在打印其中一个对象的对象散列,并且在每个请求上都会发生变化。这在请求之间不起作用。 – efritz