コンピュータの中の世界

この世界は巨大なコンピュータ上で計算されているデータに過ぎないという考え方がある。人間がコンピュータ上で物理シミュレーションをするように、どこかの開発者が幾つかの物理法則と初期状態を入力し、プログラムの実行と共にこの世界が始まったというイメージ。

その巨大なコンピュータのコンセントが抜けてしまった時、どうなるのかを考えてみる。この世界はなくなるのか。

仮に演算結果は逐一、何かに記録されていたとすると電源が切れても後からいつでも記録された時点から再スタートできる。だとするとコンピュータの中の世界では、電源が切れたことなど何も関係なくそんな事が起きたことすら分からない。もし演算結果が記録されていなくて、電源が切れると同時にデータが失われたとするとこの世界はなくなるのだろうか。
そうではないと思う。そもそも物理法則と初期状態が与えられた時点で、世界の最後まで全ては確定していて、コンピュータの計算はそれを辿るだけの作業に過ぎない。計算に何億年かかろうと一瞬で終わろうとこの世界には何も関係なく、計算などはじめから行わなくても何も変わらないのだ。1+1は計算前後で変わらない。これは物理法則に確率的な要素があったところで同じだろう。計算するごとに世界は違ったものになるだろうが、何兆の何兆乗パターンの世界があろうと、物理法則と初期状態から全て求められる。

結局のところ、この世界がコンピュータ上で計算されているのかどうかは重要ではない。いろいろな物理法則、微妙に異なるパラメータの世界は無限に考えられ、それぞれの世界は計算しようがしまいが数学と同じようにいつまでも変わらないのだろう。

ライト兄弟

ライト兄弟の成功要因は動力飛行への情熱があったことが重要なんだろうけど、それ以外の点をwikipediaライト兄弟の秘密などから抜粋する。

  • 製作技術の基礎があった

機械いじりが好きで自転車屋を2人で経営していたため、製作技術を持っていた。

  • 先人から学んだ

ドイツの飛行実験家オットー・リリエンタールの滑空実験データ、揚力表、当時の飛行機開発の最先端を行っていたサミュエル・ラングレー教授の研究資料など、過去の研究家たちが残した資料から多くを学んでいた。

  • 先人のデータを疑った

参考書通りに作ったグラインダーがうまく飛ばないことから、過去の資料があてにならないことを悟った。

  • 操縦がうまかった

グライダーによる実験の回数もリリエンタールらに比べてはるかに上回り、多くの実験データを収集すると共に飛行技術を身につけることができた。

  • 科学的な手法

風洞実験

  • 大量の試作

揚力係数はサイズに依存しないので模型サイズでよく、200種類以上の翼型をテストしデータを取得できた。風洞実験とこの試作が大きく研究を前進させた。

  • テストをしながら組み立てるプロセス

エンジニアらしい。

  • 2人だった

2人だから仕事が捗ったり、心強いという当然の効果に加え、ラバーダッキング効果や簡単に諦めなくなるという効果もあったと思う。


ライト兄弟は技術者であり科学者でもあったんですね。

Gitのレポジトリを可視化するツール Visugit

Visugit - github
Git のコミットツリーを可視化するツールを作りました。これからGitを使いたいという人は見ながら操作すると覚えが速いと思います。OSX 10.6 と Ubuntu 10.04 では動きましたがWindowsでは試していません。
Screencast

インストール

% wget --no-check-certificate https://github.com/hozumi/visugit/raw/stable/bin/visugit
% chmod +x visugit
% ./visugit upgrade
The script at ./visugit will be upgraded to the latest stable version.
-n Do you want to continue [Y/n]? y
Upgrading...

恒久的に使いたい場合はpathの通ってる場所に置きましょう。

% mv ./visugit /usr/local/bin/

使い方

visugitコマンドに対象のgitリポジトリがあるディレクトリを引数で渡します。

% ./visugit ./your-git-project-dir

既に対象のディレクトリにいる場合は省略することができます。

% ./visugit 

エラーメッセージが出ますが気にしないで下さい。
現状、コミットオブジェクトを全部表示しようとするので、中〜大規模なレポジトリは表示できないと思います。

