Quel est le coût de performance d’exécution de l’inclusion d’une bibliothèque?

Existe-t-il une différence de performances d’exécution entre l’inclusion d’une bibliothèque entière (avec probablement des centaines de fonctions) et l’utilisation ultérieure d’une seule fonction, telle que:

#include int main(int argc, char *argv[]) { bar();//from library foo return 0; } 

Et entre le collage du fragment de code correspondant de la bibliothèque directement dans le code, par exemple:

 void bar() { ... } int main(int argc, char *argv[]) { bar();//defined just above return 0; } 

Qu’est-ce qui m’empêcherait d’inclure sans réfléchir toutes mes bibliothèques préférées (et les plus utilisées) au début de mes fichiers C? Ce fil de discussion populaire C / C ++: Détecter les #includes superflus? suggère que le temps de compilation augmenterait. Mais le binary compilé serait-il différent? Le deuxième programme serait-il plus performant que le premier?


En relation: que fait réellement #include dans le programme ca

Edit: la question ici est différente de la question connexe Y aura-t-il un impact sur les performances en incluant des fichiers d’en-tête inutilisés en C / C ++? question car ici il y a un seul fichier inclus. Je demande ici si l’inclusion d’un seul fichier est différente du copier-coller des fragments de code réellement utilisés dans la source. J’ai légèrement modifié le titre pour refléter cette différence.

Il n’y a pas de différence de performance en ce qui concerne le programme final. L’éditeur de liens ne liera que les fonctions réellement utilisées à votre programme. Les fonctions non utilisées présentes dans la bibliothèque ne seront pas liées.

Si vous incluez beaucoup de bibliothèques, la compilation du programme peut prendre plus de temps.

La principale raison pour laquelle vous ne devriez pas inclure toutes vos “bibliothèques préférées” est la conception de programme. Votre fichier ne doit inclure rien, sauf les ressources qu’il utilise, afin de réduire les dépendances entre les fichiers. Moins votre fichier en saura sur le rest du programme, mieux ce sera. Il devrait être aussi autonome que possible.

Ce n’est pas une simple question et ne mérite donc pas une réponse simple. Vous devrez peut-être prendre en compte un certain nombre d’éléments pour déterminer ce qui est le plus performant.

  1. Votre compilateur et éditeur de liens : Différents compilateurs optimiseront de différentes manières. C’est quelque chose qui est facilement négligé et qui peut poser des problèmes lors de la généralisation. Pour la plupart, les compilateurs et les lieurs modernes optimiseront le binary pour n’inclure que ce qui est nécessaire à 100% pour les exécutions. Cependant, tous les compilateurs n’optimiseront pas votre binary.
  2. Liaison dynamic : Il existe deux types de liaison lorsque vous utilisez d’autres bibliothèques. Ils se comportent de manière similaire, mais sont fondamentalement différents. Lorsque vous établissez un lien avec une bibliothèque dynamic, la bibliothèque rest séparée du programme et ne s’exécute qu’au moment de l’exécution. Les bibliothèques dynamics sont généralement appelées bibliothèques partagées et doivent donc être traitées comme si elles étaient utilisées par plusieurs fichiers binarys. Étant donné que ces bibliothèques sont souvent partagées, l’éditeur de liens ne supprimera aucune fonctionnalité de la bibliothèque car il ne sait pas quelles parties de cette bibliothèque seront nécessaires à tous les fichiers binarys de ce système ou de ce système d’exploitation. Pour cette raison, un fichier binary lié à une bibliothèque dynamic aura un impact limité sur les performances, en particulier immédiatement après le démarrage du programme. Cet impact sur les performances augmentera avec le nombre de liens dynamics.
  3. Liaison statique: lorsque vous liez un binary à une bibliothèque statique (avec un éditeur de liens optimisant), l’éditeur de liens “saura” les fonctionnalités dont vous aurez besoin de cette bibliothèque et supprimera les fonctionnalités qui ne seront pas utilisées dans votre binary résultant. De ce fait, le binary deviendra plus efficace et donc plus performant. Cela a toutefois un coût.

    par exemple

    Supposons que votre système d’exploitation utilise une bibliothèque de manière intensive dans un grand nombre de fichiers binarys du système entier. Si vous construisez cette bibliothèque en tant que bibliothèque partagée, tous les fichiers binarys partageront cette bibliothèque, tout en utilisant peut-être des fonctionnalités différentes. Supposons maintenant que vous liez statiquement chaque binary à une bibliothèque. Vous vous retrouveriez avec une duplication très importante des fonctionnalités binarys, car chaque binary aurait une copie de la fonctionnalité dont il avait besoin à partir de cette bibliothèque.

Conclusion: il convient de noter qu’avant de poser la question de savoir ce qui rendra mon programme plus performant, vous devriez probablement vous demander ce qui est plus performant dans votre cas. Votre programme a-t-il été conçu pour occuper la majeure partie de votre temps CPU, optez probablement pour une bibliothèque liée de manière statique. Si votre programme est exécuté occasionnellement, optez probablement pour une bibliothèque liée dynamicment afin de réduire l’utilisation du disque. Il est également intéressant de noter que l’utilisation d’une bibliothèque basée sur des en-têtes ne vous donnera qu’un gain de performance très marginal (voire pas du tout) par rapport à un binary lié statiquement, et augmentera considérablement votre temps de compilation.

Cela dépend énormément des bibliothèques et de leur structure, ainsi que de l’implémentation du compilateur.

L’éditeur de liens ( ld ) ld que le code de la bibliothèque référencée par le code. Par conséquent, si vous avez deux fonctions a et b dans une bibliothèque, mais uniquement des références à a fonction then, il se peut que le code final ne soit pas du tout. .

Les fichiers d’en-tête (include), s’ils ne contiennent que des déclarations, et si les déclarations n’entraînent pas de références à la bibliothèque, vous ne devriez voir aucune différence entre taper les parties dont vous avez besoin (selon votre exemple) et inclure la totalité. header de fichier.

Historiquement, l’éditeur de liens ld récupérait le code par les fichiers. Ainsi, chaque fonction a et b se b dans des fichiers différents lors de la création de la bibliothèque, il n’y aurait aucune conséquence.

Cependant, si la bibliothèque n’est pas construite avec soin, ou si l’implémentation du compilateur récupère chaque bit de code de la bibliothèque, que cela soit nécessaire ou non, vous risquez d’avoir des conséquences sur les performances, car votre code sera plus gros et plus difficile à adapter. dans le cache de la CPU, et le pipeline d’exécution de la CPU devrait attendre de temps en temps pour extraire des instructions de la mémoire principale plutôt que du cache.

Cela dépend fortement des bibliothèques en question.

Ils pourraient initialiser l’état global, ce qui ralentirait le démarrage et / ou l’arrêt du programme. Ou bien ils peuvent démarrer des threads qui font quelque chose en parallèle de votre code. Si vous avez plusieurs threads, cela peut également affecter les performances.

Certaines bibliothèques peuvent même modifier des fonctions de bibliothèque existantes. Peut-être pour collecter des statistiques sur l’utilisation de la mémoire ou des threads ou à des fins d’audit de sécurité.