« est! est! est!な日記 |Main| LL魂準備日記 »

« なんか日記 | Django | »

« Re: 小町算 | Python | LL魂準備日記 »

Djangoのキャッシュはすごいな日記

Djangoテンプレートで特定のメソッドを引数付きで呼びたいという話。 {% apply func arg1 arg2 %}という書き方をするとfuncがcallableであるときに 自動的にcallされてしまうので{% apply "func" arg1 arg2 %}にしなければいけない、 とこの前書いた。

しかしこの方法ではfuncが文字列であるので、 下のような書き方をサポートする場合、 evalの名前空間にテンプレートのレンダリングに 使われているコンテキストを渡す必要がでてきてややこしいことになる。

{% for comment in comments %}
  {% apply "comment.get_something" user %}
{% endfor %}

ふと気がついたのだけど、関数を返す0引数関数を作ればいいだけじゃないかと。 comment.get_somethingが引数を1個とる関数を返すのなら {% apply comment.get_something user %}でも問題ないのでは。


= ユニコードブランチ、すごいな。 セッションIDまでユニコードか…。あたりまえか…。 「全てがUになる。」(ぇ)
= Star Alliance Japan - 運賃案内。 世界一周チケット(1年間有効)。 途中でイギリスに1ヶ月滞在して大英博物館に入り浸りとかも可能。 結婚して子供ができるとこういうことはできなくなるだろうから、 やるのは今のうちなのか。

一周で100万という話だったのだけど、エコノミーならもっと安いね。 もちろん飛行機代なんかよりも宿泊費の方が高いことをお忘れなく。 1年間ホテル暮らしなわけだもんなぁ。


= なんか昨日も今日も9時頃になると眠くなる。 帰ろうか…。
= 5時に目が覚めると、反射的に二度寝をしてしまうのをなんとかせねば。 せっかく5時に起きたのに。
= 世界一周は飛行機代よりも ホテル代が高いという話だけど、 日本のホテルが高いと仮定してカプセルホテル4000円×365日=150万くらい。 んー。高いなー。

世界一周という言葉には萌えるけども、 細かく何度か行く方がいいのかもなぁ。 冬の地中海と夏の地中海は別物だしな。


= b-mobile、あと80日くらい残っている。 金額で言えば2~3万円分は残っている。 でも遅い。
= 紙粘土で作った魚眼レンズとトルソーは 乾いたらでこぼこになった。 紙粘土は水気がなくなると変形するから、 こういうのはパテとかを使うらしい。
= 暑いなー。 冷房つけるしかないのかな。

シャワーを浴びたら涼しく感じるようになった。 表皮の血管が冷えて収縮しているせいで 熱を捨てられず、こもったように暑くなっていたのだろう。

今まで眠くなかったのだけど、熱が捨てられ始めると眠く感じる。


= スタイルシートはまず最初にresetしないといけない。

あとresetしたせいでDIVのマージンがなくなってツメツメになっているのを、 テンプレートいじって修正しなきゃと思っていたけど、 普通にスタイルシートにdev { margin: ... }とか書けばいいだけだと気づいた。

resetしたせいで文字がすごく小さくなったのでfont-size: 16pxとかやったせいで、 フォントサイズの変更ができなくなってしまったらしい。

月曜日はその2点のスタイルシートを修正する。 あと最近もっさり感の出てきた言語一覧のページにキャッシュ機能をつけよう。 Django のキャッシュフレームワーク : Django オンラインドキュメント和訳

Djangoのキャッシュ機能、最初ものすごく斜め読みをして 「ページ単位とかサイト単位でキャッシュしたいんじゃなくて、 統計情報の計算結果だけどこかにためておきたいだけなんだけどなぁ」 なんて考えていたけど、 きちんと読んでみたら「低水準API」って章にちゃんとそれの方法が書いてあった。 低水準っていうからめんどくさいかと思いきや:

>>> from django.core.cache import cache
>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'
うわー。簡単すぎる。30ってのが秒数らしいので状況に応じて86000とかすればいい。

で、明示的にdeleteすることもできる。 時間のかかる統計計算の結果をキャッシュするために、 「えーと、結果を保存するテーブルを作って、変更が起きるような処理のところで再計算してテーブルに入れて…」 なんて考えていたけどそんなことは不要。 いま統計処理をやっているところで cache.get('my_key')してNoneの時だけ再計算するようにし、 統計結果が変化するような処理をしたときには単にdeleteすればいい。

投票に関する統計結果は、投票と同時に更新すると他の情報とのかねあいで 「誰がどれにどういう投票をしたか」が透けて見えてしまうケースがあるので、 どうしようかと悩んだりもしていたけども、これも簡単。 投票時にdeleteしないでキャッシュの生存時間を5分とかにしておけばいい。

バックエンドをmemcachedにしたりデータベースにしたり、ファイルにしたり、など色々選択肢があるみたい。 新しいサーバが来たらmemcachedとか入れて試してみようっと。