Netty の基本

ここ数日、Nettyについて調べていたので理解できたことを書きます。
JBoss Netty
Netty は Java で非同期、イベント駆動のネットワークアプリを作るためのフレームワークです。Netty を使うと早くて簡単にハイパフォーマンス、ハイスケールでメンテナンス性がいいものが作れます。いいとこ取りの全部乗せです。

  • なぜハイパフォーマンス、ハイスケールか?

Netty は Java NIO(New I/O)をラップしていて、ノンブロッキングなIO操作ができます。そのため、1つのコネクションにずっと1スレッドを割り当てる必要がないため効率のよいリソース消費をします。従来のブロッキングなOIO(Old I/O)もサポートしており、僅かな変更で好きな方を使えます。また、NIOの複雑なByte BufferをChannelBufferというオブジェクトに抽象化し、不必要なコピーが発生しないなどの工夫がされているそうです。

  • なぜメンテナンス性がいいか?

処理をレイヤーごとに分離できるからです。暗号化の層、ビジネスロジックの層などその層だけを気にすればいいように作れます。

Handler と ChannelPipeline

Handler と ChannelPipeline、この2つが Netty の基礎です。これさえ理解すれば大体okです。他の事は大したことではありません。



図の人マークが Handler を表し、そのHandlerをいくつか配置したものが ChannelPipeline です。上方向の流れをUpStreamと言いますが、要は受信です。下方向はDownStreamで、送信に当たります。Serverアプリケーションならリクエストを受け取ってレスポンスを返すと思うので、UpStreamの後にDownStreamが起こります。Clientアプリケーションなら、リクエストを投げてレスポンスを受け取るので、DownStreamの後にUpStreamですね。
流れているものはデータかというと少し違います。イベントです。"データを受信した"、"Openした"、"Closeした"、などのイベントが流れます。データを受信した時のイベントからはデータが取り出せるので、まずはデータが流れていると考えてもいいと思います。
最初にイベントを受け取った最下層のHandler は イベントに入っているデータをdecodeするなどの処理をして一つ上のHandler に処理後のデータをくっ付けたイベントを渡します。このようにHandlerごとに処理を分けることによって、一つ一つのHandlerは独立して自分の仕事に専念できます。独立しているとは言っても、econde/decode処理などを考えると分かるように多くの場合、上下のHandlerに依存性を持ってはいますが。
次のHandlerに処理を渡すとき、すぐに同じスレッドで次のHandlerが処理を始めるわけではありません。各Handlerは上下の順番通りに処理はされるのですが、Handlerごとにスレッドプールから割り当てられたスレッドで処理がされます。
一番上のHandlerまでイベントが渡され、さらに上に渡そうとしたイベントは単に無視されます。Server では多くの場合、一番上のHandlerがリクエストを処理してレスポンスを返す処理を行い、DownStreamが始まります。

先程の図では簡略してPipelineにはUpStreamとDownStreamの2つのラインがあるように書きましたが、正確にはUpStream用のHandlerもDownStream用のHandlerも一つのライン上に配置され、それぞれの方向に対応していないHandlerは単に飛ばされるだけです。

更に言うと、HandlerはUpStreamにもDownStreamにも対応することができるので、こういう図になります。
encode/decode処理、暗号化/解読処理など対の処理は一つのHandlerで処理するのがいいと思われるかもしれませんが、実際にはUpStream部分だけの挙動を変えたいという時があるため、柔軟に変更するためには別々のHandlerにしておいたほうがいいかもしれません。

UpStream に対応するためにはChannelUpstreamHandlerインターフェースを実装する必要があります。

public interface ChannelUpstreamHandler extends ChannelHandler {
    void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception;
}

DownStream に対応するためにはChannelDownstreamHandlerインターフェースを実装します。

public interface ChannelDownstreamHandler extends ChannelHandler {
    void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception;
}

それぞれたった一つのメソッドです。Nettyには上記インターフェースを実装した便利なHandlerがいろいろbuilt-inで用意されていて、それを継承してHandlerを作るときは上記のメソッドではなく、他のメソッドをOverrideするだけのことが多いです。しかしそれは handleUpstream/handleDownstream メソッドから他のメソッドが呼び出されているからであり、基本はこのメソッドがUpStream、DownStreamのイベントを処理するということを忘れないでください。引数で渡される ChannelHandlerContext と ChannelEvent とはなんでしょうか。

