2012年3月11日日曜日

checking chromium processes structure

Linuxでプロセスを調べる場合にはpsコマンドを使うことがあるが、あんまり見やすいとは言い難い出力になる(少なくとも自分には)。
 今回プロセスの親子関係を調べたいと思って調べたら"pstree"なるコマンドがLinuxにはあって、それを使うと、

init─┬─NetworkManager─┬─dhclient
     │                └─2*[{NetworkManager}]
/* 省略 */
     ├─chromium-browse─┬─chromium-browse
     │                 └─19*[{chromium-brows}]
     ├─chromium-browse───chromium-browse───3*[{chromium-brows}]
/* 省略 */

みたいな感じでinitをルートとしたプロセスがきっちりと親子関係が分かりやすく出力してくれる(多分、上の例は等幅フォントじゃないとずれて見えると思うが)。

N*[...]で囲まれているのは、...がN個その階層に存在していることを意味し、{...}は...がスレッドであることを意味する。

つまり、上記の例で見ると1個目のchromium-browse(rが抜けている…文字制限か…)の下には1個の子プロセスと19個のスレッドがあり、2個目のchromiumは1個の子プロセスを持ち、その子プロセスには3個のスレッドがあるという事になる。

ちなみに上記例はchromium-browserを起動した直後の状態なので、Linux版chromiumは起動直後で既に4プロセス動いている訳だ。

ここでchromiumのタブを一つ追加して、再度pstreeを実行すると

/* 省略 */
     ├─chromium-browse─┬─chromium-browse
     │                 └─15*[{chromium-brows}]
     ├─chromium-browse───2*[chromium-browse───3*[{chromium-brows}]]
 /* 省略 */

と出力される。2個目のchromium-browseの子プロセスが2個に増えている事が分かる。よく見ると1個目のchromium-browserのスレッド数が19個から15個に減っているがこれだけでは理由は不明。

どちらにせよ1個目のchromium-browseがBrowser UIプロセスで、 2個目がRender Viewプロセスの様だ。おそらく親のプロセスは管理プロセスか何かではないかと推測。

またここで先ほど追加したタブを別ウィンドウとして切り離して再度pstreeを実行すると

 /* 省略 */
      ├─chromium-browse─┬─chromium-browse
     │                 └─16*[{chromium-brows}]
     ├─chromium-browse───2*[chromium-browse───3*[{chromium-brows}]]
 /* 省略 */

と出力される。Browser UIプロセスと思われるchromium-browserのスレッド数が1個増えているが、Render VIewプロセスと思われるchromium-browserの子プロセスは増えていない。

どうやらchromium-browserは複数のタブをウィンドウに分離してもBrowser UIプロセスは増やさずに管理している様子。

2012年3月5日月曜日

Reading platform.h in v8 repository

v8のメモリまわりを知りたいので、virtual memory機能を調べるとplatform.hにVirtualMemoryなるクラスを発見。

class VirtualMemory

予約されたメモリ領域を表現し制御するクラス。
予約されたメモリの制御は代入とcopy-contructing?(コピーコンストラクタの誤字と思われる)によって他のVirtualMemoryオブジェクトにアサイン可能。予約されたメモリはお事理なるオブジェクトからは削除される。

メソッドは以下のものがある。日本語はheader fileに記載のコメント。

VirtualMemory();
空のVirtualMemoryオブジェクトを生成。予約されたメモリを持たない。

exlicit VirtualMemory(size_t size);
サイズが引数sizeのvirtual memoryを予約する。

VirtualMemory(size_t size, size_t alignment);
引数alignment毎にアライメントされた、サイズが引数sizeの領域を持つvirtual memoryを予約する。この処理ではaddress()によって戻された位置ではないかもしれない。

~VirtualMemory();
このVirtualMemoryオブジェクトによって制御されていた予約したメモリを開放する。

bool IsReserved();
予約されたメモリを持っているかどうかを返す。

void Reset();
組み込まれたVirtualMemoryオブジェクトの初期化、もしくはリセットを実行する。

