1) est basé 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. À l'intérieur de la DLL, il y a un peu plus de surcharge sur les CPU i386, car ils ne peuvent pas générer de code indépendant de la position. Sur amd64, les sauts peuvent être relatifs au compteur du programme, ce qui constitue une amélioration considérable.
2) C'est correct. Avec des optimisations guidées par le profilage, vous pouvez généralement gagner environ 10 à 15 % de performance. Maintenant que la vitesse du CPU a atteint ses limites, cela peut valoir la peine de le faire.
J'ajouterais : (3) l'éditeur de liens peut arranger les fonctions dans un groupement plus efficace pour le cache, de sorte que les coûteux manques au niveau du cache soient minimisés. Cela pourrait aussi avoir un effet particulier sur le temps de démarrage des applications (d'après les résultats que j'ai vus avec le compilateur C++ de Sun).
Et n'oubliez pas qu'avec les DLL, il n'est pas possible d'éliminer les codes morts. Selon le langage, le code de la DLL peut ne pas être optimal non plus. Les fonctions virtuelles sont toujours virtuelles car le compilateur ne sait pas si un client les écrase.
Pour ces raisons, s'il n'y a pas de réel besoin de DLL, il suffit d'utiliser la compilation statique.
EDIT (pour répondre au commentaire, par le soulignement de l'utilisateur)
Voici une bonne ressource sur le problème du code indépendant de la position http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/
Comme expliqué, le x86 ne les a pas AFAIK pour autre chose que les plages de saut de 15 bits et pas pour les sauts et les appels inconditionnels. C'est pourquoi les fonctions (des générateurs) ayant plus de 32K ont toujours été un problème et ont nécessité des trampolines intégrés.
Mais sur les systèmes d'exploitation x86 courants comme Linux, vous n'avez pas besoin de vous soucier du fait que le fichier .so/DLL n'est pas généré avec la commande gcc
commutateur -fpic
(qui impose l'utilisation des tables de saut indirect). Parce que si vous ne le faites pas, le code est juste fixé comme un linker normal le relocaliserait. Mais en faisant cela, cela rend le segment de code non partageable et il faudrait un mappage complet du code du disque vers la mémoire et le toucher avant de pouvoir l'utiliser (vider la plupart des caches, frapper les TLB), etc. Il fut un temps où cela était considéré comme lent.
Vous n'auriez donc plus aucun avantage.
Je ne me souviens pas quel système d'exploitation (Solaris ou FreeBSD) m'a posé des problèmes avec mon système de construction Unix, car je ne le faisais pas et je me demandais pourquoi il plantait jusqu'à ce que j'applique la méthode suivante -fPIC
à gcc
.
78 votes
"Avec la liaison statique, le compilateur peut optimiser le code de la bibliothèque", mais seulement s'il la compile aussi ! Si vous vous contentez de lier des fichiers objets précompilés, votre compilateur n'a pas la possibilité de les optimiser.
3 votes
Si c'est vrai, alors vous avez raison, mais on peut se demander dans quelle mesure cela est vrai avec les compilateurs modernes. Si quelqu'un peut le vérifier d'une manière ou d'une autre, ce serait formidable.
5 votes
Avec un compilateur qui compile en code natif (comme la plupart des compilateurs C/C++), il n'y a plus de possibilité d'optimisation du code. Si le code est compilé dans un langage intermédiaire (comme .Net IL), le compilateur JIT est invoqué lorsque la bibliothèque est chargée pour la compiler en code natif. Cette compilation finale peut s'améliorer de plus en plus avec le temps, au fur et à mesure que le compilateur JIT évolue.
3 votes
@Eloff : VS2008 fait exactement cela avec LTCG activé. (Les fichiers lib deviennent énormes, cependant ) J'ai joué avec et pour quelqu'un qui s'intéresse à "ce que mon compilateur peut faire pour moi", ce n'est rien de moins qu'étonnant.