ChannelHandlerContext

ChannelHandlerContext を使うと ChannelPipeline や他の Handler に作用することができます。

  • イベントの送信

次のHandlerにイベントを渡すためには、必ずこのChannelHandlerContextを使用して明示的にイベントを渡さなければいけません。

ctx.sendUpstream(ChannelEvent)
ctx.sendDownstream(ChannelEvent)

上記メソッドを呼ばないと次のHandlerにイベントが渡されません。
これも built-in の Handler を継承する時はやらないでいいと思う時がありますが、それは継承元のHandlerがやってくれているからです。Netty が自動的に次のHandlerに処理を移してくれよと思うかもしれませんが、framing などのように受信データが一定値まで溜まるまで次のHandlerにイベントを送りたくない時などがあるのでこうなっているんだと思います。

  • ChannelPipelineを動的に変更する
ctx.getPipeline()

を呼ぶとそのHandlerの入っているChannelPipelineが取得でき、Handlerの動的な追加や削除ができます。例えば必要に応じてSSLのHandlerを追加するということができます。<書きかけ。追記予定>

【参考】
jboss netty 3.2 javadoc
javadoc ライクにソースが見れる
チュートリアルとExample

この方のブログ(英語)がとても丁寧に書かれていて参考になりました。是非読んでみてください。
Handler について
NIO FWの比較 パフォーマンス
NIO FWの比較 メモリ
NIO FWの比較 機能
NIO FWの比較 プロトコル

評論家に解説してもらわないと意味が分からない映画

町山智浩(id:TomoMachi)さんの映画評論がとても楽しくてここ数日ずっとポッドキャストなどを聞いていた。

以下の動画で町山智浩さんが映画評論について論じている。
D
マチマル:町山智浩さんと宇多丸さんはどのように映画と世界を見ているのかがとても見易く講演の内容をまとめてくれている。

これについて思う事。

「ストーリーを読み間違ってはいけない、好き勝手に解釈してはいけない」という主張はとても納得出来る。しかし

周辺にあるものを調べなければ絶対に読み違う
普通の観客は、そんな時間もないし、そこまでする必要はない。

とも言っている。

これはつまり、普通の観客は読み違いをしてしまうが、それは仕方ないと言っている。

ここで素朴な疑問がわいてくる。ストーリーを読み間違ってはいけないのに、普通に見てたら読み違いをしてしまうようにできてる映画なんておかしくないか?

私が抱いた疑問と似たような疑問はこの講演内で質問されていた。

質問者「2001年宇宙の旅ではナレーションをカットしたり、場面をずらしたりしたりすることで、その場面が分かりにくくなり、結果色んな解釈をされることになってしまった。それはキューブリックが意図したことなのか?」

町山「意図しています。人間は一方的に押し付けられたことには反発するが、自分で気付いたことは受け入れられる。気づく人は少ないかもしれないがより良く気付いてくれる。自分で考えて一番いい形で理解しうる。」

この町山さんの回答自体はとても納得出来る。

しかし気付きとは何なのか。

町山さんが提示している、2001年宇宙の旅イレイザーヘッドの正しい解釈は映画内の情報だけでは辿り着くことができない解釈だ。

町山さんが得ることができた正しい解釈は気付きではなく映画評論家としての調査の結果得られたものなのだ。

火曜サスペンス劇場の犯人がラストで初登場するのがルール違反であるのと同じように、映画内だけではストーリーが読めず評論家が調査をしないとストーリーが分からない映画なんてルール違反じゃないのだろうか。単に伝える努力がされていない映画じゃないのだろうか。キューブリックデビッド・リンチのような名のある監督だから何とかなっているのであって、新人の監督が同じ事をやっても意味不明と一蹴されてお終いじゃないだろうか。

node.jsの仕組みを聞いて分からなかった点