= PHSでどう書くorgを見るのが辛いので、 画像やCSSやJSをローカルにキャッシュさせようと思う。 CSSやJSはたまに変わるけども、 画像は変わらないので簡単。 で、ちゃんと期待したとおりに動いているかとか見るためには、 リクエストとはレスポンスヘッダとか見れるようにしたいなぁ。 と思って調べたら ネットランダム - これであなたもはまちちゃん!! 「リクエストとレスポンスヘッダをいつも目に入るようにするにはFirefox拡張のLiveHTTPHeadersを使うといいよ!」 だって。

http://ja.doukaku.org/

GET / HTTP/1.1
Host: ja.doukaku.org
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.5) Gecko/20070713 Firefox/2.0.0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: (たぶん載せない方がいいんだと思うんで割愛)

HTTP/1.x 200 OK
Date: Sat, 28 Jul 2007 17:49:49 GMT
Server: Apache/2.2.3 (Fedora)
Vary: Accept-Language,Cookie
Content-Language: ja
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
q=0.5って何だろう…。

ヘッダに「Accept-Language: ja,en-us;q=0.7,en;q=0.3」って入っているから日本語版が表示されるんだな。 たぶんjaをAcceptしなければ英語版が出るんだろう。 英訳適当なところがあるから直さないとなぁ…。

「Vary: Accept-Language,Cookie」で、間のプロクシとかがキャッシュするときに 他人のページが出たりしないようにしているって何かに書いてあった。

「Connection: close」 って、closeしてもいいんだろうか。せっかく「Connection: keep-alive」なのに??

http://ja.doukaku.org/static/style/style.css

GET /static/style/style.css HTTP/1.1
(略)
If-Modified-Since: Fri, 27 Jul 2007 09:40:00 GMT

HTTP/1.x 304 Not Modified
Date: Sat, 28 Jul 2007 17:49:52 GMT
Server: Apache/2.2.3 (Fedora)
Connection: close
Vary: Accept-Language,Cookie
ほー。 ここにExpiresを返すようにすれば期限切れまではローカルのキャッシュを使うようになるんだな。

もしかすると ビュー単位のキャッシュ で/static/images以下へのアクセスを@cache_page(86400 * 365)とかやるだけで終了かも。

開発環境をノートに入れてくるの忘れたので実際にやるのは月曜日。


= 日曜の朝。 せっかくレスポンスヘッダが見られるようになったのだから、 画像がいっぱいあってしかも負荷対策もきちんとやってそうなサイトを見る。 ミクシィ。
HTTP/1.x 200 OK
Server: Apache
Last-Modified: Fri, 15 Dec 2006 07:17:47 GMT
Etag: "2e0828-9a-6dc6fcc0"
Accept-Ranges: bytes
Content-Length: 154
Content-Type: image/gif
X-Cache-Lookup: HIT from banta.mixi.jp:80
Cache-Control: max-age=520596
Expires: Sat, 04 Aug 2007 01:45:21 GMT
Date: Sun, 29 Jul 2007 01:08:45 GMT
Connection: keep-alive
そうだよなぁ、やっぱり「Connection: keep-alive」って返ってないとだめだよなぁ。 どう書くorgはなんでcloseを返してるんだろうなぁ。 「Expires: Sat, 04 Aug 2007 01:45:21 GMT」で5日後を返している。

「X-Cache-Lookup: HIT from banta.mixi.jp:80」とか 「Cache-Control: max-age=520596」 とか「Etag: "2e0828-9a-6dc6fcc0"」は何だろうなぁ。

Expiresのネタもと: Kazuho@Cybozu Labs: キャッシュの上手な使い方。 とりあえず画像と全てのページで読み込まれているCSS、JSを1年先にExpiresするような設定にすれば だいぶ軽くなるんではないかと思っている。 ファイル名変えるのも簡単だしねぇ。 昔の「たくさんのHTMLにコピペで同じ内容がたくさん」なんて時代と違って Djangoテンプレートがツリー状の継承構造になっているから、 根本を1カ所書き換えるだけでいい。 ファイルの名前に書き方の規則をあらかじめ決めておけば(例えばjquery-0.0.0.jsとか)

(?P<filename>.*?)(-\d+(\.\d+)*)?\.(?P<ext>\w+)
ってな感じで機械的にバージョン番号を捨てたりできるから 実際のファイルのファイル名を書き換える必要すらない。

Cache-Control: max-ageとSquid : blog.nomadscafe.jp

トラックバック(Trackback)

Trackback URL: http://www.nishiohirokazu.org/mt/mt-tb.cgi/625

ご意見・ご感想をお送りください(フィードバック)

(フィードバックはメールで送信され、基本的に表示されませんが、内容によっては公開させていただくこともございます。ご了承ください。Your comment doesn't appear the page immediately. If the comment has value to other people, it will be put on the page or subsequent entries. Thank you.)

上の情報は、いずれも未記入でかまいません。 All of above questions are optional.