void* address();
予約されたメモリの先頭アドレスを返す。
もしアライメントを持って予約されたメモリならば、このアドレスは必ずしもアライメントされているとは限らない。アライメントブロックの先頭を取得するためにはアライメントサイズの倍数だけ端数を切り捨てる必要があるかもしれない。

size_t size();
予約されたメモリのサイズを返す。戻り値が意味あるのはIsReserved()がtrueの場合のみである。
もしアライメントを持って予約されたメモリならば、このサイズは要求されたサイズよりも大きくなるかもしれない。

bool Commit(void* address, size_t size, bool is_executable);
実際のメモリをコミットする。コミット操作が成功したかどうかを戻り値で返す。

bool Uncommit(void* address, size_t size);
実際のメモリをアンコミットする。アンコミット操作が成功したかどうかを戻り値で返す。

void Release();
[コメントなし]

void TakeControl(VirtualMemory* from);
予約された領域の制御を異なるVirtualMemoryオブジェクトにアサインする。
古いオブジェクトはこれ以上動作しない(IsReserved()はfalseを返す)。

static void* ReserveRegion(size_t size);
[コメントなし]

static bool CommitRegion(void* base, size_t size, bool is_executable);
[コメントなし]

static bool UncommitRegion(void* base, size_t size);
[コメントなし]

static bool ReleaseRegion(void* base, size_t size);
ReserveRegion()によって返されるベースポインタと予約時のサイズと同サイズの値を引数に実行する必要がある。

基本的なメモリ管理クラスの様だ。ccファイルの方はplatform別にplatform-<プラットフォーム名>.ccと言うファイルになっている。linuxの場合にはplatform-linux.ccといった具合。
次回はccファイルの中身を見てみる予定。

2012年3月1日木曜日

V8 JavaScript Engine libraries.cc Part 2

昨日の続き。
libraries.ccで定義されている関数がどこで使われているかを調査。
(JavaScriptコードをv8エンジンではどう使っているのか)一番気になるGetRawScriptSource()がターゲット。
■GetRawScriptSource()
1.void Deserializer::ReadChunk() @ serializer.cc
data = source_->Get();の結果がkNativesStringResourceの場合に実行される。
その戻り値を利用してNativesExternalStringResourceクラスのインスタンス生成。
2.Handle<String> Bootstrapper::NativesSourceLookup() @ bootstrapper.cc
heap->natives_source_cache()->get(index)->IsUndefined()がtrueならば実行される(ただし、Natives::GetRawScriptSource())。
※ indexはint型引数。
※ NativeSourceLookup()はbool Genesis::CompileBuiltin() @ bootstrapper.ccから実行され、戻り値がCompileNative()に渡される。
3.bool Genesis::CompileExperimentalBuiltin() @ bootstrapper.cc
ExperimentalNatives::GetRawScriptSource()限定だが実行され、その結果がfactory->NewStringFromAscii()に渡され、その結果がCompileNative()に渡される。
4.void Shell::InstallUtilityScript() @ d8.cc
GetRawScriptSource()の引数として与えられる値は以下の通り。
i::NativesCollection<i::D8>::GetIndex("d8");
"d8"と言う時点でbuiltinではなく、d8固有の機能をインストールしているはず。

ちなみにNativesとExperimentalNativesは以下の通りnatives.hで定義されている。NativeCollectionクラスの定義も同じファイルで定義されている。

typedef NativesCollection<CORE> Natives;
typedef NativesCollection<EXPERIMENTAL> ExperimentalNatives;

以上の事から、以下の2点が今後の調査ポイントになりそう。

  • Deserializer::ReadChunk()でNativesExternalStringResourceオブジェクトを作る事の意味
  • Bootstrapper::NativesSourceLookup()でCompileNative()にJavaScriptソースコードが渡された後の処理
あと、libraries.ccに生成された整数値の羅列を解析(と言う程のものではないが、char型データとしてファイル出力)して、目視確認すると以下の事をやっている事は分かった。
  • コメント行は全て改行のみに変換
  • ローカル変数名を1文字のアルファベットに変換

つまりは、データ化した時のサイズを小さくする事が目的の変換が施されている様子。
依然として関数名の先頭に%が記述されている変則的な記法は残っている。。。

とりあえず今日はここまで。