メソッドコールキャッシュの実装その1
CallCacheInterceptor
というものを実装してみているところ。
これは、あるインスタンスのあるメソッドにある引数リストで呼び出したときに、その結果をキャッシュして次回以降は実際には呼び出さずにキャッシュした戻り値を返却する、というもの。
二次キャッシュはトラブルの元…しかし、以下のような利点も見逃せない
- ServiceもDAOも愚直に書いて、パフォーマンス上懸念のある点だけInterceptorをかましてキャッシュする
- データアクセス以外にもキャッシュできる可能性がある(バイト配列から固有のチェックサムを算出するような関数があるとして、何回もおなじ引数でコールする可能性がある場合)
二次キャッシュにおいて最大の懸念材料は次のようなもの
- 返却された型がimmutableでない場合、その参照をキャッシュしてしまうと、知らないうちに値が変わってしまう。
これについては以下のように対策できるだろう。
- コピーされた値をキャッシュし、返却時もコピー品を返すべき
- clone()ではいけない(shallow copy)
- 戻り値は Serializableでないといけないと仮定してしまう。
- その上で、「コピーされた値」は直列化した形式のまま保存する。つまり
ObjectInputStream
やObjectOutputStream
を使えばいいのではないか。
- ちなみにシリアライズによるdeep copyのパフォーマンスはなかなか素晴らしいらしい(IBMかどっかのWeb上公開文書(PDF)で見た.応答キャッシュうんぬん)