先日、HTML5 の File API が Chrome の中でどのように実装されているか調べた。JavaScript の中から readAsText() でファイルを読んだときにブラウザの中では一体なにが起きるのだろうか?
そんなの fread() を呼んで終わり、だったら楽なのだが、 Chromeではそうはいかない。そもそもページを描画したりJavaScriptを実行したりしているレンダラーはサンドボックスされたプロセスの中で実行されているので、ファイルアクセスが一切できない。ではどうやるかというと、ブラウザ本体のプロセスに「このファイルを読んでください」というリクエストを投げる。プロセス間通信、IPC である。
で、このリクエストはブラウザ本体ではIPC用のスレッドが受け取るのだが、このスレッドでは同期的なファイルアクセスができない。同期的なファイルアクセスをこのスレッドでやってしまうと、たとえば、ファイルを読み込んでいる間、他のIPCリクエストが受け付けられなくなってしまい、困るからだ。よって、こういったリクエストは非同期的なファイルアクセス [1] で処理するか、別スレッドに投げるなりする必要がある。
こんな感じでIPC周りは複雑なのだが、それでは他の部分は単純かというと全然そんなことはなく、何重ものレイヤーが、コードの読み手の行く手を阻む。そもそも IPC がはじまる手前の部分だけでもかなり複雑だ。
といったわけで、こういう複雑なコードは必死で追いかけても、なかなか頭の中にはいらない。読んでいるそばから混乱して何が何だかわからなくなってしまう。というわけでコードを読みながら書いたのがこのメモ:
http://www.chromium.org/developers/code-reading/how-html5-s-filereader-works
書いてみてわかったのは、こういうメモはコードを理解する助けになるというだけでなく、他にもメリットがあるということだ。
まず第一に、達成感があること。コードを読んでいるだけだと、何も成果が出ないまま時間を浪費しているという焦燥感のようなものがあるのだが、こういうメモを残すと、多少は達成感があるがよい。第二に、仲間に受けがよいということだ。実際には、デバッガのスタックトレースに毛が生えたようなものなのだが、文書になっているとなんとなくありがたいものに見えるものだ。
ただし、問題点もある。コードリーディングのメモを残すことは、コードを理解する助けになることが第一なのだが、メモを書き始めると、ついそちらの方に身が入ってしまい、手段の目的化が発生しがちである。このメモの場合も、完全性をもとめて、当初の目的にとって、さして重要でない部分まで読み込んで時間を使ってしまった。さすがに、IPCの詳細は省いたが。
[1] 非同期のファイルアクセスについてはこの記事がおもしろい
http://neugierig.org/software/blog/2011/12/nonblocking-disk-io.html