サポートに連絡

メールでご返信します。通常は2日以内です。

不正利用を防ぐため、Google reCAPTCHA がこの送信を確認します。その際データが Google に送られます。スクリプトはこのフォームを開いたときにだけ読み込まれます。

← すべての記事

キャッシュが逆向きに育つとき

このサービスのキャッシュ用フォルダに、小さなファイルが四つある。いちばん大きいもので 35 バイト。合わせてカウンター番号を三つ持っていて、カウンターへの要求があるたびに読まれる。

これがあるのは、計数の道筋がデータベースに四つの問いを立てずに済ませるためだ。どれも答えはほぼいつも「いいえ」である。このカウンターは持ち主自身の訪問を除くか。外向きのクリックを数えるか。サイト内の経路を追うか。自分で読み直すか。99 % を超えるカウンターでは答えはすべていいえで、「はい」の少数の番号だけを収めたファイルは、索引付きの問い合わせ四本より安く済む。

安く済む。そしてこれは、ひっくり返る種類の安さでもある。

2 10 100 1,000 10,000 100,000 動いている 2,218 すべて: 0.43 ミリ秒 ファイル: 番号 3 個で 0.02 ミリ秒、100,000 個で 21.4 ミリ秒 索引付きの問い合わせ一本: どの大きさでも 0.16 ミリ秒

何を測ったか

同じ問い —「このカウンターは一覧に載っているか」— を二通りで、六つの一覧の長さで立てた。ファイルの道: 読み込み、JSON を解き、番号を探す。データベースの道: 索引付きの列に対する用意済みの問い合わせ一本。それぞれ二千回、五巡、中央値を取った。

今の大きさではファイルが八倍速い。0.0202 ミリ秒に対して 0.1630 ミリ秒。番号が千になると横並びになる。一万でファイルは十二倍、十万では 135 倍かかる。そのころには 578 キロバイトを毎回読んで解かねばならないからだ。

データベースの線は動かない。二行でも 0.16 ミリ秒、十万行でも 0.16 ミリ秒。索引とはそのためのもので、この退屈な線の裏にどれだけの仕事が隠れているかは、すぐ忘れられる。

居心地の悪いところ

交点は番号 100 個と 1,000 個のあいだにある。このサービスには、この三十日で通信のあったカウンターが 2,218 ある。

つまり、もしこの除外機能が成功したら — カウンターを持つ全員が「自分の訪問は数えない」を入れたら — ファイルは 2,218 個の番号を抱え、11 キロバイトになり、一回あたり 0.02 ミリ秒ではなく 0.43 ミリ秒かかる。昨日の 18,423 回で計算すると、一日に八秒ぶんの仕事だ。三秒で済んだはずの問い合わせを避けるために。

この最適化は、その機能がいちばん使われていないときにいちばん速い。遅い問い合わせのように負荷とともにじわじわ悪くなるのではない。普及とともに悪くなる。そして普及は、誰も見張っていない唯一の軸である。普及が伸びるのは良い知らせのはずだからだ。

それでも残してある理由

今は正しいからだ。そして「今は正しい」は何かの理由であってよい。いつ正しくなくなるかを誰かが書き留めてある限りは。

三つのファイルに三つの番号。代わりの手より八倍安く、しかもこの機械では計数の道筋だけが速くあらねばならない。いま、それが打ち負かしている問い合わせに置き換えるのは、仮定を根拠に悪いほうの仕組みを選ぶことだ。

足りないのは仕掛け線であって、作り直しではない。ファイルはどのみちデータベースから書かれる。設定を変える側のコードが書く。まさにそこが、一覧が数百件を超えたと気づき、そう言うべき場所である。上限が書いてあるキャッシュは決定だ。上限のないキャッシュは、誰も同意していない賭けである。

一般化した形

これはファイルにキャッシュを置くことへの反論ではない。自分のキャッシュがどちらへ育つかを知っておくべきだ、という話である。

たいていのキャッシュは負荷の下で良くなる。要求が増え、当たりが増え、比率が良くなる。これは別の種類だ。要求あたりの費用は、抱えている量で決まる。そして抱えている量は、サービスが後押ししたいものと一緒に増える。読むたびに全件ぶんを払う。いま数えられている訪問者と何の関係もない 2,215 件も含めて。

メモリやファイルに置く索引表に立てるべき問いは「どれだけ速いか」ではなく「何がそれを大きくし、それがうまくいったら何が起きるか」だ。答えが「遅くなる」なら、大きさの上限はコードに属する。ファイルを書く場所の隣に、それを作る日に。

広告