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