9 時間 manufacture。 若年労働者層として資本家階級に搾取されてきますた。
※日本語訳
日雇いバイトに行って電動歯ブラシの柄を磨いたりキャップの袋をつめたりしてきました。 拘束時間が長いくせに時給が 800 円を切っているのは横暴だと思います。
今週後半は中間レポートと緊急バイトで追われてて、 日記書く暇もありゃしない。
そして明日は Wiki ばな V2 飲み会に行くのだー。
嬉しいことは嬉しいんだが、本当にいいのか。 ていうか、また途中で方向転換するんじゃないだろうなあ。
何はともあれ、本当にオープンソース化されたら 今度こそ (Sun の気が変わる前に) 速攻で入手して CD-R に焼く。
(22:49)
今日は参った。
最初 Wiki ばなの会場に行ったんだけども、分単位の行き違いになって合流できず。 しかも飲み会の店とか連絡先とか地図とかを全部書いた紙を家に忘れて来たことにようやく気付く。 確か目黒駅で待ち合わせだったような気がしたので行ってみたが、こっちでも行き違いになる。 西口と東口を行ったり来たりしていたのが失敗だったようだ。
もしかしたら Wiki ばなのサイトに店の名前が載ってたかなーと思い 携帯からアクセスを試みるも通常の HTML が扱えず敗北。
この時点で家に帰って日記に「ふて寝します」って書いて寝ようかとも思ったんだけど、 もうちょっと粘ってみた。 飲み会の店の URL がぐるなびだったことと、 「〜そば」という店名だったことは覚えていたので、 インターネット喫茶に入ってぐるなびにアクセスし、 目黒周辺で検索してみる。 「北前そば」というのがあったので、これかー! と思って喜んだが、 それは北前そば五反田店であった。
いやねぇ。まさか北前そば目黒店というのが別にあるとは思わなかったよ。 同じインターネット喫茶に二回入って二回とも 10 分しないで出ちまった。 しかも探してた店って、入ってたインターネット喫茶を出て目の前でやんの。
長い冒険の末、ようやく辿りついた Wiki ばな飲み会。 これだけ苦労すると喜びもひとしおです。 世の中、問題はどれだけ努力したかだよ!
嘘です。すんなり着いたほうがいいに決まってます。
早くも眠くなってきました。 寝てしまう前にいくつか話題をピックアップしておきます。
いちばん印象に残ったのは、増井さんに聞いた、時間を意識したインターフェイスの話かな。 一言で言うと、リソースは十分増加しているんだからもっとメタデータを蓄積して 楽しい使いかたをしようじゃないか、という話です。 「アクセスされていないと廃れていくページ」の話も聞きました。 「これをずっと使っているとそうじゃないほうがおかしく思えてくる」とか。
…… Wiki じゃないじゃん。
そういえば 「Ruby が (Perlに比べて) 遅いから……」という言い分 (言い訳) を よく聞くんですが、それはかなり疑わしいと思います。 体感でわかるくらい遅いのなら、 ほとんどの場合アルゴリズムとか設計がまずいのが原因です。
しまった! せっかくゆきちさんが来ていたんなら Wiki 文法標準化の話を聞けばよかったな。 今日は人数が多かったうえに飲み会しか出てないから、 名前すら知らない人もかなりたくさん……。
あ、そうだ、飲み会にしか参加しないくせに、 わたしもポジションペーパーなるものを書きました。 実際に使うわけじゃないし、 実装よりは使いかたに興味のある人が多そうだったので、 あえて逆をついて実装の話題にしてます。 我ながら実に天邪鬼な発想だなあ。
うむ。総じて今回の飲み会も楽しかったです。 今回はいろんな人に会えたのも収穫でした。 やっぱり遅れたのは痛かった。
(02:52)
正直どーしよーかなーって思ったけど、 どうせ安いんだからと後悔しないように申し込んでおいた。
しかし参加費は学生 1500 円なのに郵送費が 600 円って、 比率としてどうなのよ。
(21:18)
http://d.hatena.ne.jp/wakatono/20040601#p7
Subversion、新しいデータベースを実装しているんですね。 ちょっと試したい気分になってきました。
(01:07)
Just another Ruby Porter,より
http://www.st.ryukoku.ac.jp/~kjm/security/memo/2004/06.html#20040609_CVS
CVS pserver は果てしなくやばそうなので、 対策が済むまで cvs.loveruby.net を停止します。
なお BitChannel (Wikiサイトのほう) はローカル CVS なので関係ありません。
(02:03)
(ツッコミに書こうと思ったけど長すぎたので移動)
そうか……もしBitChannelを分散管理できるようにしたら情報テロが (以下略)
ていうか CVS じゃ分散ってありえないよな。 BitKeeper ならできるかもしれない。 レポジトリを分散して適当にマージ。 適当にマージはできないだろ (一人ツッコミ) マージできそうなとこだけマージ? 全ドキュメントに世界共通の ID を付けて、同じ ID を 持つドキュメント間でだけマージするか。 知らないうちに別のホストでアップデートされていくドキュメント。 いいなあ。萌えるなあ。
世界共通の ID と言えば GUID か? つーか MD5 checksum 程度でもよいかもしれない ……いやそれじゃやっぱりだめだよな変更されていくんだから。 いっそのことタイトルを使えばいいんだろうか。 かなりの唯一性が要求されるが、そのくらいは必要か?
あとはどういう経路でプッシュ (or プル) するかだ。 BitChannel が稼働しているホストを探索するにはどうするか。 うーむこのへん勉強不足だな。ネームサービスみたいなものを どこかに置いとくしか思いつかん。DNS だってルートサーバの IP アドレスは覚えさせとくわけだし、なんらかの形で 一段目が必要になりそうな気がする。
どの情報をプッシュするか。全部プッシュしても面白くないな。 均一になるのを目指してるわけじゃない。 ……既に手元にある情報を元に、似ている情報を集めるのはどうか。 あー、でもそれだと似たような情報ばかりを集める結果になりそうだな。 手元のプールからランダムでキーワードを選べばちょっとは分散されるだろうか。
ときにはすごく意外な情報も入ってきたほうがいいなあ。 Winny みたいに情報を仲介する過程でキャッシュすることにして、 そのキャッシュからもランダムでピックアップするか。
そういうのは人の日記を適当に巡回してれば十分じゃないかって気がしてきた。
Wikiで日記を書く人がいるけど、 日記が流通して勝手に続きが書き加えられたら面白いよな。 漂流する交換日記? いや交換してないから漂流日記……だと漂流教室のようだ。
同じ ID を持つドキュメントであっても、 プログラム外から破壊する意図を持って変更されていた場合にはどうするか。 いやその前にどうやってチェックするか。 データは追記のみ valid な形式とし、 履歴部分の MD5 sum をつねに併記すればよいか。 未知のブランチがあった場合はどうするか。
マージに失敗した場合はどうするか。 ……その前に、どんなときに失敗するのか。 常に分岐しつつ追加されていくとすると、 マージは起こらないのではないだろうか。 ……ユーザが意図的に指定すれば発生するか。 main trunk へ収束させる圧力が必要かもしれないな。
そーか。履歴を束ねたときの MD5 sum があれば、それが ID になりうる。 いや違う、履歴を束ねた全体の同一性が保証できない。 やはり別にドキュメント ID は必要だ。
実装の問題はマージか。ネットワーク関係はさして問題ない。 下手すると BitKeeper 以上のレベルを要求されるか?
なんでこんなことを考えているのだろう……
そうか URL だ! URL があった! URL は唯一のキーとして使えるかもしれない!
と、一瞬喜んだけどタイトルとたいして差がなさげ。 原作者を明示する意味はあるやもしれない。 偽造も簡単なのでむしろ危ういかもしれない。
むー。普段ウェブで読むドキュメントの署名が (それなりに) 信用できるのはなぜだろう。 それは URL がなんらかの形で物理ホストと連結されているからではなかろうか。 URL がホストと切り離されるとその瞬間に URL は単なる情報と化し価値が無くなる。 例えるならば、評価して値の得られる変数には意味があるが、 評価できない (未定義の) 変数は意味がない。ということかな。
他人のシステムにあるドキュメントは (クラックしないかぎり) 改竄しようがない。 変更を加えたら必ず自分のホスト (のBitChannelノード) で公開することにすれば、全ての変更を検証できる。
……いや、分散ドキュメント側の URL が改竄されたらやっぱりだめだ。 やっぱそのために MD5 sum は付けとかなきゃ。
あー、違う違う。 これでは誰がその変更を行ったかということしか検証できないんだ。
そういえば arch は BitKeeper と似たシステムだったっけ? 見てみよっと。
(03:53)
■ ささだ [こんびにで買ったら郵送費(多分)なかったすよ。]
■ 青木 [なにーい! コンビニで買えたのか……そっちにすればよかった。]
■
smbd [席代:1500円、郵送料:600円はあまりにもばかばかしかったので
電子チケットピアで買って、ファミマで発券するようにしました
これなら発券量:100円で済みます。
でも、電子チケットピアで買う方法がわかりにくいのなんの…
10分くらいサイトをうろうろ探し回りましたよ(苦笑]
■
かずひこ [cvs-1.11.17, cvs-1.12.9 出ました
https://ccvs.cvshome.org/servlets/NewsItemView?newsItemID=110
https://ccvs.cvshome.org/servlets/NewsItemView?newsItemID=111]
■ nobsun [lightenning talk とかでしゃべると、講演者あつかいになるかも]
■
青木 [そういえば昔ファミマでバイトしてたときも
ぴあの操作がよくわからないって人がよくいました。]
■ 青木 [喋るのはちょっと……]
BitChannel 0.2.0 および CVS HEAD に XSS 脆弱性が発見されました。 旧バージョンのユーザは早急に 0.2.1 または最新版にアップデートしてください。
なお、CVS は停止中のため、 とりあえず今日時点のスナップショットを作っておきました。
とりあえず手作業で〜という場合は、 template/preview.rhtml と template/edit.rhtml に一ヶ所ずつある body() を escape_html(body()) に直してください。 テンプレートは毎回読み直すので FCGI や mod_ruby で動かしたままでも問題ありません。
(19:21)
cvs.loveruby.net の稼働を再開しました。 停止中は御不便をおかけしました。
突然ですが、こんな機構を導入してみました。
read/write マスターレポジトリ ←―――― 別系統のCVSサーバ ←―――――― LAN only | | ミラー +-------------------------------------------------------+ | | chroot jail | | ↓ read only | | ミラーレポジトリ ←―――― 2401ポートのpserver ←――|――― Internet +-------------------------------------------------------+
ミラーは cron で 15 分ごとに Ruby スクリプトをまわしてます。 でも、書いた後になって cvsup を使えばよかったと気付きました。 もう書いちゃったからこれでいいや……。
と、いうことなので、しばらくは何か変なことが起こるかもしれません。 問題があったら遠慮なくつっこんでください。
しかし、15 分ごとにレポジトリを全部なめるのはいくらなんでも無駄すぎる。 commitinfo あたりで、なんとか……
(01:59)
■ shugo [そのRubyスクリプトってCVSのロックとかも見てるんですか?]
■
青木 [akrさんのruby-cvsを使っているので、たぶん大丈夫です。
「たぶん」と言うのは、検証テストが難しいために、
ロックまわりをテストしていないからです。ruby-cvs が
正しく実装されていても使いかたが間違っていたらそれ
までですし。
:pserver:anonymous@cvs.loveruby.net:/src co cvstools
すると mirror-repository.rb というのがそうです。]
■
shugo [なるほど。
ちなみに自分はcvsupでいったんローカルにコピーしてからssh経由でrsyncしようと思ってました。
たんにcvsupでも安全なのかもしれませんが...。]
今日は毎月恒例の RHG 読書会でした。 今回は難所の状態付きスキャナだったのですが、 またしても新たな Ruby の心の^H^H闇が発見されました。 それは……多重代入の右辺に来るかどうかで解釈が変わる式がある。
m (a), b { nil } x, y = m (a), b { nil }
前者は m((a), b{nil}) なんですが、 後者は m(a) と b{nil} の二項と解釈されます。
なお、引数をシンプルにするとまた解釈が違います。
m a, b x, y = m a, b
これだと上下とも m(a, b) になるんですねえ。謎。 どっちがいいのかも謎。
(02:45)
http://zunda.freeshell.org/d/20040612.html#p01
うーむ、全然速くなりませんか。 大口たたいたわりに役に立ってないですねえ。 すみません。
前回も書いたとおり全体のプロファイルはとったことがあるし、 refctl.rb を作ったときの速度の上がりかたからしても、 parse_as_search が問題だというところまでは合ってるはずなんです。 どこがボトルネックになっているんだろうなあ。
(19:23)
(追記)
あれ? ja/disp_referrer.rb のパターン、一部しか変わってないのでは? [^./]+ のほうが効果が大きいから、こっちを全部に適用しないと意味がないっす。
いややっぱり違う。 マッチ回数自体が少なくなってるんだからどっちにしても意味はないんだ。 やっぱりまずはボトルネック計測だな。 これいじょう当て推量をやっても無駄っぽい。
データ集め
0. 環境
1. 実行時間 (高速な順)
素tDiary 2.35s user 0.01s system 100% cpu 2.357 total refctl.rb 3.95s user 0.01s system 100% cpu 3.955 total disp_referrer2.rb, with cache 9.75s user 0.11s system 100% cpu 9.833 total disp_referrer2.rb, without cache 11.39s user 0.01s system 100% cpu 11.373 total
2. URL の種別傾向
all =22346 search=21256 (fail=339) other =1090
3. プロファイル (disp_referrer2 original)
% cumulative self self total time seconds seconds calls ms/call ms/call name 20.45 125.30 125.30 320980 0.39 0.63 Array#<=> 16.67 227.44 102.14 87027 1.17 5.35 Array#each 8.13 277.27 49.83 11 4530.00 22780.00 Array#sort 6.35 316.15 38.88 322328 0.12 0.12 Fixnum#<=> 5.97 352.73 36.58 275366 0.13 0.13 String#<=> 3.53 374.35 21.62 22346 0.97 11.42 #<Class:0x409ffa44>::DispRef2URL#parse_as_search 3.36 394.92 20.57 363683 0.06 0.07 Hash#[] 2.72 411.57 16.65 22533 0.74 1.94 TDiary::RefererManager.add_referer 2.68 427.96 16.39 43521 0.38 0.80 #<TDiary::Config:0x40293864>.to_native 2.50 443.28 15.32 90843 0.17 0.24 String#gsub 2.34 457.60 14.32 163544 0.09 3.87 Class#new 1.89 469.21 11.61 14 829.29 4305.00 String#each 1.55 478.73 9.52 43521 0.22 0.35 Uconv.u8toeuc 1.53 488.12 9.39 251846 0.04 0.04 Array#[] 1.36 496.48 8.36 180744 0.05 0.05 String#split (1% 以下略)
4. プロファイル (disp_referrer2改)
% cumulative self self total time seconds seconds calls ms/call ms/call name 17.57 55.98 55.98 86915 0.64 1.21 Array#each 10.96 90.90 34.92 21256 1.64 9.61 #<Class:0x409ffa44>::DispRef2URL#parse_as_search 6.97 113.12 22.22 361772 0.06 0.07 Hash#[] 5.16 129.55 16.43 22533 0.73 1.95 TDiary::RefererManager.add_referer 4.93 145.25 15.70 163225 0.10 2.08 Class#new 4.92 160.93 15.68 87984 0.18 0.25 String#gsub 4.68 175.85 14.92 43520 0.34 0.79 #<TDiary::Config:0x40293864>.to_native 3.54 187.14 11.29 14 806.43 4300.71 String#each 3.16 197.22 10.08 43520 0.23 0.36 Uconv.u8toeuc 3.12 207.15 9.93 180427 0.06 0.06 String#split 2.76 215.96 8.81 6 1468.33 42170.00 Hash#each 2.22 223.03 7.07 22346 0.32 1.11 #<Class:0x409ffa44>::DispRef2URL#lookup_hostspec 2.17 229.94 6.91 22346 0.31 10.69 #<Class:0x409ffa44>::DispRef2URL#parse 1.78 235.62 5.68 43520 0.13 0.92 #<Class:0x409ffa44>::DispRef2Setup#to_native 1.59 240.70 5.08 20917 0.24 0.39 #<Class:0x409ffa44>::DispRef2String#normalize 1.51 245.50 4.80 145479 0.03 0.03 Hash#default 1.50 250.29 4.79 20919 0.23 3.97 #<Class:0x409ffa44>::DispRef2String#parse_query 1.36 254.62 4.33 116091 0.04 0.04 Hash#[]= 1.24 258.57 3.95 93843 0.04 0.04 Array#<< 1.16 262.27 3.70 21174 0.17 0.51 #<Class:0x409ffa44>::DispRef2String#unescape 1.15 265.93 3.66 42175 0.09 0.45 Enumerable.detect 1.10 269.45 3.52 81168 0.04 0.04 String#delete 1.09 272.92 3.47 87877 0.04 0.04 Regexp#=~ 1.07 276.34 3.42 22535 0.15 0.79 CGI#unescape 1.05 279.69 3.35 93183 0.04 0.04 Array#initialize (1% 以下略)
5. 各メソッドの消費時間配分 (sec)
DispRef2Refs#to_long_html 0.01 DispRef2Refs.new 8.75 DispRef2URL#parse 8.57 DispRef2URL#parse_as_other 0.15 DispRef2URL#lookup_hostspec 1.31 DispRef2URL#parse_as_search 7.87 ivar set 2.21 query analyse 4.36 query setup 2.53 keyword setup 2.24
6. parse_as_search HotSpot
keys.empty? 5 keys.kind_of?(String) 0 query=nil 5 cache URL 257 else 20651
現在の実装の延長でがんばる場合
(総合)
まず、DispRef2URL#parse がボトルネックになっていることは明らかである。 次にリスト 2 からリファラの 95% 以上が検索エンジンだとわかるので、 検索エンジンに最適化する。 また検索エンジンからのリファラの 95% 以上は !keys.empty? かつ kind_of?(Array) かつ非キャッシュエントリなので、 このパターンで最小手数になるように最適化すべき。
(方針)
(詳細)
検索エンジンのディスクリプタは独自クラスにして、 固有の最適化情報を最大限に利用する。 例えば Google 以外では site: を sub する必要はない。 ie/oe を見れば charset がわかるので、必要なければ uconv を呼ばない。 とにかく uconv は可能な限り減らすべきである。
現在は CGI query を一度ハッシュに展開しているが、 これをもうちょっと軽くする。 これも検索エンジンごとにコードを変更できればかなり最適化できそう。
ところで、今回の調査で実行時間のほとんどは parse であることがはっきりわかった。 ということは、キャッシュがちゃんと効いていれば parse のコストはほとんどなくなって大幅に効率が改善できるはずだ。 しかし実際には実行時間は 25% しか減っていないわけで、何かがおかしい。
……ちょ、ちょっと待って、 なんで検索エンジンだけキャッシュしてないんですか? それでキャッシュヒット率が異様に低かったのか!
あ、そうか。 検索エンジン抜きでキャッシュが 25MB ということは、 全部キャッシュすると 200MB を超えるんだな。 家のサーバじゃキャッシュをロードしただけでメモリがなくなる。 最低でもキャッシュデータベースを月ごとに分けないとまずいな。
あるいは、何か情報をあきらめるか。 検索キーワードは残して URL を捨てれば軽くならないかな。 ならないな。だめだ。
うーん。 こりゃちょっといじっただけじゃ速くならないな。 やっぱ工夫して全部キャッシュしちゃうのがお手軽でしょう。 粘ったわりにつまらない結論だ。
(03:52)
RHG 読書会で笑い死にそうになったネタが 思い出せなくて気になってたんだけども、 期待に違わず誰かが書いておいてくれた。 首都国家東京だった。やっとすっきりした。
そしてそんなこととは全然まったく関係なく、 明日提出のレポートがまだ書けていません! わーい!
(04:10)
■
zunda [プロファイル取ってみたのですが→http://zunda.freeshell.org/d/20040613.html#p01
とりあえず帰って寝ることにします。ぉぃ。]
日記を書き始めるとついいろいろ調べてしまって無限ループにはまるので、 ここしばらく意図的に日記を書かないで過ごしてみました。 それでも油断するとつい何か書いてしまいそうになります。
でもこの間にずいぶん本を読みました。 図書館にこもりっぱなしだと「うおぉ俺勉強してるぜ!」 という薄っぺらな満足感が得られてお得です。
(00:01)
ちょっと前からやっていた、BitChannel 内部構造の変更をコミットした。 クラスモデルを変えて PageEntity クラスと CVSWorkingCopy クラスを作ったのが特徴。 これで WikiFarm のコードがずいぶんきれいになった……って、 そういえば WikiFarm をちゃんと使えるようにしないとなあ。 次にコードをゆっくりいじれるのはいつになるんだろう。
(01:37)
「世界規模ソースコード検索エンジンの開発」
http://www.ipa.go.jp/jinzai/esp/2004mito1/gaiyou/2-23.html
まさにこういうのが欲しかった! ひたすら HDD にソースコードをためこんで grep かけるのって 非効率だなーとかねがね思ってたんだよー。これはいいなあ。
(17:59)
って、もしかしてすごく反応遅かった?
http://pc5.2ch.net/test/read.cgi/hard/1043011481/l50
699 名前: 不明なデバイスさん [sage] 投稿日:04/05/01 00:16 デュアルのどこがいいの? シングルで2倍速いCPU使ったほうがいいに決まってる。 703 名前: 不明なデバイスさん [sage] 投稿日:04/05/01 09:23 >>699 か っ こ い い だ ろ ?
激しく同意!
(19:36)
(必要ないことがわかったので削除。00:13)
RDtool は拡張ライブラリは使っていないので、 使っているファイルを全部一つにまとめてしまえば インストールも楽になるのではなかろうか。 試しに作ってみたのがこれ。
ダウンロードしたら rd2html にリネームして、 chmod 755 して、どっかに置けばインストール終わり。 あ、ちなみに Ruby 1.8 用ね。
動的に require してるのを潰すのがちょっとめんどくさかった。
(19:41)
http://i.loveruby.net/d/20040512.html#c07 より
■テシ [個人的にはテキストベースの方がエンコード云々で 全く信用ならないんですが・・・]
それは関係ないでしょう。 データベースがバイナリだろうとテキストだろうと コンテンツのエンコーディングは問題になります。 強いて言うとメタデータ部分で改行コードが違うと問題になりますが、 それはデータベース側で「CR LF を使う」などと決めてしまえばそれで終わりです。
(20:01)
ちょっとわけあって「クロネコヤマト 小さな引越し便」で検索したんですが、
ヒント: 伝票番号に「ヤマト」を付けると宅配状況が検索できます (例)ヤマト 99999999999
そんなことまでできるのかよ!
(22:58)
検索と言えばおれも ReFe という検索インターフェイスを握ってるんだよな。 検索できるのはいまのところ以下の二つだ。
もっと変なものを検索してみたい。 やはり Ruby に関連したものだろう。
……やっぱりウェブのことはウェブでやったほうがよさそうだ。
そういえば昔 ReFe CGI を作ったような気がする。 あれどこにやったっけ。
(23:33)
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.
■ kjana [履歴からも消したいっていうのは WiLiKi でも出てましたね。
http://www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?WiLiKi%3aWishList
(2004/01/18 で検索)]
■ kdmsnr [kitajさんの後に『Rubyレシピブック』にサインを頂きました!
ありがとうございました。# 青木さん、同じ年でビックリ。]
■ きた [いつも言おう言おうと思ってて忘れるんですが,Webと実物とのギャップってオレよりも青木さんの方が大きいよねぇ?]
■ ただただし [それは言える >きた]
■ 青木 [ガーソ]
■ 青木 [いやー、ぼくなんかのサインでいいんだったらいくらでもしますよ。
本、買ってくださってありがとうございます。 > kdmsnrさん]
■ 青木 [そういえば、「消そうとしても消せない」という特徴は
Winnyで最近話題になりましたねえ。CVS程度なら最終的には
レポジトリから消しちゃえば済むわけですが、Plan9 の
ファイルシステム (dumpfs だっけ) とかやばそうですよね。
絶対に情報が消えないシステムというのはそれ自体で価値が
あり、かつ危険なのかもしれません。]