12:43:00 # Life 共有ライブラリはスタティックライブラリよりもオーバヘッドがあるの? 最近のLinuxで共有ライブラリを利用したプログラムを利用する場合, スタティックリンクの場合との違いとして, 関数呼び出しは一旦pltセクションというところのジャンプ命令を経由して 本当の関数を呼び出すようになります. この背景としては,共有ライブラリがロードされるアドレスというのが事前に決定できないため, ロードしてから関数呼び出すのアドレスを解決するという現状のELFのダイナミックローディングの仕様があります. それを実現するために text セグメント(プログラムの実行可能データの領域.ジャンプ命令の呼び出し先アドレスなどが書かれている)を全部書き換えれるようにしてしまうと 実行バイナリをそのままmmapで読み込み専用で読み込めないことになります. そうするとスワップ領域を無駄に確保する必要がでてきたりするので, 変更できる部分を外だしにしている,というあたりがそもそもの理由のようです. 関数呼び出しは,pltセクションに対してのジャンプ命令を発生し, pltセクションの該当する部分はGOTの適切な部分のアドレスを読み込みそのアドレスに飛びます. (powerpcの場合直接pltが書き変わっているきがしますが,これは確認必要です.) それにより実際の関数のコードへジャンプすることができます. powerpcで関数呼び出しだけを1G回するプログラムを作り,比較してみました. 約500MHzで動作しているCPUなので,2秒が約1クロックサイクルです. 同じ事を繰り返しているので一番高速な場合であることが予想できます. 結果を見てみると,どうやら-fPICの場合,関数呼び出しに2クロックサイクルくらい余計にかかっているようです.
項目 | 共有ライブラリ版(-fPIC) | スタティックリンク版 |
実時間 | 17.646 | 13.746 |
ユーザ時間 | 17.005 | 13.233 |
システム時間 | 0.024 | 0.018 |
参考までに,PLTセクションに書き込まれていたブランチ命令はこんな感じです.
0x10011b70 <function_in_lib@plt+0>: b 0xffdf590 <function_in_lib>
Athlon 64 2.2GHzで同様のテストをしてみました. 今回は,2.2G回実行してみたところ下記の結果が得られました. どうやら2クロックくらい消費しているようです.ppcと同じくらいですね. アッセンブラを解析してみたところ,しっかりとジャンプテーブルがGOTに作成されており, PLTではGOTへのインデックスをとりジャンプするようになっていました.
項目 | 共有ライブラリ版(-fPIC) | スタティックリンク版 |
実時間 | 8.185 | 6.142 |
ユーザ時間 | 8.168 | 6.125 |
システム時間 | 0.000 | 0.002 |
ここで,oprofileで実行中の時間分布をみてみると,ちょっと予想をうらぎる結果がでました. しかしなぜこうなるのでしょう.続きはまた後で.
共有ライブラリ版 | スタティックリンク版 | |
function_in_lib | 61% | 25% |
---|---|---|
main | 28% | 66% |
.plt | 4% | - |
Ian Wienandさんにまちがいを指摘されたので訂正しました. 彼の紹介してくれたこのページは非常にマニアックです.おすすめ. PLTセクションは書き込み可能ではないそうです.(古いABIではpowerpcではPLTセクションが書き変わっていた,とのことです.)
powerpc で確認してみたログです,li命令がb命令に置き換わっているので,pltセクションが書き変わっているみたいです.
(gdb) disassemble 0x10011b70 Dump of assembler code for function function_in_lib@plt: 0x10011b70 <function_in_lib@plt+0>: li r11,4 0x10011b74 <function_in_lib@plt+4>: b 0x10011b40 <_GLOBAL_OFFSET_TABLE_+44> End of assembler dump. (gdb) cont Continuing. Breakpoint 2, main (ac=1, av=<value optimized out>) at main.c:50 (gdb) disassemble 0x10011b70 Dump of assembler code for function function_in_lib@plt: 0x10011b70 <function_in_lib@plt+0>: b 0xffdf590 <function_in_lib> 0x10011b74 <function_in_lib@plt+4>: b 0x10011b40 <_GLOBAL_OFFSET_TABLE_+44> End of assembler dump.
22:18:34 # Life サーバ障害. netfort.gr.jpのサーバの/homeがフルになっていたため,メールが受信できていなかった可能性があります. 何か重要なメールをだしていたのにもかかわらず返事が無い,という場合はお手数ですが,再送ください.
$Id: dancer-diary.el,v 1.90 2006/01/31 11:16:16 dancer Exp $