ByteArrayキャッシュ

今回は、Flash内で扱うデータのキャッシュについて。

CPUバウンドな処理を行うFlashを公開するにあたり、処理を軽くする方法をいろいろ考えましたが、
シンプルに考えて、計算結果をどこかにキャッシュしておくことにしました。

少し前に書いたFlashでステレオビジョン入門を例に取ります。

例えば、ブロックマッチング法などでは動的計画法(DP)を用いて途中の計算結果を使い回しますが、
“アプリケーション”であれば、最終的な計算結果のみをどこかにキャッシュしておき、
次のリクエストからはそのキャッシュデータを引っぱってきた方が効率的です。

ここで、キャッシュを組み込んだステレオマッチングのデモを上げておきます。
“use cache” チェックボックスをonにすると、キャッシュを利用して視差マップを生成し、
チェックボックスをoffにすると、毎回ステレオマッチングの計算を行います。
パラメータを大きくしていくと違いが分かってくると思います。
Experiments in Stereo Vision

ステレオマッチングの計算では Vector ではなく ByteArray をコンテナとして使っています。
Vector の場合は、ストリームに流す前に一度シリアライズする必要がありますが、
ByteArray をコンテナとして使えば、計算後そのままシームレスに流すことができます。
シリアライズのコストが削減できるし、コードも小さくまとめられるので個人的にオススメ。

また、今回のデモの場合は最終的にデータが反映されるのは BitmapData なので、
PNGEncoder などを使ってエンコード処理を入れる必要もありません。
画像ヘッダなどはこの場合ノイズになるし、エンコードのコストも発生するのでムダかと。
また、ByteArray のみのやりとりなので、URLLoader + Loader で通信処理を書く必要もなく、
URLStream にそのままデータを流し込んでやればOK。
Loader を起動するよりも高速かつオブジェクトサイズも小さいです。

キーにはURIを利用し、リソース指向でキャッシュの仕組みを作ります。
GETでリクエストされたらFlash側にデータを返し、POSTならストレージにデータを保存するだけ。
URIは、例えばステレオマッチング処理のパラメータを使って組み立てます。
http://foo.com/stereovison/{画像ファイル名}/{探索ウィンドウサイズ}/{探索距離}/
みたいな感じでURIを一意に決めておき、パスをキャッシュのキーに使います。

・データキャッシュ用クライアントの例

サーバ側では .htaccess でリクエストをキャッシュ処理を行うスクリプトに集め、
URIのパスを key、リクエストデータを value にしてストレージに突っこむだけです。

・.htaccess 例 (mod_rewrite)

上記のような .htaccess ファイルをベースURIのディレクトリに置いてください。
つまり、
https://rest-term.com/contents/flex/stereovision/tsukuba_stereopair/5/10
などでアクセスされた場合、
https://rest-term.com/contents/flex/stereovision/bmp_cache.rb
にリクエストを集めます。そしてキャッシュのキーには、

/contents/flex/stereovison/tsukuba_stereopair/5/10

を利用することになります。

サーバ側の処理は各々好きな言語で。
簡単なWeb APIを作ればいいので特につまづく所もないかと思います。
AMF-RPCサービスを作ってやりとりする方法でもいいですが、
なんにせよ退屈な処理なので、工数が少なくて済む方法を選ぶといいです。

・サーバサイド 擬似コード :Sinatra ライク

サーバ側でクライアントのチェックはしておいてください。
あと、Rubyとかムリ!でもPHPならできるよ!という人は、
Limonade (is a PHP micro framework ~) というのもありますよ。
(「FlasherのためのLimonade入門」みたいな記事があると多くの人が幸せになれる、かも)

キャッシュバックエンド

計算結果をキャッシュしておくストレージには memcached と SQLite を試しました。

1. memcached (memcached 1.4.5, libmemcached 0.40)
画像データ部のみ格納された ByteArray のやりとりは特に問題なし。
ByteArray.compress() で圧縮したデータでも大丈夫でした。
でも共用のレンタルサーバだと memcached が使えない。。

※ “問題なし”というのは BitmapData.setPixels() でエラーが発生しないことを指します

2. SQLite (SQLite 3.7.3, ファイルDB)
SQLite を Key-Value Store 的に利用。
これも ByteArray のやりとりに支障はありませんでした。
memcached より速度面ではさすがに劣りますが、どの共用レンタルサーバでも大体使えます。

ステレオマッチングのデモは、キャッシュ用ストレージに SQLite を選択しました。
Flash Developer の方々はサーバサイドの言語にPHPを選ぶ人が多い(?みたいなので、
PEARの Cache_Lite とかで試してみてもいいかもしれません。

今回のようなステレオマッチング処理では、探索範囲などのパラメータにも大きく依存しますが、
256×192 pixel の画像でもマッチングの計算に数秒はかかってしまうので、
ファイル, ネットワークI/Oにかかる時間はほぼ無視できると考えていいと思います。
ByteArray.compress() にかかるコストも予想していたより小さくて安心しました。
キャッシュは行わずに、Alchemy を使ってC言語で計算させるパターンも試しましたが、
CPUに負荷をかけることには変わりない上に、パラメータ依存なので速度にムラが出ます。

また、データを一時的にキャッシュするのではなく、サーバ側で保存/管理するのが目的であれば、
SQLite などのファイル型ストレージを選択すればもちろん永続化できます。
例えば、ペイント系Flashで描画した BitmapData をサーバに保存する用途などに応用できるかと。

まぁ、
そもそもActionScriptが速ければキャッシュなんてする必要ないんですけど。。

・関連記事
Flashでステレオビジョン入門

あわせて読む:

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です