Question

Y a-t-il des raisons de performances convaincantes pour choisir la liaison statique sur la liaison dynamique ou vice versa dans certaines situations? Je l'ai entendu ou lu ce qui suit, mais je ne sais pas assez sur le sujet à se porter garant de sa véracité.

1) La différence dans les performances d'exécution entre la liaison statique et la liaison dynamique est généralement négligeable.

2) (1) n'est pas vrai si vous utilisez un compilateur de profilage qui utilise les données de profil pour optimiser hotpaths du programme car avec la liaison statique, le compilateur peut optimiser à la fois votre code et le code de la bibliothèque. Avec la liaison dynamique que votre code peut être optimisé. Si la plupart du temps est consacré à l'exécution du code bibliothèque, cela peut faire une grande différence. Dans le cas contraire, (1) applique encore.

Était-ce utile?

La solution


Certaines modifications à inclure les suggestions très pertinentes dans les commentaires et dans d'autres réponses. Je tiens à souligner que la façon dont vous cassez sur cela dépend beaucoup sur quel environnement vous envisagez d'exécuter dans. Les systèmes embarqués minimes ne peuvent pas disposer de ressources suffisantes pour soutenir la liaison dynamique. Un peu de petits systèmes plus grands peuvent bien soutenir la liaison dynamique, parce que leur mémoire est assez petit pour faire des économies de RAM dynamique de liaison très attrayante. PC grand public Full Blown ont, comme le fait remarquer Mark, des ressources énormes, et vous pouvez probablement laisser les problèmes de proximité conduisent votre pensée à ce sujet.


Pour résoudre les problèmes de performance et d'efficacité: il dépend

.

Classiquement, les bibliothèques dynamiques ont besoin d'une certaine forme de couche de colle qui signifie souvent le double expédition ou une couche supplémentaire d'indirection en fonction d'adressage et peut coûter un peu de vitesse (mais est fonction de temps d'appel en fait une grande partie de votre temps de marche ?? ?).

Cependant, si vous exécutez plusieurs processus qui tous les appels de la même bibliothèque beaucoup, vous pouvez finir par des lignes de cache sauvegarde (et gagner ainsi des performances en cours d'exécution) lors de l'utilisation dynamique de liaison par rapport à l'aide de la liaison statique. (À moins d'OS de modernes sont assez intelligents pour remarquer segments identiques dans les binaires liés statiquement. Semble dur, quelqu'un sait?)

Une autre question: le temps de chargement. Vous payez les frais de chargement à un moment donné. Lorsque vous payez ce coût dépend de la façon dont le système d'exploitation fonctionne aussi bien que ce que vous liant l'utilisation. Peut-être que vous préférez payer rebutés jusqu'à ce que vous savez que vous avez besoin.

Notez que l'enchaînement statique vs dynamique est traditionnellement pas un problème d'optimisation, car ils impliquent tous deux la compilation séparée vers les fichiers objets. Cependant, ce n'est pas nécessaire: un compilateur peut en principe « à une forme AST digéré initialement, et » « compiler » « bibliothèques statiques les liens » en ajoutant ces RSHS à ceux générés par le code principal, donnant ainsi les moyens d'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 à des questions de performance est toujours en testant (et utiliser un environnement de test autant que l'environnement de déploiement possible).

Autres conseils

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

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

Je voudrais ajouter: (3) l'éditeur de liens peut organiser des fonctions dans un cache plus efficace regroupement, de sorte que manque de niveau de cache coûteux sont réduits au minimum. Il peut également effectuer en particulier le temps de démarrage des applications (en fonction des résultats que j'ai vu avec le compilateur C du Soleil)

Et ne pas oublier que sans l'élimination de code mort de DLL peut être effectuée. En fonction de la langue, le code de DLL peut-être pas optimale non plus. Les fonctions virtuelles sont toujours virtuel, car le compilateur ne sait pas si un client est le remplacer.

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.

EDIT (pour répondre à ce commentaire, par underscore utilisateur)

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

Comme expliqué x86 ne les a pas pour autant que je sache quoi que ce soit d'autre, alors les plages de saut 15 bits et non pas pour des sauts inconditionnels et des appels. C'est pourquoi les fonctions (de générateurs) ayant plus de 32K ont toujours été un problème et trampolines embarqués nécessaires.

Mais sur OS x86 populaires comme Linux vous n'avez juste besoin de prendre soin si le fichier SO / DLL est pas généré avec le gcc commutateur -fpic (qui impose l'utilisation des tables de sauts indirects). Parce que si vous ne le faites pas, le code est simplement fixé comme un agent de liaison normale serait relocaliser. Mais tout en faisant cela, il fait le segment de code non partageable et il aurait besoin d'une cartographie complète du code à partir du disque dans la mémoire et le toucher tout avant qu'il puisse être utilisé (vider la plupart des caches, frapper TLB de) etc. Il y avait un temps quand cela a été considéré comme lent ... trop lent.

