質問

特定の状況で動的リンクではなく静的リンクを選択したり、その逆を選択したりする説得力のあるパフォーマンス上の理由はありますか?私は次のようなことを聞​​いたり読んだりしたことがありますが、その真実性を保証できるほどこの件については知りません。

1) 静的リンクと動的リンクの間の実行時のパフォーマンスの違いは、通常は無視できる程度です。

2) (1) は、プロファイル データを使用してプログラムのホットパスを最適化するプロファイリング コンパイラーを使用する場合には当てはまりません。静的リンクを使用すると、コンパイラーはコードとライブラリ コードの両方を最適化できるためです。動的リンクを使用すると、コードのみを最適化できます。ほとんどの時間をライブラリ コードの実行に費やしている場合、これは大きな違いを生む可能性があります。それ以外の場合は、(1) が引き続き適用されます。

役に立ちましたか?

解決

  • 動的 リンクすることができます 総リソース消費量を削減する (複数のプロセスが同じライブラリを共有する場合 (もちろん、「同じ」内のバージョンも含みます))。これが、ほとんどの環境でこのツールが存在する理由になっていると思います。ここでの「リソース」には、ディスク領域、RAM、キャッシュ領域が含まれます。もちろん、動的リンカーの柔軟性が不十分な場合は、次のようなリスクがあります。 DLL地獄.
  • 動的 リンクとは、バグ修正とライブラリのアップグレードを意味します。 伝播する 改善する あなたの 何も発送する必要のない製品です。
  • プラグイン いつも呼びかける 動的 リンクすること。
  • 静的 リンクすると、コードがすぐに実行されることがわかります。 限られた環境 (起動プロセスの初期、またはレスキュー モード)。
  • 静的 リンクするとバイナリを作成できる 配布しやすい 多様なユーザー環境に (より大規模でより多くのリソースを必要とするプログラムを送信するというコストがかかります)。
  • 静的 リンクは少し許可されるかもしれません より高速な起動 ただし、これはプログラムのサイズと複雑さの両方にある程度依存します。 そして OS のロード戦略の詳細については、こちらをご覧ください。

コメントや他の回答に非常に関連性の高い提案を含めるためにいくつか編集しました。これを突破する方法は、どのような環境で実行する予定であるかによって大きく左右されることに注意してください。最小限の組み込みシステムには、動的リンクをサポートするのに十分なリソースがない可能性があります。わずかに大きな小規模システムでは、メモリが十分に小さいため、ダイナミック リンクによる RAM の節約が非常に魅力的になるため、ダイナミック リンクをサポートする場合があります。Mark 氏が指摘するように、本格的なコンシューマ PC には膨大なリソースがあり、利便性の問題に基づいてこの問題について考えることもできるでしょう。


パフォーマンスと効率の問題に対処するには: 場合によります.

従来、ダイナミック ライブラリにはある種の接着層が必要で、これは多くの場合二重ディスパッチや関数アドレッシングにおける間接層の追加を意味し、速度が若干低下する可能性があります (しかし、関数呼び出し時間は実際には実行時間の大きな部分を占めますか?)。

ただし、すべてが同じライブラリを頻繁に呼び出す複数のプロセスを実行している場合、静的リンクを使用する場合よりも動的リンクを使用する方がキャッシュ ラインを節約できる (したがって、実行パフォーマンスが向上する) 可能性があります。(最新の OS が静的にリンクされたバイナリ内の同一セグメントを認識できるほど賢い場合は別です。難しそう、誰か知ってる?)

別の問題:ロード時間。ある時点で積載コストを支払います。このコストをいつ支払うかは、OS の動作方法と使用するリンクによって異なります。おそらく、必要になるとわかるまで支払いを先延ばしにしたほうがよいでしょう。

静的リンクと動的リンクは伝統的に区別されることに注意してください。 ない どちらもオブジェクト ファイルまで個別にコンパイルする必要があるため、最適化の問題が発生します。ただし、これは必須ではありません。コンパイラは原則として、最初に「静的ライブラリ」をダイジェストされた AST 形式に「コンパイル」し、メイン コード用に生成された AST にそれらの AST を追加することでそれらを「リンク」することができ、これによりグローバルな最適化が可能になります。私が使用しているシステムはこれを行うものではないため、それがどの程度うまく機能するかについてコメントすることはできません。

