Lien statique vs lien dynamique

y a-t-il des raisons impérieuses de performance pour choisir la liaison statique plutôt que la liaison dynamique ou vice versa dans certaines situations? J'ai entendu ou lu ce qui suit, mais je n'en sais pas assez sur le sujet pour me porter garant de sa véracité.

1) la différence de performance d'exécution entre la liaison statique et la liaison dynamique est généralement négligeable.

2) (1) n'est pas vrai si on utilise un compilateur de profils qui utilise des données de profil pour optimiser le programme hotpaths parce qu'avec la liaison statique, le compilateur peut optimiser à la fois votre code et le code de la bibliothèque. Avec dynamic linking, seul votre code peut être optimisé. Si la plupart du temps est consacré à l'exécution code de la bibliothèque, cela peut faire une grande différence. Dans le cas contraire, le paragraphe (1) s'applique toujours.

349
demandé sur Tim 2010-01-03 03:06:12

15 réponses

  • Dynamique "151930920 de" liant " peut réduire la consommation des ressources (si plus d'un processus de partage la même bibliothèque (y compris la version en "le même", bien sûr)). Je crois que c'est l'argument qui motive sa présence dans la plupart des environnements. Ici, "ressources" inclut l'espace disque, la mémoire vive et l'espace de cache. Bien sûr, si votre linker dynamique n'est pas suffisamment flexible, il y a un risque de DLL enfer .
  • lien dynamique signifie que les corrections de bogues et les mises à niveau vers les bibliothèques propagent pour améliorer votre "produit 1519150920" sans exiger que vous expédiez quoi que ce soit.
  • Plugins toujours appeler pour dynamique lien.
  • lien statique , signifie que vous pouvez savoir que le code sera exécuté en très environnements limités (au début du processus de démarrage, ou en mode de secours).
  • Statique "151930920 de" liant " peut faire binaires plus facile à distribuer à la diversité des environnements d'utilisateur (lors de l'envoi de la grande et de plus en plus gourmandes en ressources du programme).
  • Statique "151930920 de" liant " peut permettre un peu démarrage plus rapide temps, mais cela dépend dans une certaine mesure de la taille et complexité de votre programme et sur les détails de la stratégie de chargement OSs.

quelques modifications pour inclure les suggestions très pertinentes dans les commentaires et dans d'autres réponses. Je voudrais noter que la façon dont vous rompez avec ça dépend beaucoup de l'environnement dans lequel vous prévoyez de courir. Les systèmes intégrés minimaux peuvent ne pas avoir suffisamment de ressources pour soutenir la liaison dynamique. Légèrement plus petites systèmes de soutien linking, parce que leur mémoire est suffisamment petite pour rendre les économies de RAM de linking dynamique très attrayantes. Les PC grand public ont, comme le souligne Mark, d'énormes ressources, et vous pouvez probablement laisser les problèmes de commodité vous conduire à réfléchir sur cette question.


pour répondre aux questions de performance et d'efficacité: cela dépend .

classiquement, les bibliothèques dynamiques nécessitent une sorte de couche de colle ce qui signifie souvent une double répartition ou une couche supplémentaire d'indirection dans l'adressage de la fonction et peut coûter un peu de vitesse (mais le temps d'appel de la fonction est-il réellement une grande partie de votre temps d'exécution???).

cependant, si vous exécutez plusieurs processus qui appellent tous beaucoup la même bibliothèque, vous pouvez finir par sauver des lignes de cache (et donc gagner sur la performance d'exécution) en utilisant la relation de lien dynamique en utilisant la liaison statique. (Sauf si les OS modernes sont assez intelligents pour remarquer segments identiques dans statiquement binaires. Semble difficile, quelqu'un sait?)

un autre problème: le temps de chargement. Vous payez les frais de chargement à un moment donné. Quand vous payez ce coût dépend de la façon dont le système d'exploitation fonctionne ainsi que ce lien que vous utilisez. Peut-être que tu préférerais reporter le paiement jusqu'à ce que tu saches que tu en as besoin.

notez que la liaison statique-vs-dynamique est traditionnellement et non un problème d'optimisation, parce qu'ils impliquent tous les deux compilation jusqu'aux fichiers d'objets. Cependant, cela n'est pas nécessaire: un compilateur peut en principe "compiler" des "bibliothèques statiques" à une forme AST digérée initialement, et les "relier" en ajoutant ces AST à ceux générés pour le code principal, ce qui permet une optimisation globale. Aucun des systèmes que j'utilise ce faire, donc je ne peux pas commenter sur la façon dont il fonctionne.

la façon de répondre aux questions sur les performances est toujours en testant (et en utilisant un environnement d'essai comme tout comme le déploiement de l'environnement que possible).