Alors, vous n'auriez plus aucun avantage.

Je ne me rappelle pas ce système d'exploitation (Solaris ou FreeBSD) m'a donné des problèmes avec mon système de construction Unix parce que je ne faisais pas ce et se demande pourquoi il est écrasé jusqu'à ce que je -fPIC appliqué à gcc.

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

Je suis d'accord avec les points dnmckee REPONSES, plus:

  • statiquement les applications liées pourraient être plus faciles à déployer, car il y a moins ou pas de dépendances de fichiers supplémentaires (.dll / .so) qui pourraient causer des problèmes quand ils sont manquants ou installés au mauvais endroit.

L'une des raisons de faire une construction statique est de vérifier que vous avez la fermeture complète de l'exécutable, à savoir que toutes les références de symboles sont résolus correctement.

En tant que partie d'un grand système qui a été construit et testé à l'aide d'intégration continue, les tests de régression en soirée ont été effectuées en utilisant une version dynamique des exécutables. De temps en temps, nous verrions qu'un symbole ne résoudrait pas et le lien statique échouerait même si l'exécutable lié dynamiquement lierait avec succès.

C'était généralement se produit lorsque des symboles qui étaient profondément ancrés dans les bibliothèques partagées avaient un nom mal orthographié et donc ne serait pas un lien statique. L'éditeur de liens dynamique ne résout pas complètement tous les symboles, quelle que soit l'utilisation de l'évaluation en profondeur d'abord ou en largeur, donc vous pouvez finir avec un exécutable lié dynamiquement qui ne possède pas la fermeture complète.

1 / Je suis sur des projets où la liaison dynamique vs liaison statique a été étalonnées et la différence n'a pas été déterminé assez petit pour passer à la liaison dynamique (je ne faisais pas partie du test, je sais juste la conclusion)