パフォーマンスに関する質問に答える方法は次のとおりです。 いつも テストすることによって実行できます (デプロイメント環境とできるだけ似たテスト環境を使用します)。

他のヒント

1) は、DLL 関数の呼び出しが常に追加の間接ジャンプを使用するという事実に基づいています。現在、これは通常無視できる程度です。i386 CPU では位置に依存しないコードを生成できないため、DLL 内でさらにオーバーヘッドが発生します。amd64 では、ジャンプはプログラム カウンターを基準にできるため、これは大幅な改善です。

2) これは正しいです。プロファイリングに基づいて最適化を行うと、通常は約 10 ~ 15% のパフォーマンスを向上させることができます。CPU 速度が限界に達した今、それを行う価値があるかもしれません。

私ならこう付け加えます。(3) リンカは、よりキャッシュ効率の高いグループに関数を配置できるため、コストのかかるキャッシュ レベルのミスが最小限に抑えられます。また、特にアプリケーションの起動時間に影響を与える可能性があります (Sun C++ コンパイラで確認した結果に基づく)

また、DLL ではデッドコードの削除を実行できないことを忘れないでください。言語によっては、DLL コードも最適ではない場合があります。仮想関数は、クライアントが上書きしているかどうかをコンパイラが認識しないため、常に仮想関数です。

これらの理由により、実際に DLL が必要ない場合は、静的コンパイルを使用してください。

編集(ユーザーのアンダースコアによってコメントに答える)

位置非依存コードの問題に関する優れたリソースは次のとおりです。 http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/

説明したように、x86 には 15 ビット ジャンプ範囲以外には、私の知る限りではありませんし、無条件ジャンプや呼び出しにも対応していません。そのため、(ジェネレーターからの) 32K を超える関数は常に問題となり、埋め込みトランポリンが必要でした。

しかし、Linux のような一般的な x86 OS では、SO/DLL ファイルが gcc スイッチ -fpic (間接ジャンプ テーブルの使用を強制します)。そうしないと、通常のリンカーが再配置するのと同じようにコードが修正されるだけだからです。しかし、これを実行している間、コードセグメントは共有不可能になり、コードをディスクからメモリに完全にマッピングし、使用する前にすべてにアクセスする必要があります(ほとんどのキャッシュを空にし、TLBにアクセスする)など。これは遅いと考えられていた時代がありました...遅すぎる。

したがって、あなたにはもう何のメリットもありません。

どの OS (Solaris または FreeBSD) で Unix ビルド システムに問題が発生したのか思い出せません。なぜなら、私はこれを実行していなかったので、適用するまでなぜクラッシュするのか疑問に思っていたからです。 -fPICgcc.

動的リンクは、 LGPL のように、いくつかのライセンス要件を満たすための唯一の実用的な方法でありますます。

私は dnmckee が言及した点に同意します。さらに、次のことに同意します。

  • 静的にリンクされたアプリケーションは、不足している場合や間違った場所にインストールされている場合に問題を引き起こす可能性がある追加のファイル依存関係 (.dll / .so) が少ないかまったくないため、展開が簡単になる可能性があります。

静的にリンクされたビルドを行うための一つの理由は、すべてのシンボル参照が正しく解決されること、すなわち、あなたが実行可能ファイルの完全な閉鎖を持っていることを確認することです。

は継続的な統合を使用して構築され、テストされていた大規模なシステムの一部として、夜間の回帰テストは実行ファイルの静的にリンクされたバージョンを使用して実行されました。時折、我々はシンボルが解決されないだろうと静的リンクを動的にリンクされた実行可能ファイルが正常にリンクするにもかかわらず、失敗することがわかります。

これは、通常、静的にそれほどのリンクをしません深い共有ライブラリ内に設置されたシンボルはスペルミスの名前を持っていたときに発生するとされました。あなたは完全な閉鎖を持っていない動的にリンクされた実行ファイルに仕上げることができるように、ダイナミックリンカは完全に関係なく、深さ優先または幅優先の評価を使用するのではなく、すべてのシンボルを解決しません。

1/ 私は、動的リンクと静的リンクのベンチマークが行われたプロジェクトに参加しましたが、その差が動的リンクに切り替えるほど小さいとは判断されませんでした (私はテストに参加していませんでした。結論だけを知っているだけです)

