XenLASY: XenのI/O 処理を 追跡するための

XenLASY: XenのI/O処理を
追跡するための
アスペクト指向プロファイラ
柳澤 佳里 光来 健一 千葉 滋
東京工業大学 情報理工学研究科
1
VMを考慮したチューニングを支援す
るツール

OS単体でのチューニングでは不十分


I/Oがドメイン0を通る
複数のVMのI/Oが競合
例) XenのI/O処理 ドメイン0
ドメインU
OS
実ドライバ
OS
仮想ドライバ
仮想ドライバ
仮想マシンモニタ (VMM)
ハードウェア
2
I/Oフローの追跡が大切

I/Oフローとは



I/Oを発行してデバイスが送出する流れ
デバイスで受信しアプリケーションが受け取る流れ
個別のデータの動き (フロー) の追跡が必要


データがドメインUやドメイン0でどう処理されるかを知りたい
複数のドメインがI/Oした場合に、区別して追跡したい


余計なフローは取りたくない
個々のフローはフロー識別子 (ID) が必要

一つ一つのデータの流れを区別するため
3
単純なフロー追跡では不十分

コールフロー


関数呼び出しの流れを追跡
実行スレッドが変わると追跡不可



ドメイン間の追跡が不可能
トップハーフ / ボトムハーフの追跡が不可能
単純なデータフロー


データのポインタを追跡
データ形式が変化すると追跡不可


ドメイン間ではデータ形式が変化し、追跡不可
データの複製、分割すると追跡不可
4
XenLASY


Xen上のI/O処理をプロファイリングをするための
アスペクト指向システム
xflowポイントカット

Xen上のデータフローを選択するポイントカット

指定した種類のフローに指定したデータが入っている時を選択


追跡すべきデータの流れをきめ細かく指定可能




文法: xflow(フロー名, データへのポインタ)
開始点、中継点、終了点を指定
データ形式の変化、分割などにも対処
余計なデータが含まれないようにできる
xflow_idポイントカットでフローIDを取得
5
KLASY を拡張して開発

KLASY [Yanagisawa ’06] とは、


カーネル用動的アスペクト指向システム
ソースコードレベルの情報を実行時の織り込みで利用

accessポイントカットを実現





構造体メンバーへのアクセスをポイントカット
Source-based binary-level dynamic weaving
xflow、xflow_idを扱えるよう言語拡張
@ドメイン名を使えるよう言語拡張
Xen上のドメインに織り込めるよう変更
6
XenLASYのアスペクト例
accessポイントカットで選択
id1
id2
<aspect>
データフロー (netflow)
ポイントカット
<advice>
DomainU
Domain0
<pointcut>
access(sk_buff.%) AND target(skb) AND
xflow(netflow, skb) AND xflow_id(id)
</pointcut>
<before>
long long tsc;
DO_RDTSC(tsc);
STORE_DATA3($pc$, tsc, id);
</before>
アドバイス
</advice>
</aspect>
sk_buff構造体インスタンスが
netflowのデータだった場合に
pc、時間、フローidをログ出力
netflow: ネットワークI/Oの
フロー
7
xflowポイントカットの定義
<xflow name=“netflow”>
<start><pointcut>
access(sk_buff.data) AND
within_function(alloc_skb_from_cache)
</pointcut></start>
<transit><pointcut>
access(sk_buff.head) AND
within_function(skb_clone)
</pointcut>
<move from=“skb” to=“n” />
</transit>
<quit><pointcut>
access(sk_buff.%) AND
within_function(__kfree_skb)
</pointcut></quit>
</xflow>

netflow


start: 開始点


Xen上のネットワークI/O
処理フロー
データフローの開始点を
指定
transit: 中継点

データ形式が変わる場合



skb_cloneは複製を作成
ドメイン間の場合
quit: 終了点
8
start/quit (開始点/終了点)
<start><pointcut>
access(sk_buff.data) AND
within_function(alloc_skb_from_cache)
</pointcut></start>

構造体インスタンスからIDを
引けるよう登録、削除

構造体インスタンスの指定
そのほかの記述例

<start><pointcut>…</pointcut>
<select local_var=“data” />
</start>
<start><pointcut>…</pointcut>
<action>
int id = new_flowid();
…
</action>
</start>


