2011-10-27 8 views
4

「オブジェクト」をキーとしてオブジェクトに関するいくつかの準拠した情報を表す、適切なキャッシュキーを探しています。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));です。

EDIT 2:

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

Patternrequirementsは、これらの値のため、ハッシュこの方法の出力を変更するオブジェクトの値は以下のとおりです。私が働いているオブジェクトは、次の定義が含まれキャッシュキーに存在する必要があります。

また、同じ情報から同じIDを確実に再生成できないため、誰かがuniqid()を提案しました。これは一般的なキャッシュルックアップキーの目的を無効にします。

編集3:私は十分な文脈を与えていないと思います。

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

私は私は本当に唯一のシリアル化するために高価な呼び出しを避けるためにしようとしていると思います(と私はまた少し高価であるSHA1を、推測):ここでは、これまでのコードへのリンクがあります。私ができることは、シリアライズしているもののサイズを縮小しようとすることです...

+0

"計算上の複雑さ"の何が問題になっていますか? –

+0

実際に必要なサイクル数よりも多くのサイクルが実行されています;)現在、シリアライズは、キャッシュヒット時に、apc_fetch自体よりも時間がかかります。 – efritz

+0

したがって、そのデータ項目の値に基づいてデータ項目を取得するか、あるいはデータ項目を保存しますか?これは意味をなさない - 値を取得するには、それが何であるかを既に知っていなければなりません! – symcbean

答えて

1

結果を計算するために使用する値から単純にキーを生成する方法があります。

ここではとおおよその例です。

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

"オブジェクトの内容(プロパティ)は関数によってハッシュされておらず、内部ハンドルとハンドラテーブルポインタだけであることに注意してください。入って来る各要求は、スタック上に異なる開始点を有するかもしれない。私はオブジェクトの1つのオブジェクトハッシュを印刷していますが、それは毎回の要求で変更されます。これは要求間では機能しません。 – efritz