2/ ダイナミック リンクは、PIC (位置独立コード、ロードされるアドレスに応じて変更する必要のないコード) に関連付けられることがよくあります。アーキテクチャによっては、PIC はさらなる速度低下を引き起こす可能性がありますが、2 つの実行可能ファイル (OS がセキュリティ対策としてロード アドレスのランダム化を使用している場合は、同じ実行可能ファイルの 2 つのプロセスでも) 間で動的にリンクされたライブラリを共有する利点を得るために必要です。すべての OS が 2 つの概念を分離できるかどうかはわかりませんが、Solaris と Linux は分離できますし、HP-UX の ISTR も同様です。

3/ 私は、「簡単パッチ」機能にダイナミック リンクを使用する他のプロジェクトに参加しました。しかし、この「簡単なパッチ」により、小さな修正の配布は少し簡単になりますが、複雑な修正の配布はバージョン管理の悪夢になります。間違ったバージョンがトークンだったために、すべてをプッシュしなければならず、さらに顧客サイトで問題を追跡しなければならないという結果になることもよくありました。

私の結論は、次の場合を除いて静的リンクを使用したということです。

  • 動的リンクに依存するプラグインなどの場合

  • 共有が重要な場合 (C/C++ ランタイム、GUI ライブラリなど、複数のプロセスで同時に使用される大きなライブラリなど)多くの場合、独立して管理され、ABI が厳密に定義されています)

「簡単なパッチ」を使用したい場合は、ライブラリは上記の大きなライブラリと同じように管理する必要があると私は主張します。これらは、修正によって変更されてはならない定義済みの ABI とほぼ独立している必要があります。

これは本当に、非常に単純です。あなたは、ソースコードの変更を行うと、あなたはそれを構築するために10分または20秒待つしたいですか? 20秒は、私が我慢できるすべてです。それを超えて、私はどちらか剣を出すか、私は別のコンパイルを使用することができますし、リンクが快適ゾーンにそれを戻すために方法についての思考を開始します。

システムでUnixライクな、動的リンクは、アウト・オブ・ウェイの場所にインストール共有ライブラリを使用してアプリケーションを使用する「ルート」のために生活が困難になることができます。ダイナミックリンカは、一般的にroot権限を持つプロセスに対してLD_LIBRARY_PATHまたはそれと同等に注意を払っていないためです。時には、それから、静的リンクは、一日を保存します。

また、インストールプロセスがライブラリを検索する必要がありますが、それはそれが困難なソフトウェアの複数のバージョンがマシンに共存するために作ることができます。

動的リンクは、OSが動的ライブラリを見つけ、それをロードするための余分な時間を要します。静的リンクでは、すべてが一緒にいると、それはメモリにワンショット負荷である。

また、 DLL地獄を参照してください。これは、DLL OSの負荷ことは、アプリケーションに付属の1、またはバージョンのアプリケーションを期待していることではありません。

シナリオです

は、動的リンクのための最良の例は、ライブラリが使用されるハードウェアに依存している場合。古代ではC数学ライブラリは、各プラットフォームはそれを最適化するために、すべてのプロセッサ機能を使用することができるように、動的にすることを決めた。

アンさらに良い例では、OpenGLのかもしれません。 OpenGLは、AMDとNVIDIAによって異なる方法で実装されたAPIです。そして、あなたは、ハードウェアが異なるため、AMDカードにNVIDIAの実装を使用することができません。あなたはそのため、あなたのプログラムに静的にOpenGLをリンクすることはできません。動的リンクは、APIは、すべてのプラットフォーム用に最適化させるために、ここで使用されます。

まだ議論していないもう一つの問題は、ライブラリ内のバグを修正されます。

静的リンクを使用すると、ライブラリを再構築する必要がありますが、再リンクして実行ファイルをredestributeする必要がありますだけではなく。ライブラリはただ一つの実行で使用されている場合、これは問題ではないかもしれません。しかし、大きな痛みは必要性が再リンクや再配布することがより実行可能である。

動的リンクでは、あなただけの再構築と動的ライブラリを再配布し、あなたが行われています。