309
répondu dmckee 2014-04-26 01:18:41

liaison dynamique est le seul moyen pratique de répondre à certaines exigences de licence telles que la LGPL .

63
répondu Mark Ransom 2010-01-03 05:01:09

1) est basé sur le fait que l'appel à une fonction DLL utilise toujours un saut indirect supplémentaire. Aujourd'hui, c'est généralement négligeable. À l'intérieur de la DLL il y a un peu plus de overhead sur i386 CPU, parce qu'ils ne peuvent pas générer de code indépendant de position. Sur amd64, les sauts peuvent être relatifs au compteur de programme, donc c'est une énorme amélioration.

2) Ceci est correct. Avec des optimisations guidées par le profilage Vous pouvez habituellement gagner environ 10-15 pour cent de performance. Maintenant que la vitesse CPU a atteint ses limites, il pourrait être intéressant de le faire.

j'ajouterais: (3) le linker peut organiser les fonctions dans un regroupement plus efficace du cache, de sorte que les erreurs coûteuses du niveau du cache sont minimisées. Il pourrait aussi affecter particulièrement le temps de démarrage des applications (basé sur les résultats que j'ai vu avec le compilateur Sun C++)

et n'oubliez pas qu'avec la DLL aucune élimination de code mort ne peut être effectuée. Selon la langue, le code DLL peut ne pas être de façon optimale. Les fonctions virtuelles sont toujours virtuelles parce que le compilateur ne sait pas si un client l'écrira ou non.

pour ces raisons, dans le cas où il n'y a pas besoin réel de DLL, puis il suffit d'utiliser la compilation statique.

MODIFIER (pour répondre à un commentaire, une par utilisateur trait de soulignement)

Voici une bonne ressource au sujet de la position code indépendant problème http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries /

comme expliqué x86 ne les a pas AFAIK pour autre chose que des gammes de sauts de 15 bits et pas pour des sauts et des appels inconditionnels. C'est pourquoi les fonctions (à partir de générateurs) ayant plus de 32K ont toujours été un problème et ont besoin de trampolines intégrés.

mais sur les systèmes d'exploitation x86 populaires comme Linux, vous n'avez pas besoin de vous soucier si le fichier SO/DLL n'est pas généré avec le gcc switch -fpic (qui renforce l'utilisation des tables de saut indirect). Parce que si vous ne le faites pas, le code est juste réparé comme un linker normal le relocaliserait. Mais en faisant cela il rend le segment de code non partageable et il aurait besoin d'un mappage complet du code du disque dans la mémoire et le toucher tout avant qu'il ne puisse être utilisé (vider la plupart des caches, frapper TLB's) etc. Il fut un temps où cela était considéré comme lent ... trop lent.

pour que vous n'ayez plus aucun avantage.

Je ne me rappelle pas ce que L'OS (Solaris ou FreeBSD) m'a donné comme problèmes avec mon système de compilation Unix parce que je ne le faisais pas et je me suis demandé pourquoi il s'est écrasé jusqu'à ce que j'applique -fPIC à gcc .

62
répondu Lothar 2017-05-03 02:20:47

je suis d'accord avec les points mentionnés par dnmckee, plus:

  • les applications liées statiquement pourraient être plus faciles à déployer, car il y a moins ou pas de dépendances de fichiers supplémentaires (.dll/.donc) qui pourrait causer des problèmes quand ils sont manquants ou installés au mauvais endroit.
42
répondu stakx 2010-01-03 00:16:24

une des raisons de faire une compilation liée statiquement est de vérifier que vous avez une fermeture complète pour l'exécutable, c'est-à-dire que toutes les références de symboles sont résolues correctement.

faisant partie d'un grand système en cours de construction et d'essai par intégration continue, les essais de régression de nuit ont été effectués à l'aide d'une version statiquement liée des exécutables. De temps en temps, nous verrions qu'un symbole ne résoudrait pas et le lien statique échouerait même si le un exécutable lié dynamiquement se lierait avec succès.

cela se produisait habituellement lorsque les symboles qui étaient profondément ancrés dans les libs partagés avaient un nom mal orthographié et donc ne serait pas lié statiquement. Le linker dynamique ne résout pas complètement tous les symboles, indépendamment de l'utilisation de la première évaluation de la profondeur ou de la première évaluation de la largeur, de sorte que vous pouvez terminer avec un exécutable lié dynamiquement qui n'a pas la fermeture complète.

31
répondu Rob Wells 2012-12-22 18:55:31

1 / j'ai été sur des projets où la liaison dynamique vs la liaison statique a été mise à l'essai et la différence n'a pas été déterminée assez petite pour passer à la liaison dynamique (Je ne faisais pas partie de l'essai, je sais juste la conclusion)

