ログ集計とかを省メモリでできるようになったら超早いよね。

ログ集計って膨大なメモリを使う。
そのため、ログ集計中にメモリが足りなくなってswapし始めるとCPU使用率よりOSが行うswap-in outに時間をとられていく(スラッシング)。

visitors とかを動かして膨大なログを集計しながら top コマンドで見ていくと、最初はCPUを独占していた visitors プロセスが、最後のほうになると CPU使用率 50%以下ぐらいで動いているのがわかる。

ようするに、ロジックの速度というより、以下にしてメモリ消費を抑える方が全体的な高速化につながるのだ。

では、なぜログ集計にメモリを使うか。
それは、アクセス数を出すために、ユニークユーザやらアクセスされたURLやらを記録しなければいけないからだ。
これらをどう保持するかでメモリの消費量は変わってくる。

たとえば、思い切ってハッシュのみを格納するのはどうだろうか。
あるURLを 128bit (16バイト)に変換して、それだけを記録する。
普通URLは 20文字〜30文字ぐらいはあるから、運がよくて半分ぐらいになると思う。
もちろん、ハッシュなので衝突の危険性はあるが、 1 / 2^128 の確率は無視してもいいと思う。

ただ、これには、最大の問題点がある。
集計した結果、人気のURLランキングを描画したくても、データにはハッシュ値しかもっていないので、表示できないのだ。
逆にユニークアクセス集計に使うデータなど、表示する必要が無いものについてはどんどんこれを採用してハッシュにしていけばいいと思う。
もちろん、128bitハッシュではなく、 日付(4バイト YYYYMMDD) + UA(4バイトハッシュ) + IP(4バイトハッシュ) = 12バイトで十分な気がする。
結果的に、64bitハッシュ + 日にち単位なので、よほどの人気サイトでなければ衝突する確率は低いと思う。

だけど、人気URLもハッシュにしたいよね。
最近、フレームワークとかのブームのおかげでURLってどんどん長くなる傾向があるし。

それだったら、こういうのはどうだろうか。
hash 16バイト + 何個目のログファイルの何行目のURLか int * 2 = 32バイト
ハッシュと一緒にそのURLが現れたのは、何個目のログファイルの何行目かを記録する。
集計が終わったら、これらの情報を元に、ログからURLを抜き出す。
どうせ、URLなんて上位100件ぐらいしか必要にならないだろうから、これで十分な気がする。
なお、1ログファイルのサイズが 4G以下だったら、 何行目を ftell にしてもいいと思う。

32バイトも使うけど、前にも書いたけど、最近のURLはどんどん長くなってきているので、ほとんどの場合、問題ないと思う。