重要なのは,リクエストとタスクの違いです。ここで言うタスクとはリクエストを細分化したもので,例えばリクエストの解析や,キャッシュサーバーやデータベースサーバーへの問い合わせ,レスポンスの作成といった個々の処理を指します(もしくはイベントといったほうが適切です)。Node.jsはリクエスト(コネクション)という単位に縛られることなく,細分化したタスクを順番に処理していきます。より具体的に言えば,一人目がデータベースに問い合わせている間に二人目のリクエストの処理を行い,データベースから結果が返ってきたら一人目の処理へ戻り,といった具合です。データベースやファイルI/Oに問い合わせている間に何もすることがない,といったことが起こりません。

2011年のJavaScript ─ウェブアプリ全盛の時代へ
つまりはこういうことだと思う。
3つのリクエストを処理する時、スレッドモデルはこう。

人はスレッドを表していて、処理時間はCPU数による。

node.jsはこう。

  • 分からない点1

シングルスレッドモデルは複数スレッドによるリソース消費がなく、また待ち時間を他のタスクで埋めることができるので効率がいい。しかし、待ち時間を全て埋めてしまった後は時間が伸びていくだけのはず。一つのリクエストを処理する時間の90%が待ち時間だとすると10リクエストで待ち時間が全て埋まる。これはCPUのコア数がいくらだろうと同時に処理できるのは10リクエストが限界でそれ以上はどんどん応答が遅延するということを意味していると思う。この認識は間違いなのか。

  • 分からない点2

スレッドモデルでもこの待ち時間を考慮できて、CPUが遊んでいる時は他のスレッドをCPUに割り当てるはず。そうすると待ち時間の有効活用についてのnode.jsとスレッドモデルの違いは、スレッド切り替えコストの有無だけと言うことができる。この認識は間違いなのか。

Emacs + color-theme で自分の好きな配色にする。スクリーンショット100枚ぐらい

Emacs の配色(スキン?) をカスタマイズするには、color-theme をインストールして好みの配色を自分で選ぶのがいいみたいです。100種類ぐらいあります。
以下の手順は Mac OS X 10.6.4、 Aquamacs 23.2.50 で動作を確認しました。

  • インストール
cd ~/.emacs.d
wget http://download.savannah.gnu.org/releases/color-theme/color-theme-6.6.0.tar.gz
tar xzf color-theme-6.6.0.tar.gz
rm color-theme-6.6.0.tar.gz

~/.emacs.el

(add-to-list 'load-path "~/.emacs.d/color-theme-6.6.0")
(require 'color-theme)
(eval-after-load "color-theme"
  '(progn
     (color-theme-initialize)
     (color-theme-hober)))

最後の(color-theme-hober)は自分の好きな color-theme名に変更します。

次に、好きなテーマを選びます。スクリーンショットが公式にありませんでしたので作りました。スクリプトで半自動で取得しました。

私は取りあえず color-theme-gnome2 の眠くなる淡い感じが気に入りました。

2010/10/28 追記
color-theme-zenburnというのがなかなかいいみたいです。ただ、↑のcolor-theme-6.6.0に入ってなかったのでまたインストールします。

cd ~/.emacs.d/color-theme-6.6.0
wget http://github.com/credmp/color-theme-zenburn/raw/master/zenburn.el

~/.emacs.el

(add-to-list 'load-path "~/.emacs.d/color-theme-6.6.0")                         
(require 'color-theme)                                                          
(require 'zenburn)          ;<-追記                       
(eval-after-load "color-theme"                                                  
  '(progn                                                                       
     (color-theme-initialize)                                                   
     (color-theme-zenburn))  ; <-変更

Aquamacsだと更に一旦、~/Library/Preferences/Aquamacs Emacs ディレクトリを消す必要がありました。前回終了時の情報などテンポラリな情報を入れておくところだと思います。起動し直せばまた作られます。
zenburn は Lisp だと対応する括弧のハイライトがないので厳しいです。以下を追加しておいたほうがいいと思います。

zenburn.el 376行目くらいに。

     '(show-paren-match-face ((t (:bold t :background "Aquamarine" :foreground  
                                        "steel blue"))))                        
     '(show-paren-mismatch-face ((t (:background "Red" :foreground "White"))))