2 / La liaison dynamique est souvent associée au PIC (code indépendant de la Position, code qui n'a pas besoin d'être modifié en fonction de l'adresse à laquelle il est chargé). Selon l'architecture PIC peut apporter un autre ralentissement, mais est nécessaire afin d'obtenir l'avantage de partager une bibliothèque dynamiquement liée entre deux exécutables (et même deux processus du même exécutable si le système d'exploitation utilise la randomisation de l'adresse de chargement comme mesure de sécurité). Je ne suis pas sûr que tous les OS permettent de séparer les deux concepts, mais Solaris et Linux font et ISTR que HP-UX fait aussi.

3/ j'ai été sur d'autres projets qui ont utilisé la liaison dynamique pour le "facile patch". Mais ce "patch facile" rend la distribution de petit fix un peu plus facile et d'un compliqué un cauchemar vertigineux. Nous avons souvent fini par avoir à tout mettre en place et à suivre les problèmes sur le site du client parce que la mauvaise version était token.

ma conclusion est que j'ai utilisé la liaison statique excepté:

  • pour des choses comme les plugins qui dépendent de la liaison dynamique

  • lorsque le partage est important (grandes bibliothèques utilisées par plusieurs processus à la fois comme C/C++ runtime, GUI libraries, ... qui sont souvent gérés indépendamment et pour lesquels L'ABI est strictement défini)

si l'on veut utiliser le "patch facile", je dirais que les bibliothèques doivent être gérées comme les grandes bibliothèques ci-dessus: elles doivent être presque indépendantes avec un ABI défini qui ne doit pas être modifié par des correctifs.

21
répondu AProgrammer 2010-01-03 10:03:18

ce discute en détail sur les bibliothèques partagées sur linux et l'impliaction de performance.

19
répondu nos 2010-01-03 00:17:14

sur les systèmes de type Unix, la liaison dynamique peut rendre la vie difficile à "root" d'utiliser une application avec les bibliothèques partagées installées dans des endroits éloignés. Cela est dû au fait que le linker dynamique ne fait généralement pas attention à LD_LIBRARY_PATH ou à son équivalent pour les processus avec des privilèges root. Parfois, puis, la liaison statique sauve la journée.

alternativement, le processus d'installation doit localiser les bibliothèques, mais cela peut rendre difficile pour plusieurs versions du logiciel coexister sur la machine.

10
répondu Jonathan Leffler 2010-01-04 19:15:05

C'est assez simple, vraiment. Lorsque vous effectuez un changement dans votre code source, ne vous attendez 10 minutes de construire ou de 20 secondes? Vingt secondes, c'est tout ce que je peux supporter. Au-delà de cela, soit je sors l'épée ou commencer à penser à la façon dont je peux utiliser compilation séparée et lien pour le ramener dans la zone de confort.

10
répondu Hans Passant 2018-05-03 08:49:24

la liaison Dynamique qui nécessite du temps supplémentaire pour le système d'exploitation pour trouver la dynamique de la bibliothèque et de la charge. Avec la liaison statique, tout est réuni et c'est une charge unique dans la mémoire.

voir Aussi l'Enfer des DLL . C'est le scénario où la DLL que charge L'OS n'est pas celle qui est venue avec votre application, ou la version que votre application attend.

7
répondu Thomas Matthews 2010-01-03 00:40:53

le meilleur exemple de lien dynamique est lorsque la bibliothèque dépend du matériel utilisé. Dans les temps anciens, la bibliothèque de mathématiques C a été décidé d'être dynamique, de sorte que chaque plate-forme peut utiliser toutes les capacités du processeur pour l'optimiser.

un meilleur exemple pourrait être OpenGL. OpenGl est une API qui est implémentée différemment par AMD et NVidia. Et vous n'êtes pas en mesure d'utiliser une implémentation NVidia sur une carte AMD, parce que le matériel est différent. Vous ne pouvez pas lier OpenGL statically dans votre programme, à cause de cela. La liaison dynamique est utilisée ici pour permettre à L'API d'être optimisée pour toutes les plateformes.

7
répondu Arne 2015-02-12 01:52:32

un autre problème non encore discuté est la correction de bogues dans la bibliothèque.

avec les liens statiques, vous n'avez pas seulement à reconstruire la bibliothèque, mais vous devrez relink et redestribute l'exécutable. Si la bibliothèque n'est utilisée que dans un seul exécutable, cela peut ne pas être un problème. Mais plus les exécutables doivent être relancés et redistribués, plus la douleur est grande.

avec la liaison dynamique, vous venez de reconstruire et redistribuer la Bibliothèque dynamique et vous êtes fait.

5
répondu R Samuel Klatchko 2010-01-03 08:31:46

lien statique vous donne seulement un exe simple, inorder pour faire un changement que vous avez besoin de recompiler votre programme entier. Alors que dans dynamic linking vous devez faire des changements uniquement à la dll et quand vous exécutez votre exe, les changements seront repris à l'exécution.Il est plus facile de fournir des mises à jour et des corrections de bugs par liaison dynamique (par exemple: windows).

3
répondu Govardhan Murali 2016-10-11 01:35:30

il existe un nombre considérable et croissant de systèmes où un niveau extrême de liaison statique peut avoir un impact positif énorme sur les applications et les performances du système.

je me réfère à ce que l'on appelle souvent les" systèmes embarqués", dont beaucoup utilisent de plus en plus des systèmes d'exploitation à usage général, et ces systèmes sont utilisés pour tout ce qui est imaginable.

un exemple extrêmement commun sont les dispositifs utilisant les systèmes GNU / Linux utilisant Busybox . J'ai pris cela à l'extrême avec NetBSD en construisant une image de système amorçable i386 (32-bit) qui inclut à la fois un noyau et son système de fichier racine, ce dernier qui contient un binaire simple statique-lié (par crunchgen ) avec des liens durs à tous les programmes qui contient tous (bien au dernier compte 274) des programmes de système complet standard (la plupart sauf la chaîne d'outils), et il est moins que (20) mega octets de taille (et fonctionne probablement très confortablement dans un système avec seulement 64 Mo de mémoire (même avec le système de fichiers racine non compressé et entièrement en RAM), bien que j'ai été incapable de trouver un si petit pour le tester sur).

il a été mentionné dans des billets précédents que le temps de démarrage d'un binaire static-linked est plus rapide (et il peut être un lot plus rapide), mais ce n'est qu'une partie de l'image, surtout quand tous les objets le code est lié dans le même fichier, et encore plus particulièrement lorsque le système d'exploitation prend en charge le pagage de demande de code directement à partir du fichier exécutable. Dans ce scénario idéal, le temps de démarrage des programmes est littéralement négligeable puisque presque toutes les pages de code seront déjà en mémoire et seront utilisées par le shell (et et init tout autre processus de fond qui pourrait être en cours d'exécution), même si le programme demandé n'a jamais été exécuté depuis le démarrage, car peut-être seulement une page de mémoire doit être chargée pour répondre aux exigences d'exécution du programme.

cependant ce n'est pas encore toute l'histoire. En outre, je construis et utilise généralement le système D'exploitation NetBSD installe pour mes systèmes de développement complet par liaison statique tous les binaires. Même si cela prend beaucoup plus d'espace disque (~6,6 Go au total pour x86_64 avec tout, y compris la chaîne d'outils et X11 static-linked) (surtout si on garde des tables de symboles de débogage disponibles pour tous programmes un autre ~ 2,5 GB), le résultat court toujours plus vite dans l'ensemble, et pour certaines tâches utilise même moins de mémoire qu'un système dynamique typique lié qui prétend partager des pages de code de bibliothèque. Le disque est bon marché (même le disque rapide), et la mémoire pour mettre en cache les fichiers de disque fréquemment utilisés est également relativement bon marché, mais les cycles CPU ne sont vraiment pas, et payer le coût de démarrage ld.so pour chaque processus qui commence chaque le temps qu'il commence prendra des heures et des heures de cycles CPU loin des tâches qui nécessitent de départ de nombreux processus, en particulier lorsque ces programmes sont utilisés, tels que les compilateurs sur un système de développement. Les programmes de chaînes d'outils statiques peuvent réduire les temps de construction multi-architectures pour L'ensemble de mes systèmes de heures . Je n'ai pas encore construit la chaîne d'outils dans mon unique binaire crunchgen 'ed, mais je soupçonne que lorsque je le ferai, il y aura plus d'heures de temps de compilation économisées en raison de la victoire pour le cache CPU.

2
répondu Greg A. Woods 2017-07-28 22:19:30

la liaison statique inclut les fichiers dont le programme a besoin dans un seul fichier exécutable.

la liaison dynamique est ce que vous considéreriez comme l'habituel, il rend un exécutable qui nécessite encore DLLs et tel pour être dans le même répertoire (ou les DLLs pourraient être dans le dossier système).

(DLL = lien dynamique bibliothèque)

les exécutables dynamiquement liés sont compilés plus rapidement et ne sont pas aussi ressources-lourds.

1
répondu Nykal 2017-09-05 12:01:51