2005年08月10日

事の発端はたつをさんのくっつきカウンター

ファイルのタイムスタンプをカウンターとして使用しています。エコかつロバ
ストかな、と (どうだろう...あやしいな)。

今までよく見てなかったんだけど、先日よく見てみたら激しく面白い手法じゃないですか!

よく考えると、ファイルのタイムスタンプを使わなければ1ファイルあたり64ビットのデータも格納できる事に気づいた。
くっつきカウンターは、純粋に数値データだけを保存しているけど文字列だって8バイト分も格納できるよね
って事で、fileのatimeとmtimeにそれぞれ4バイトずつの任意の数値若しくは文字列を格納できる汎用的なストレージマネージャーを実装してみました。

File::Storage::Stat です。
使い方は、数字データだったら

use File::Storage::Stat;
my $fss = File::Storage::Stat->new({FilePath => 'filepath'});
$fss->set(100, 1000);
my($a, $b) = $fss->get;

文字列だったら
use File::Storage::Stat;
my $fss = File::Storage::Stat->new({FilePath => 'filepath', Type => 'char'});
$fss->set('保存', 'save');
my($a, $b) = $fss->get;

こんな感じで使えます。
文字列に限ってはサイズオーバーすると空文字になります。

利点としてはfile openせずにデータの格納を行うため、複数のプロセスが同時にアクセスした場合でもデータ破損は最悪免れます。
どんなタイミングであれ、何かしらのデータが残るはず。
atomicでは無いのですが、ある程度大雑把なデータを高負荷状態でread/writeする時なんかでも使えるかな?とも思います。
まさしくくっつきカウンターを作ったりする時ですよ!

って事なので、File::Storage::Statを使ったくっつきカウンターもどきを簡単に作れるモジュールも作ってみました。
File::CounterSS です。

use File::CounterSS;
my $c = File::CounterSS->new({DirPath => '/tmp/kcount', Id => 'id'});
my ($day, $total) = $c->count;

こんなコードで、本日のカウントとトータルカウントが取れます。
他にも、時間別、週別、月別、年別や、今年と去年、今週と先週などのパターンでも取れます。
ただし、過負荷状態では正確なカウントは取れないとは思います。
ロック処理も何も入っていないので、基本的には超軽量カウンターになるでしょう。

次はFile::Storage::Statの有用な使い方を考えないとな。

※注意 くっつきません。カウントの手法がもどきなだけです。

Posted by Yappo at 2005年08月10日 22:43 | TrackBack | Perl
Comments

よく判らないんですけど、atime領域とmtime領域に2次元でデータ格納できるんですよね?
今度はそういうファイルをたくさん作ったとして、両者の積での検索は簡単にできますでしょうか。
いや、
http://kokogiko.net/m/archives/000911.html
みたいなの考えてた時に、PostGISやMySQL空間拡張みたいな特殊なもの使わなくても、誰でも簡単に導入できる2次元検索できる手段があればいいな、とか考えてて、FileSystemをその候補に考えてた時もあったんで…。
結局思いつきませんでしたが…。

検索といっても、別に現実的な速さがあればいいと思うので、Fileをオープンしなくても取れるFile属性で大小を判定すれば、個人レベルの利用なら多分その範囲に収まると思うデータ1万件くらいまでなら、どちらかの属性でソートかけた上での総当りでもなんとかならないかなー、とか思ったのですが…。

案ずるより生むが…なので、今度やってみまつ。

Posted by: at 2005年08月11日 01:10

その方向なら、ファイルシステム自体を活用した方がパフォーマンスあがるかもしれません。

たとえば
http://photos.yappo.jp/map?lat=35.59479488842256&lon=139.82936583129035&z=0
への何らかのデータをおく場合(南緯北緯は考慮しません)
/foo/baz/lat/0/3/5/5/9/uniq_id
/foo/baz/lon/1/3/9/8/2/uniq_id
とファイルを2つ置いて、各uniq_idのatime,mtimeに残りの桁の値を入れ込むとかどうでしょう。
それぞれのuniq_idは同じ物を表します。

小数点2位まではディレクトリで表現してしまう事で、より早く必要なポイントを発見できるかもです。
必要な範囲のlatとlonファイルのuniq_idをかき集めて、それぞれで積をとりつつatime,mtimeを見て絞り込めば格段にdisk seekが減ると思われます。

Posted by: Yappo at 2005年08月11日 01:40

いや、まった
atime,mtimeに残りの緯度の桁を緯度経度いれるのではなくて
/foo/baz/lat/0/3/5/5/9/uniq_idのatimeに479488842
/foo/baz/lon/1/3/9/8/2/uniq_idのatimeに936583129
を入れればいいか。。。(桁数少ないのは32bit intで収めるため)
uniq_idで緯度経度の同一性は保てるし。


なんにしろ、データバックアップの手間は保証できませんがw

Posted by: Yappo at 2005年08月11日 01:45
Post a comment









Remember personal info?






コメントを投稿する前に↓の場所にnospamと入力してください。