省略時はaccessポイントカッ
トで選択した構造体のインス
タンスを選択
selectで任意の変数も指定可
DB登録/削除処理は自動で
設定

任意のコードを指定する場合
はactionを利用
9
transit (中継点)
<transit><pointcut>
access(sk_buff.head) AND
within_function(skb_clone)
</pointcut>
<move from=“skb” to=“n” />
</transit>




そのほかの記述例
<transit><pointcut>
…
</pointcut>
<copy from=“skb” to=“n” />
</transit>
moveで対応付けを指示

skb: フローID格納元
n: フローID格納先
skbを鍵としてフローID
が引けないようエントリを
抹消
エントリを保持するcopy
も用意
10
ドメインをまたがるtransit定義

xin_move、xout_move要素を用意

ドメインをまたがるとデータのアドレスからフロー
IDを引けない



ドメイン間ではアドレス空間が違う
ドメイン間ではデータベースを共有していない
フローIDを送信先ドメインに伝搬

ドメイン間で渡されるヘッダの空き領域にIDを格納
ヘッダ
ドメイン0
DomU
実データ
フローIDを格納
11
ドメイン間transitの例
<transit><pointcut>
access(netif_tx_request.flags) AND
within_file(drivers/../netfront.c@linU)
</pointcut>
<xin_move name=“netin” from=“skb” to=“tx”>
<field name=“flags” offset=“4” size=“12” />
</xin_move>
</transit>


linUからlin0にフローIDを
伝搬
xin_move

skbのフローIDをtxに格納


xout_move

<transit><pointcut>
access(netif_tx_request.flags) AND
within_file(drivers/../netback.c@lin0)
</pointcut>

<xout_move name=“netin” from=”tx” to=“skb” />
</transit>
flagsメンバーの下位4ビッ
ト目から12ビットを使用
xin_moveの逆処理でフ
ローIDを取得し、skbに割
当

対象xin_moveはnameで
選択
@ドメイン名で選択するド
メインを指定
tx->flags
12bit
4bit
12
xflowの実装: start/quitの変換
<start><pointcut>
access(sk_buff.data) AND
within_function(alloc_skb_from_cache)
</pointcut></start>
<pointcut>
access(sk_buff.data) AND target(skb)
AND within_function(alloc_skb_from_cache)
</pointcut>
<before>
id = get_new_flowid();
register_flowid(netflow, id, skb);
</before>
targetポイントカットを追加
構造体インスタンスへの参照を取得
DBに参照を鍵としてIDを
取り出せるよう登録
•alloc_skb_from_cache
でskbから新規フローID
を引けるようDBに登録
quitも同様
13
xflowの実装: transitの変換
<pointcut>
access(sk_buff.head)
AND within_function(skb_clone)
AND local_var(skb, skbp)
AND local_var(n, np)
</pointcut>
<before>
void *skb = *((void **)skbp);
void *n = *((void **)np);
int id = get_flowid(netflow, skb);
if (id != 0) {
register_flowid(netflow, id, n);
remove_flowid(netflow, skb);}
</before>
<transit><pointcut>
access(sk_buff.head) AND
within_function(skb_clone)
</pointcut>
<move from=“skb” to=“n” />
</transit>
•local_varポイントカットでロー
カル変数への参照取得
skbに割り当てら
れていたフローID
をnに割り当てる
14
xflowの実装:
ドメイン間transitの変換
<transit><pointcut>
access(netif_tx_request.flags) AND
within_file(drivers/../netfront.c@linU)
</pointcut>
<xin_move name=“netin” from=“skb” to=“tx” />
<field name=“flags” offset=“4” size=“12” />
</xin_move>
</transit>
<pointcut>
access(netif_tx_request.flags) AND
within_file(drivers/.../netfront.c@linU)
AND local_var(tx, txp)
AND local_var(skb, skbp)
</pointcut>
<after>
struct netif_tx_request *tx = txp;
void *skb = *((void **)skbp);
id = get_flowid(skb);
ポインタに対応づ
if (id != 0) {
けられたフローID
tx-&gt;flags |= id &lt;&lt; 4; をヘッダに格納
id &gt;&gt;= 12;
}
remove_flowid(netflow, skb);
</after>
local_varポイントカットでロー
カル変数への参照取得
•XenのネットワークI/OはドメインU
でnetif_tx_request構造体にヘッダ
を格納
送信先でフローIDを
15
受け取るコードは割愛
実装: KerninstのXen対応