静的リンクはあなたのプログラム全体を再コンパイルする必要がある変更を行うためにinorderを、あなたにだけ、単一のexeファイルを提供します。ダイナミックであなただけのDLLに変更を加える必要がリンクして、あなたのexeファイルを実行すると、変更は、動的リンク(例:窓)でのアップデートとバグ修正を提供する方が簡単runtime.Itsでピックアップされるだろうに対します。

静的リンクの極端なレベルがアプリケーションとシステムのパフォーマンスに大きなプラスの影響を持つことができるシステムの広大な増加があります。

私は、多くの場合、今、ますます汎用オペレーティング・システムを使用しているそれらの多くは、「組み込みシステム」と呼ばれているものを指し、これらのシステムは、すべての想像のために使用されます。

アン極めて一般的な例は、 Busyboxのに使用してGNU / Linuxシステムを使用してデバイスです。私はのNetBSD のブート可能I386を構築することにより(32ビット)システムイメージと極端にこれを撮影しましたの自体に含まれているすべてのプログラムのすべての(だけでなく、最後のカウント274で)へのハードリンクを持つ単一の静的にリンクされた(crunchgenによって)バイナリが含まれているカーネルとルートファイルシステム、後者の両方を含んでいます標準のフル機能のシステムプログラム(ツールチェインを除くほとんど)、そしてそれは20未満のメガのサイズのバイト(そしておそらくルートファイルシステムとメモリの唯一の64メガバイト(とシステムに非常に快適に動作します圧縮されていないと、完全に)RAMに、私は上でそれをテストするので、小さなものを)見つけることができませんされてきたもののます。

静的にリンクされたバイナリの起動時間は(と、それはの多くの可能速い)高速ですが、それは絵の一部に過ぎないことを、以前の記事で言及されていますすべてのオブジェクト・コードは、同じファイルにリンクされている場合は特に、およびオペレーティングシステムのサポートは、実行可能ファイルからのコードの直接のページングを要求し、さらに場合は特に。この理想的なシナリオでは、プログラムの起動時間は、コードのほぼすべてのページが既にメモリ内にあり、シェルによって使用中である(そして、実行される可能性があります、他のバックグラウンド・プロセスをinit)されますので、の文字通りのごくわずかです、おそらくメモリの1ページのみがプログラムの実行時の要件を満たすためにロードする必要があるため要求されたプログラムは、これまでのブート以降に実行されていない場合でもます。

しかし、それはまだ全体の話ではありません。私はまた、通常、静的リンクすることによって私の完全な開発システムのすべてのバイナリNetBSDオペレーティングシステムのインストールを構築し、使用しています。これはまだ、(1はすべてのプログラム別〜2.5ギガバイトために利用可能な完全なデバッグ・シンボル・テーブルを保持している場合は特に)、結果を膨大な量より多くのディスクスペース(ツールチェインとX11の静的リンクを含むすべてのもの、とx86_64のための〜6.6ギガバイトの合計)を取るにもかかわらずより速く、全体的な、そしていくつかのタスクのためのランでも趣旨は、ライブラリのコードページを共有することを、一般的なダイナミック・リンクシステムより少ないメモリを使用しています。ディスクは、比較的安価でもあるが、CPUサイクルが実際にはなく、すべてのプロセスのためにld.soの起動コストを支払う頻繁にディスク・ファイルを使用したキャッシュへの格安(でも高速なディスク)、およびメモリであることを開始し、のすべてのの時間は開始は、開発システム上のコンパイラとして、同じプログラムが何度も使用されている場合は特に、離れて多くのプロセスを開始する必要なタスクから時間とCPUサイクルの時間がかかります。静的にリンクされたツールチェーンプログラムは、の時間のことで、私のシステムのためのビルド時間を全体-OSのマルチアーキテクチャを減らすことができます。私は、単一のcrunchgen'edバイナリにツールチェーンを構築するためには至っていないが、私はので、CPUのキャッシュのための勝利の保存されたビルド時間のより多くの時間があるだろうかとき、私は疑っています。

静的リンク単一の実行可能ファイルのプログラムのニーズというファイルが含まれます。

動的リンクを使用すると、通常のを検討するものです、それはまだDLLを必要とし、同じディレクトリにある(またはのDLLをシステムフォルダにすることができる)実行可能ということになります。

(DLL = のダイナミックリンクのライブラリー)

動的にリンクされた実行可能ファイルは、より速くコンパイルおよびリソース重いとしてではありませんされます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top