2 / liaison dynamique est souvent associée à PIC (Position Indépendant du code, le code qui n'a pas besoin d'être modifié en fonction de l'adresse à laquelle il est chargé). Selon le PIC d'architecture peut apporter un nouveau ralentissement, mais est nécessaire pour obtenir des avantages de partager une bibliothèque liée dynamiquement entre deux exécutables (et même deux processus du même exécutable si le randomization utilisation du système d'exploitation d'adresse de charge en tant que 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 bien.

3 / J'ai été sur d'autres projets utilisant la liaison dynamique pour la fonction « patch facile ». Mais ce « patch facile » rend la distribution de petite solution un peu plus facile et d'un complexe un cauchemar de versioning. Nous avons souvent fini par avoir à pousser tout en plus d'avoir à suivre les problèmes sur le site client, car la mauvaise version était symbolique.

Ma conclusion est que je l'avais utilisé la liaison statique exceptés:

  • pour des choses comme plug-ins qui dépendent de liaison dynamique

  • lorsque le partage est important (grandes bibliothèques utilisées par plusieurs processus en même temps comme C / C ++ Runtime, les bibliothèques de l'interface graphique, ... qui sont souvent gérées de manière indépendante et pour lesquels l'ABI est strictement définie)

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:. Ils doivent être à peu près indépendante avec un ABI défini qui ne doit pas être modifié par des corrections

Cette discuter en détail sur les bibliothèques partagées sur les implications de Linux et de performance.

Il est assez simple, vraiment. Lorsque vous effectuez un changement dans votre code source, voulez-vous attendre 10 minutes pour qu'il construire ou 20 secondes? Vingt secondes est tout ce que je peux supporter. Au-delà de cela, je reçois soit l'épée ou commence à penser à la façon dont je peux utiliser la compilation séparée et liant pour le ramener dans la zone de confort.

Sur les systèmes Unix, liaison dynamique peut rendre la vie difficile pour les « root » pour utiliser une application avec les bibliothèques partagées installées dans hors sentiers battus endroits. En effet, l'éditeur de liens dynamique ne sera généralement pas prêter attention à LD_LIBRARY_PATH ou son équivalent pour les processus avec les privilèges root. Parfois, alors, la liaison statique enregistre le jour.

Vous pouvez également le processus d'installation doit localiser les bibliothèques, mais qui peut le rendre difficile pour plusieurs versions du logiciel à coexistant sur la machine.

Liaison dynamique nécessite un temps supplémentaire pour le système d'exploitation pour trouver la bibliothèque dynamique et le charger. Avec la liaison statique, tout est ensemble et il est une charge d'un coup dans la mémoire.

En outre, voir l'enfer des DLL . Tel est le scénario dans lequel la DLL que les charges OS est pas celui qui est venu avec votre application, ou la version que votre application attend.

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

Un exemple encore mieux peut-être OpenGL. OpenGl est une API qui est mis en œuvre différemment par AMD et NVidia. Et vous n'êtes pas en mesure d'utiliser une implémentation NVidia sur une carte AMD, car le matériel est différent. Vous ne pouvez pas lier OpenGL statiquement dans votre programme, à cause de cela. liaison dynamique est utilisé ici pour laisser l'API optimisée pour toutes les plateformes.

Une autre question pas encore discuté est la correction de bugs dans la bibliothèque.

Avec la liaison statique, vous avez non seulement de reconstruire la bibliothèque, mais vous devrez réassocier et redestribute l'exécutable. Si la bibliothèque est juste utilisée dans un exécutable, cela peut ne pas être un problème. Mais plus les executables qui doivent être Relinked et redistribué, plus la douleur est.

Avec la liaison dynamique, vous reconstruisez juste et redistribuez la bibliothèque dynamique et vous avez terminé.

liaison statique vous donne un seul exe, envue de faire un changement, vous devez recompiler votre programme. Alors que dans dynamique vous liant besoin de faire le changement que dans la dll et lorsque vous exécutez votre exe, les changements seraient pris en charge à runtime.Its plus facile de fournir des mises à jour et corrections de bugs par dynamique liaison. (Ex: fenêtres)

Il y a un vaste et un nombre croissant de systèmes où un niveau extrême de liaison statique peut avoir un énorme impact positif sur les applications et les performances du système.

Je me réfère à ce qu'on appelle souvent « systèmes embarqués », dont beaucoup sont maintenant de plus en plus utilisent des systèmes d'exploitation à usage général, et ces systèmes sont utilisés pour tout imaginables.

Un exemple très commun sont des dispositifs qui utilisent des systèmes GNU / Linux en utilisant Busybox . J'ai pris cela à l'extrême avec NetBSD en construisant une image système i386 de démarrage (32 bits) qui comprend à la fois un noyau et son système de fichiers racine, celui-ci qui contient un seul binaire statique lié (par crunchgen) avec liens physiques à tous les programmes qui se contient tous (bien au dernier décompte 274) du programmes standard par le système complet de fonctionnalités (la plupart à l'exception du toolchain), et il est inférieur à 20 mega octets de taille importante (et 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), mais je suis incapable de trouver un si petit pour le tester sur).

Il a été mentionné dans les messages précédents que le temps de démarrage d'un binaires statiques liés est plus rapide (et il peut être beaucoup plus rapide), mais qui ne représente qu'une partie de l'image, surtout quand tout le code objet est lié dans le même fichier, et encore plus particulièrement lorsque le système d'exploitation prend en charge la pagination du code de la demande directe 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 être utilisé par le shell (et et init tout autre processus de fond qui pourraient être en cours d'exécution) , même si le programme demandé n'a jamais été exécuté depuis le démarrage depuis peut-être qu'une seule page de la mémoire doit être chargée pour remplir les conditions d'exécution du programme.

Mais c'est pas encore toute l'histoire. Je construis aussi souvent et d'utiliser le système d'exploitation NetBSD installe mes systèmes de développement complet par tous les binaires statiques de liaison. Même si cela prend un espace énorme disque plus important montant (~ total de 6.6GB pour x86_64 avec tout, y compris toolchain et X11 statique lié) (en particulier si l'on garde les tables de symboles complet de débogage pour tous les programmes autre ~ 2.5GB), le résultat encore tourne plus vite dans l'ensemble, et pour certaines tâches utilise encore moins de mémoire qu'un système lié dynamique typique qui prétend partager des pages de code bibliothèque. Disk est pas cher (même disque rapide), et à la mémoire cache sont souvent des fichiers de disque utilisés est également relativement pas cher, mais les cycles de CPU vraiment pas, et de payer le coût de démarrage de ld.so pour chaque processus qui commence tous temps les mises en chantier prendre des heures et des heures de cycles CPU à des tâches qui nécessitent à partir de nombreux processus, en particulier lorsque les mêmes programmes sont utilisés encore et, comme les compilateurs sur un système de développement. programmes de l'ensemble des outils statiques liés peuvent réduire tout le temps-OS de construction multi-architecture pour mes systèmes par heures . Je n'ai pas encore à construire le toolchain dans mon seul binaire crunchgen'ed, mais je pense que quand je ne serai plus là heures de temps de construction enregistrée en raison de la victoire pour le cache du processeur.

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

liaison dynamique est ce que vous considérez l'habitude, il est un exécutable qui nécessite encore des DLL et comme être dans le même répertoire (ou les DLL pourraient être dans le dossier système).

(DLL = liens dynamiques bibliothèque)

executables compilés sont liés Dynamiquement plus rapidement et ne sont pas aussi lourds ressources.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top