ドキュメントを読んでみる。

以下は、OSCache を使い始めた頃にメモったものです。なんとなく捨てちゃうのももったいないし、デスクトップに置いておいてもなんなので、こっちに置いてみました。まだろくにソースに目を通していない頃の戯言なので、突っ込みどころ満載だろうなぁ。

TODO: 内容があまりにもいい加減なものは、後日検閲しようw

とりあえず、ドキュメント読んでみて、興味のあるところだけメモ。Web系はCacheの本質と関係ないので、ひとまず黙殺。

Brief Feature List

Expiry of Cache Entries - You have a huge amount of control over how cached objects expire, including pluggable RefreshPolicies if the default functionality does not meet your requirements.

RefreshPolicies の strategy を注入する感じなのかな?

Feature List
http://www.opensymphony.com/oscache/wiki/Feature%20List.html

Fast in-memory caching

The cache is keyed programmatically. This means you can calculate a cache key that works for your situation. For example an ecommerce site might use product ID as keys, or content site might use an article date and article ID combination.

これは、一見長所のような書き方をしているけど、実はKeyがStringに限定されるということですよね? ライブラリ開発者の視点から見ると理にかなってますが、ライブラリ利用者の視点からみると使いづらいかも。しかし、ディスクへのストアを考えると、hashCode() と equals() による一意性の判断はキビシそうです。なぜなら、データをgetする際にはキーの比較が必要であり、キーがオブジェクトだとディスクからデータをとってくる場合にキーオブジェクトがオンメモリに無ければいけない。Ehcacheはどうやってるんだろう?とおもい、Ehcacheのソースを見てみた。メモリ上に、キーのマップを持ってました。キーオブジェクトが巨大なら、ディスク上にデータをストアしたところでメモリを圧迫するんですね、、、。

かといって、常にキー生成プログラムを作成するのもメンドイと思うのですが、OSCacheではどのようにしているのでしょうか。キーは全てStringとして扱ってるみたいですね。キャッシュに入れる前から、Stringのキー作っとけよということですね。

オブジェクト指向にやさしいか、実装にやさしいかという二者択一の感がありますが、この場合、どちらの方法にするかを決め打ちにするのではなく、キーオブジェクトと静的なユニークキーのマッピング層を導入するという方法もアリかもしれませんね。

The cache is stored in standard scopes that any JSP programmer is familiar with (application or session). The session scope allows you to have different cached content per user. This is one unlike any other caching system we've ever seen.

(TODO:要調査)

Persistent on-disk caching

OSCache can also write the cache to disk. This provides caching across server restarts, and caching of datasets that do not fit into memory. Caching can be configured to use memory or file caching, or a combination of both.

メモリ上、ディスク上、メモリとディスク両方という3パターンのキャッシュ戦略が得られる。サーバ再起動を跨いだデータ保存も可能。

なるほど。見かけ上はEhcacheとおなじような感じです。しかし、再起動を跨いだデータ保存って、どんな場合に使うんだろう?

If you want to persist the cache to somewhere other than disk, you can plug in a custom PersistenceListener. This allows you to persist the cache to anywhere (for example to a database via JDBC or to LDAP via JNDI).

外部へのキャッシュ情報の保存が、PersistenceListener という形で抽象化されているということですね。デフォルトでは、DiskPersistenceListener と HashDiskPersistenceListener が用意されてます。

実装的にはListenerなのですが、EhcacheのようにStoreというような名前で扱ってくれると分かりやすかったかも。ちょっと残念な点です。

Ehcacheの場合は、Storeというインタフェースで概念を抽象化しているのはいいのですが、CacheManagerでべたべたな実装してますね。設定パラメータでもdiskStoreという言葉使っちゃってるし。しかし、CacheのcreateDiskStore()メソッドをオーバーライドすれば何とかなりそうな感じですね。では、Cacheを作成しているのはどこかというと、CacheManager中でConfigurationHelperを呼び出して作成している。ConfigurationHelperは、CacheManager の privateメソッドのinit()内で作成している。そしてそのinit()は、CacheManagerのコンストラクタから呼ばれている。ということで、CacheManagerを継承してやればいけそうです。しかし、ここまでする人あまりいないでしょうね。

When using both disk caching and memory caching. It is possible to limit the cache size to avoid using too much memory but let disk cache unlimited, resulting in browser style complementary disk cache. When cached objects are removed from memory, they are still on disk. If the item is needed again and it is not expired the cache file will be used. This also gives fault tolerance if the server crashes.

メモリとディスクを併用する場合、メモリ消費量を制限して、ディスク容量を無制限にすれば、ブラウザのようなディスクキャッシュができます。キャッシュされたオブジェクトがメモリ上から削除されても、ディスク上には残り、再びアクセスがあれば、期限切れになっていなければそれを参照する。サーバークラッシュ時のフォルトトレランスにもなる。

ここらへんは、Ehcacheとほぼ同じような動作のようです。

