読者です 読者をやめる 読者になる 読者になる

Chromium (Chrome) のソースを読む

Chromium (Chrome) のソースを読んでみた.
まず Chromium の位置づけがややこしい.
Google 発のオープンソースなブラウザである Chromium があって,Google Chrome はこれをカスタムビルドしたもの,という位置付けらしい.まあ大多数の人間にとっては,Google Chrome のソースを読めるという認識で問題ないんだろう.
ソースをダウンロードしてビルドまで,の手順はここにまとまっている.

推奨ビルド環境は Visual C++ 2005 SP1.ソリューションファイル同梱なので,Windows っ子も安心.
巨大な tar ファイルの展開が終わると,Visual C++のプロジェクトファイルが大量に現れる.各プロジェクトの概要はこちら.

Google でせっせと書かれたと思われる部分のうち,結構な割合に Win32 色が強い.ビルドプロセスも Visual C++ 内で完結.なんか普段から Visual C++ で開発されているという印象を受ける.
あまりにも Win32 っぽいプロジェクトなので,自然といくつか気になる単語を検索してみたり.そして何回か検索しているうちにバグ発見.
WM_DWMCOMPOSITIONCHANGED を検索してみたところ,一箇所ヒットはするものの,まともにハンドルされていない.Chromium (Chrome) さんは,アプリケーション起動時にデスクトップコンポジションの有効・無効を確認するものの,その後にデスクトップコンポジションが無効化されたり元に戻ったりというケースを想定していないようだ.実際,DWM を無効にした状態で Google Chrome を起動し,その後で DWM を有効化してみたところ哀しいことになった.
とまあこんな感じで,Win32 開発経験のある人にとっては普通に面白いソースだろう.IMM32 周りのコードも結構あって,コメントを読んでいるとその苦労に泣けてくる.
その手の人にはおすすめ.

(追記) Chromium (Chrome) のタイマ精度

こういう記事も見つけた.

ここで興味深いことが一点。JavaScriptのTimerは1/1000秒すなわちmsecの精度で、タイマーを動かすことができます。すなわちsetInterval("test", 1)のようにタイマーを発動させると、1msec毎にtestという関数を呼び出すことができます。ただ、実際には、このTimerの精度は、JavaScriptのエンジンの実装に依存していて、一般的にタイマーの最小精度は10~16msec程度になっているのが通例でした。16msecというと、約1/60秒なので、アニメーションするときにもこの程度の精度があれば十分だし、悪意のあるJavaScriptの暴走を止める意味でも16msecくらいに留めておくのが一般的だというのが従来のブラウザの常識(?)だと勝手に解釈してたのですが、Chromeのタイマー精度は1msecで動きます。なので、setIntervalで1msecを指定したパフォーマンス測定をすると、ダントツ性能が上がります。(他のブラウザでは1msec指定しても実際には10~16msec毎にしか動かないので)

Web 屋さんには,JavaScriptエンジンのタイマ精度が何かと気になるところらしい.しかしその 10〜16msec という間隔,Windowsっ子的には単なるハードウェアタイマのデフォルトの割り込み間隔だったりする.

んで,1msec で動くという Chrome (Chromium) さんのソースコードから,timeBeginPeriod を検索してみたところ,timeBeginPeriod(1); が 3 箇所ほどみつかった.やはりというかなんというか.
もちろん 1msec 間隔でタイマを動かすにあたって他にも注意すべき事はある.しかし,開発者が OS 特性を熟知していて,しかるべき場所でしかるべき API を呼んでいるかどうかだけで決まっている問題が,外野からは「中の人には深いお考えがあってのこと」と深読みされていることも結構あるんじゃないかと深読みする今日この頃.

(追記2) Chromium (Chrome) のタイマ精度 (2)

さっき書いたタイマ精度の話,消費電力という点では確かに「中の人には深いお考えがあってのこと」説はありうる.これはごもっとも.

さて、JavaScriptのタイマーには、本当に1msの精度が必要だろうか。Flashでさえ、Flash Player 10で、timeBeginPeriodの使用をやめるというのに。まあこれは、省電力のほか、Vistaではオーディオスタックが違うという理由もあるのだけれど、MSやIntelから省電力の強い圧力がかかっているのだから、やはり省電力だろう。

Windows にしても Linux にしても,タイムシェアリングの根本的なところで,ハードウェアタイマである Programmable Interval Timer (PIT) に依存している*1.PIT はひとつしかないため,こいつの割り込み間隔を変えるとスレッドスケジューラの動作がまるで変わってしまい,結果的に全プロセスが影響を受ける.timeBeginPeriod(1); が行っていることは,つまりはそういうことだ.消費電力的にこれはどうよ? という声は根強い.主に盛り上がっているのはお隣 Linux の方だけど.

Windows ではどうかというと,6 年前に書かれた『Guidelines For Providing Multimedia Timer Support』の Reasons for a New Timer で既に問題が指摘されていたにも関わらず,HPET の普及具合とか新 API をどうするかとか,なかなか解決の形が見えてこない.
さしあたって今の我々には Win32 API しか自由度はないわけだが,うまい落としどころを見つけられるとそれだけでかなり大きな成果になる.消費電力込みのベンチマークを取ってみる等,Chromium はよい実験材料になるだろう.明らかに操作してなさそうな時は timeBeginPeriod の割り込み間隔を元に戻すといった誰でも思い付く方法でも,案外十分な効果があるかもしれない.
Chrome のノリを考えるに,about:timer みたいなモニタツールを作るのも面白そうだ.そもそもこの問題が知られていなさすぎというのもあるし,そこでブラウザを通じて問題提起というのも Chrome の立ち位置には相応しいかもしれない.

*1:新しめのハードウェア+新しめの OS では,[http://en.wikipedia.org/wiki/HPET:title=HPET (High Precision Event Timer)] に移行中.