Perlテックブログ

ITエンジニアの成長意欲を刺激する技術考察、モジュール開発の日記。Perlイベントや国内や海外のPerlの記事の紹介。

ダイナミックリンクライブラリの呼び出しが遅くなる理由

最近は、ダイナミックリンクライブラリの呼び出しが遅くなる理由はなぜかということについて考えていた。ダイナミックリンクライブラリというのは、実行時にLinuxであれば「.so」Windowsであれば「.dll」で、呼び出しとは、このファイルの中に記述された関数を呼び出すことをいう。

実行時の名前解決

呼び出しが遅くなる主な理由は、呼び出す関数のアドレスが、実行時に決まるからだ。

まず、最初に名前解決を行わないといけない。これは、関数の名前から、関数のアドレスを取得することをいう。関数のアドレスを実行時に取得するということは、関数のアドレスが、実行時になるまで決まらないということだ。

これの何がパフォーマンス上で問題となるか。

コンパイル時のインライン展開が行えないということ

もっとも問題なのは、実行時にアドレス解決するので、コンパイル時には呼び出す関数のアドレスがわからないということだ。これは、コンパイル時における最適化がかからないということを意味する。

コンパイル時の最適化の一つとしてインライン展開がある。これがきかない。 もしループの中で、関数で記述された小さなロジックを繰り返し実行するのであれば、インライン展開がきかないというのは、非常にパフォーマンス上に影響を与える。

たとえば、実際は3行程度の処理であるのに、それがダイナミックリンクライブラリで実装されていて、繰り返し関数が呼び出されたりする場合だ。

小さめの処理は静的に実装するしかない

こういうわけで、大きめの処理であれば、ダイナミックリンクライブラリで十分だけれど、小さめの処理は、インライン展開の恩恵にあづかるために、静的に実装するしかないという結論に至る。

ひとつのファイルの中であれば最適化はきく

ライブラリ間では最適化はきかないけれど、ひとつのファイルの中であれば最適化はきく。なぜなら、一つのファイルの中における、関数は互いに、自分自分について知っているから。

SPVMで数学関数を最適化する問題について考えていて、Math.soに固めていたのだけれど、「これって、インライン展開できなくね!?」と気づく。数学関数でパフォーマンス劣化を起こさせないためには、静的にSPVM自体に関数定義を含めるしかない。そうするとインライン展開をきかすことができる。