Persistence can also be switched to overflow mode using the property oscache.persistence.overflow.only. This changes the default behavior (of persisting every cache entry when there is a listener) to only persist when the memory cache capacity has been reached.

oscache.persistence.overflow.only プロパティをセットすると、メモリキャッシュが溢れた場合のみPersistenceListenerに永続化されるようです。
Ehcacheには、このオプションはなさそうですね。

Excellent Performance

Written with performance in mind.

パフォーマンス重視ですか。確かにそんな雰囲気を感じるライブラリです。

Mulitple cache requests can be handled concurrently.

当然ですね。

Only one requesting thread needs to update an expired cache entry even if multiple threads are requesting it simultaneously. Other threads can be configured to either receive the recently-expired object, or block until the cached object is updated. Similarly, when a new entry is being added to the cache, other threads requesting that entry will block until it is ready rather than run off and race to build the same object. In a high load environment this can provide enormous performance benefits.

ブロッキングとノンブロッキングの話ですね。ここら辺も概要は Ehcache と変わらず。

Automatically takes advantage of JRE 1.4 or higher if available.

1.4より前のJDKからは使えないという制約事項を利点っぽく書いているのね。EhcacheはJDK1.2でも使えるから。

Ehcacheは、クラスローダ使って、適切なクラスをロードするような仕組みになってます。

ちなみに、おいらがキャッシュ作るなら、JDK5未満はすべて切り捨てますw

Clustering support

OSCache can easily be configured to cluster across multiple boxes. This provides both scalability and failover support without any changes required in your caching code.

実装が気になるなぁ。機能はあっても品質がなぁ。本能が、「逃げろ、奴は危険だ」といっているw

Flexible Caching System

You are given a huge amount of control over the way cached objects expire. Objects can be cached indefinitely, expired once they reach a certain age, or expired based on a cron expression. Programmatic flushing is also possible, and if that is still not enough pluggable RefreshPolicies allow custom refresh strategies.

cron表記で有効期限が書けるのは、うれしいかも。フラッシュの条件をプログラム的に書けるインタフェースがあるということでしょうか。いい使い道があれば面白そうかも。

Cached objects can be grouped together however you like, allowing for powerful management of cached data. This is an extremely useful feature that is far more powerful than what other caching solutions typically offer (such as the flushing of cache keys that match a particular pattern).

なんか魅力的に見えるけど、具体的な想像が全くできない説明です。おいらがキャッシュ初心者だからですよね、きっと。(要確認)

Fully event driven! OSCache fires events for various happenings 'under the hood' such as cache entry events (adding, updating, flushing and removing) and cache accesses (hit, stale hit and miss). It is easy to add your own event handlers.

非常にただし設計思想です。Ehcacheに見習わせたいです。

Multiple caches can be created, each with their own unique configuration.

これは、Ehcache同様ですね。

Comprehensive API

For the ultimate control, OSCache can be used through its straightforward API. You can instantiate, configure and control multiple caches programmatically. It would be possible for example to create one small in-memory cache that held currency conversion rates and was updated daily at 2am, while another cache could be purely disk based and used for holding dynamically created images.

ライブラリとしてはよい設計思想だと思います。

Cache Flushing

Flushing of caches can be controlled via JSP Tags, so these functions can easily be built into your administration interface.

Ehcahceのように、JMXの口も用意してくれると助かるのだが、、、。

Cached objects can be expired in a number of ways. Objects can be told to expire once they reach a certain age, or, through the use of cron expressions, on particular dates and/or times (eg it is trivial to make an object expire every weekday at 3am). If this is not enough, you can expire objects programmatically as required, or plug in your own custom RefreshPolicy class that can dynamically decide when an object should be flushed.

デフォルトで多くの期限切れの種類を提供し、RefreshPolicyインタフェースで抽象化されているからカスタムのルールを作成するのも簡単。こうあるべきですね。

Ehcacheの場合は、Elementクラスがexpirationに関するデフォルトの情報を持っているのですが、オンメモリでも邪魔だし、シリアライズ時のデータの喰い方は最悪です。しかも、Elementはfinalクラス。Elementの概念を持ったインタフェースがあるわけでもなし。これだけで使う気をなくす人がいても、おいらは驚きません。

Entire groups of objects can be easily flushed from the cache. For example suppose you were caching product data as well as entire pages of your website. When a product was updated, you could flush not just the product object but also all the pages that contain information about that product. No more waiting for the cached objects to expire before the updated content shows up on your site!

キャッシュリージョン毎以外にも、すばらしいグルーピングの方法があるといっているのでしょうか。面白そうです。(要確認)

i18n Aware

The caching is i18n aware and supports all encodings.

国際化を使うポイントは何処なんだろう、、、。(要確認)

Solid Reputation

Comprehensive JUnit test suite that covers every aspect of OSCache, including a web stress test and various concurrent cache access scenarios.

Cloverのレポート見る限り、テストカバレッジが低すぎなのでは。普通にテストしてたら、[CACHE-296] とかあり得ないし。