2011-10-27 75 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