アスペクトの織り込みにKerninst [Tamches ’99]を使用
割り込みテーブル読み込みを除去


ブレークポイントトラップ処理関数をエクスポートし、
Kerninstから直接参照
割り込みテーブル読み込みは特権命令


ドメインUやドメイン0から読み込めない
特権レベル判定を変更


Xen上ドメインでの実行に対応
Kerninstはring0でカーネルが動作していると仮定
16
マイクロベンチマーク

目的


xflowのバックエンド関数の
オーバーヘッドを調査
実験方法




CPU: AMD Athlon™ 64
3500+
メモリー: 2GB


関数名
get_new_flowid
各関数を2000回呼び出し、
空要素 get_flowid
平均を計算
実験環境

結果
ドメイン0: 256MB
ドメインU: 128MB
実行時間(ナノ秒)
3 ± 0.0
9 ± 0.0
register_flowid
33 ± 4.0
get_flowid
15 ± 1.0
remove_flowid
32 ± 2.0
ドメイン0で実施
バックエンド関数のオーバーヘッドは低い
17
ネットワークI/Oのボトルネックの調査

目的


ドメインUからドメイン0までの処理の流れ、ボトルネック
を調査
xflowを用いて、ドメインUからドメイン0までのデー
タフローを調査

sk_buff構造体のメンバーにアクセスがあった箇所でフ
ローIDを取得し、時間とともに記録

例に出したアスペクトを使用
18
実験結果

処理の流れがわかった


skb_clone関数でできた複製も追跡可能

TCP再送処理のためにTCP層で実行され、ドライバーは複製を
利用
ボトルネックはドメイン0の内部
ボトムハーフ → トップハーフのところ

netif_receive_skbはトップハーフの処理割り当て関数
送信時のパケットの流れ
フロ
ー
0
500
1000
network_start_xmit
tcp_sendmsg
alloc_skb_from_cache
1500
2000
2500
経過時間 (μ秒)
netif_rx
netbk_fill_flags
3000
FreeTxDescriptors
3500
4000
__br_forward
netif_receive_skb SkGeXmit
19
xflowによるオーバーヘッドの削減

目的


方法



xflowを使うことでプロファイルのオーバーヘッドを削減でき
るか調査
上のケーススタディのアスペクトでxflowありとなしを比較
ApacheBenchを300リクエスト、10並列で実行
結果
メモリー使用量
ドメイン0
ドメインU
性能(req/s)
xflowあり
1.6MB
10.6MB
382
xflowなし
13.6MB
15.7MB
382
約60%のメモリーを削減
20
関連研究

Dflow pointcut [Masuhara ’03]




DJcutter [Nishizawa ’04]、DAC++ [Almajali ’05]



データの流れを選択するポイントカット
自動的にデータを追うのでデフォルトでは追跡しすぎる
コンパイル時にdflowのためのコードを織り込み
分散環境に対応したアスペクト指向システム
ユーザーランドのアプリケーションを対象とする
Causeway [Chanda ’05]


メタデータを伝搬させ処理の流れを追跡
FreeBSDのネットワークI/Oコードを改造して実装
21
まとめ

XenLASYを提案

xflowポイントカットを提供




データフロー追跡をアスペクトとして容易に記述可能
複数ドメインに自動でアスペクトを織り込み
KLASYを拡張した動的アスペクト指向システム
ケーススタディ


ネットワークI/Oのボトルネックがドメイン0の処理にあること
を発見
フロー追跡機能により調査に必要なメモリー使用量の削減
を確認
22
今後の課題

データフロー分割時のフローIDの割り当て方




例) TCPにおけるフラグメント処理
同じIDだと、分割同士の区別ができない
違うIDだと、分割同士の関係が不明瞭
ヘッダに空き領域がない場合に対応

ドメイン間で共有メモリーによりフローIDを
渡す実装を検討
23