Est-ce que l'utilisation de grandes bibliothèques font intrinsèquement un code plus lent?

StackOverflow https://stackoverflow.com/questions/2247465

Question

J'ai un tic psychologique qui me rend réticent à utiliser de grandes bibliothèques (comme GLib ou Boost ) dans les langues de niveau inférieur comme C et C ++. Dans mon esprit, je pense:

  

Eh bien, cette bibliothèque a des milliers de   heures de travail mis en elle, et il a été   créé par des gens qui connaissent beaucoup plus   sur la langue que je ne le fera jamais.   Leurs auteurs et les fans disent que   les bibliothèques sont rapides et fiables,   et la fonctionnalité ressemble vraiment   utile, et il va certainement me arrêter   de (mal) réinventer la roue.

     

Mais bon sang, je ne vais jamais utiliser   toutes les fonctions de cette bibliothèque. Ses   trop grand et il est probablement devenu pléthorique   au cours des années; il est une autre balle   et de la chaîne de mon programme a besoin de faire glisser autour.

Le Torvalds diatribe (si controversé il est) ne met pas exactement mon cœur à l'aise non plus.

Y at-il base à ma pensée, ou suis-je simplement déraisonnable et / ou ignorants? Même si je n'utilise que une ou deux caractéristiques d'une grande bibliothèque, en reliant à cette bibliothèque que je vais supporter les frais généraux de performance d'exécution?

Je suis sûr que cela dépend aussi de ce que la bibliothèque est spécifique, mais je suis généralement intéressé à savoir si les grandes bibliothèques, à un niveau technique, introduire intrinsèquement inefficacités.

Je suis fatigué de obsédante et marmonnant et se soucier de cela, quand je n'ai pas les connaissances techniques pour savoir si je suis bien ou pas.

S'il vous plaît me mettre hors de ma misère!

Était-ce utile?

La solution

  

Même si j'utilise seulement une ou deux caractéristiques d'une grande bibliothèque, en reliant à cette bibliothèque que je vais supporter les frais généraux de performance d'exécution?

En général, non.

Si la bibliothèque en question n'a pas beaucoup de code indépendant de la position, alors il y aura un coût de démarrage alors que l'éditeur de liens dynamique effectue les délocalisations sur la bibliothèque quand il est demandé. Habituellement, cela fait partie du démarrage du programme. Il n'y a pas d'effet de la performance d'exécution au-delà.

Linkers sont aussi bons à enlever « code mort » des bibliothèques statiquement liées à la compilation, de sorte que toutes les bibliothèques statiques que vous utilisez auront en tête de taille minimale. La performance ne même pas entrer en elle.

Franchement, vous soucier des mauvaises choses.

Autres conseils

Je ne peux pas commenter GLib, mais gardez à l'esprit que beaucoup de code dans Boost est principe en-tête seulement et compte tenu du C ++ de l'utilisateur ne payant que pour ce qu'ils utilisent, les bibliothèques sont assez efficaces. Il y a plusieurs bibliothèques qui vous obligent à établir un lien avec eux (regex, système de fichiers viennent à l'esprit), mais ils sont des bibliothèques distinctes. Avec Boost vous ne liez pas contre une grande bibliothèque monolithique mais seulement contre les plus petits composants que vous utilisez.

Bien sûr, l'autre question est - quelle est l'alternative? Est-ce que vous souhaitez implémenter la fonctionnalité qui est en vous Boost quand vous en avez besoin? Étant donné que beaucoup de personnes très compétentes ont travaillé sur ce code et fait en sorte que cela fonctionne à travers une multitude de compilateurs et est toujours efficace, cela pourrait ne pas être exactement une entreprise simple. De plus, vous êtes réinventer la roue, au moins dans une certaine mesure. À mon humble avis, vous pouvez passer ce temps de façon plus productive.

Boost n'est pas une grande bibliothèque.

Il est une collection de nombreuses petites bibliothèques. La plupart d'entre eux sont si petits qu'ils sont contenus dans un en-tête ou deux. L'utilisation boost::noncopyable ne traîne pas boost::regex ou boost::thread dans votre code. Ils sont différentes bibliothèques. Ils sont juste distribués dans le cadre de la même collection de la bibliothèque. Mais vous ne payez que pour ceux que vous utilisez.

Mais, en général, parce que les grandes bibliothèques existent, même si Boost est pas un d'entre eux:

  

Y at-il base à ma pensée, ou suis-je simplement déraisonnable et / ou ignorants? Même si je n'utilise que une ou deux caractéristiques d'une grande bibliothèque, en reliant à cette bibliothèque que je vais supporter les frais généraux de performance d'exécution?

Pas de base, plus ou moins . Vous pouvez tester vous-même.

Ecrire un petit programme C ++ et le compiler. Maintenant, ajoutez une nouvelle fonction à elle, celle qui est jamais appelé, mais est définie. Compiler à nouveau le programme. optimisations sont activées en supposant, il se dépouilla par l'éditeur de liens, car il est utilisé. Ainsi, le coût de l'inclusion supplémentaire utilisé Code est égal à zéro.

Bien sûr, il y a des exceptions. Si le code instancie des objets globaux, ceux qui pourraient ne pas être enlevés (c'est pourquoi y compris l'en-tête de iostream augmente la taille de l'exécutable), mais en général, vous pouvez inclure autant de têtes et un lien vers autant de bibliothèques que vous le souhaitez, et il a gagné » t affectent la taille, la performance ou l'utilisation de la mémoire de votre programme * aussi longtemps que vous ne le faites pas utiliser tout le code ajouté.

Une autre exception est que si vous établissez un lien dynamique à un .dll ou .so, toute la bibliothèque doit être distribuée, et ne peut donc pas être dépouillé de code inutilisé. Mais les bibliothèques qui sont compilés statiquement dans votre exécutable (soit sous forme de bibliothèques statiques (.lib ou .a) ou tout simplement sous forme de fichiers d'en-tête inclus peuvent généralement être rognées par l'éditeur de liens, la suppression des symboles inutilisés.

Grande bibliothèque, de la code perspective de performance:

  • occupent plus de mémoire , si elle a un binaire d'exécution (la plupart des régions de boost ne nécessitent pas de binaires d'exécution, ils sont « en-tête seulement »). Alors que le système d'exploitation ne charger que les effectivement utilisées parties de la bibliothèque à la RAM, il peut encore charger plus que vous avez besoin, parce que la granularité de ce qui est chargé est égale à la taille de la page (4 Kb uniquement sur mon système, cependant).
  • prendre plus de temps pour charger par éditeur de liens dynamiques, si, encore une fois, il a besoin de fichiers binaires d'exécution. Chaque fois que votre programme est chargé, éditeur de liens dynamique doit correspondre à chaque fonction, vous devez bibliothèque externe pour contenir son adresse réelle en mémoire. Il prend un certain temps, mais juste un peu (cependant, il importe à l'échelle du chargement de nombreux programmes, tels que le démarrage de l'environnement de bureau, mais vous n'avez pas le choix là-bas).

    Et oui, il faudra un saut supplémentaire et quelques ajustements de pointeur lors de l'exécution à chaque fois que vous appelez la fonction externe d'un partagé bibliothèque (lié dynamiquement)

de de développeur perspective de performance:

  • ajouter une dépendance externe . Vous en fonction de quelqu'un d'autre . Même si le logiciel libre de cette bibliothèque, vous aurez besoin des frais supplémentaires pour le modifier. Certains développeurs de programmes veeery bas niveau (je parle de noyaux OS) détestent compter sur personne - c'est leur avantage professionnel. Ainsi, les coups de gueule.

    Toutefois, cela peut être considéré comme un avantage. Si d'autres personnes sont habitués à boost, ils trouveront des concepts familiers et les termes de votre programme et seront compréhension plus efficace et la modifier.

  • bibliothèques Bigger généralement contiennent des concepts spécifiques à la bibliothèque qui prennent du temps à comprendre. Considérez Qt. Il contient des signaux et des fentes et des infrastructures connexes moc. Par rapport à la taille de l'ensemble Qt, ce qui les prend apprendre une petite fraction du temps. Mais si vous utilisez une petite partie d'une telle grande bibliothèque, qui peut être un problème.

Code excès ne fait pas comme par magie la course du processeur plus lent. Tout ce qu'il fait est assis il occupe un peu de mémoire.

Si vous liez statiquement et votre éditeur de liens est tout raisonnable, il ne comprendra que les fonctions que vous utilisez réellement de toute façon.

Le terme que j'aime des cadres, des ensembles de bibliothèques, et certains types d'outils de développement, sont les technologies de plate-forme. technologies de la plate-forme ont des coûts au-delà de l'impact sur la taille du code et de la performance.

  1. Si votre projet est lui-même destiné à être utilisé comme une bibliothèque ou d'un cadre, vous pouvez finir par pousser vos choix technologiques de la plate-forme sur les développeurs qui utilisent votre bibliothèque.

  2. Si vous distribuez votre projet sous forme de source, vous pouvez finir par pousser les choix technologiques de la plate-forme sur vos utilisateurs finaux.

  3. Si vous n'êtes pas un lien statiquement tous vos cadres choisis et les bibliothèques, vous pouvez finir par surcharger vos utilisateurs finaux avec des problèmes de bibliothèque de versioning.

  4. Compiler les effets du temps la productivité des développeurs. liaison supplémentaire, les en-têtes précompilés, la gestion des dépendances d'en-tête appropriée, etc., peuvent aider à gérer les temps de compilation, mais ne pas éliminer les problèmes de performance du compilateur associés aux quantités massives de code en ligne des technologies de plate-forme présente.

  5. Pour les projets qui sont distribués en tant que source, le temps de compilation affecte les utilisateurs finaux du projet.

  6. De nombreuses technologies de la plate-forme ont leurs propres exigences en matière d'environnement de développement. Ces exigences peuvent accumuler ce qui rend difficile et prend du temps pour les nouveaux développeurs sur un projet pour être en mesure de reproduire l'environnement nécessaire pour permettre la compilation et le débogage.

  7. L'utilisation des technologies de la plate-forme crée en effet un nouveau langage de programmation pour le projet. Cela rend plus difficile pour les nouveaux développeurs de contribuer.

Tous les projets ont des dépendances technologiques de la plate-forme, mais pour de nombreux projets, il y a des avantages réels pour le maintien de ces dépendances au minimum.

Il peut y avoir une petite tête lors du chargement de ces bibliothèques si elles sont liées dynamiquement. Ce sera typiquement un minuscule, minuscule fraction du temps de votre programme en cours d'exécution passe.

Cependant il n'y aura pas de frais généraux une fois que tout est chargé.

Si vous ne souhaitez pas utiliser tous de boost, puis non. Il est modulaire, de sorte que vous pouvez utiliser les pièces que vous voulez et ignorer le reste.

Plus grand ne signifie pas intrinsèquement plus lent. Contrairement à quelques-unes des autres réponses, il n'y a pas de différence inhérente entre les bibliothèques stockées entièrement en-têtes et les bibliothèques stockées dans les fichiers objets soit.

Bibliothèques en-tête uniquement peuvent un avantage indirect. La plupart des bibliothèques basées sur des modèles doivent être en-tête seule (ou beaucoup de code finit par les en-têtes de toute façon), et les modèles ne donnent beaucoup de possibilités d'optimisation. Prendre le code dans une bibliothèque typique fichier objet et le déplacer dans tous les en-têtes seront pas , cependant, ont généralement beaucoup de bons effets (et pourrait conduire à météorisation code).

La vraie réponse à une bibliothèque particulière dépend généralement de sa structure globale. Il est facile de penser à « Boost » comme quelque chose d'énorme. En fait, il est une énorme collection des bibliothèques, dont la plupart sont individuellement assez faible. Vous ne pouvez pas dire grand-chose (significative) à propos de Boost dans son ensemble, parce que les bibliothèques individuelles sont écrits par des personnes différentes, avec des techniques différentes, des objectifs, etc. Certains d'entre eux (par exemple Format, Assign) sont vraiment plus lent que presque tout vous seriez très susceptibles de le faire vous-même. D'autres (par exemple Pool) fournir des choses que vous pourriez vous faire, mais ne sera probablement pas, d'obtenir des améliorations de vitesse au moins mineure. Quelques (par exemple uBLAS) utiliser la magie modèle robuste pour courir plus vite que tout, mais un petit pourcentage d'entre nous peut espérer réaliser nous-mêmes.

Il y a, bien sûr, un bon nombre de bibliothèques qui sont vraiment individuellement de grandes bibliothèques. Dans bon nombre de cas, ce sont vraiment plus lent que ce que vous écrivez vous-même. En particulier, beaucoup (la plupart?) D'entre eux tentent d'être beaucoup plus général que presque tout ce que vous seriez tout susceptible d'écrire sur votre propre. Bien que cela ne veut pas nécessairement conduire à un code plus lent, il y a certainement un forte tendance dans cette direction. Comme avec beaucoup d'autres code, lorsque vous développez des bibliothèques dans le commerce, les clients ont tendance à être beaucoup plus intéressés par les fonctionnalités que des choses comme la taille de la vitesse.

Certaines bibliothèques consacrent également beaucoup d'espace, le code (et souvent au moins les bits de temps) pour résoudre les problèmes que vous pouvez très bien ne pas se soucier du tout. Il y a à peine, par exemple, des années j'ai utilisé une bibliothèque de traitement d'images. Son soutien pour plus de 200 formats d'image semblait vraiment impressionnante (et d'une manière qu'il était vraiment) mais je suis sûr que je ne l'utilisais pour traiter plus d'une douzaine de formats (et je pourrais probablement obtenu en soutenant que la moitié beaucoup). OTOH, même avec tout ce qu'il était encore assez rapide. Soutenir moins de marchés aurait limité leur marché au point que le code aurait effectivement été plus lente (juste par exemple, il a traité plus rapidement que les fichiers JPEG IJG).

Comme d'autres l'ont dit, il y a certains frais généraux lors de l'ajout d'une bibliothèque dynamique. Lorsque la bibliothèque est d'abord chargé, les délocalisations doivent être effectués, même si cela devrait être un coût mineur si la bibliothèque est compilé correctement. Le coût de la recherche des symboles individuels est également augmenté puisque le nombre de bibliothèques qui doivent rechercher est augmentée.

Le coût en mémoire d'ajouter une autre bibliothèque dynamique dépend en grande partie de la quantité de celui-ci que vous utilisez. Une page de code ne sera pas chargé à partir du disque jusqu'à ce que quelque chose est exécuté. Cependant, d'autres données telles que les en-têtes, des tables de symboles, et les tables de hachage intégrées dans le fichier de bibliothèque seront chargés, et ceux-ci sont généralement proportionnelles à la taille de la bibliothèque.

Il y a un grand document par Ulrich Drepper, le contributeur principal à glibc, qui décrit le processus et les frais généraux des bibliothèques dynamiques.

dépend de comment l'éditeur de liens fonctionne. Certains linkers sont paresseux et comprennent tout le code dans la bibliothèque. Les linkers plus efficaces seront seulement extraire le code nécessaire à partir d'une bibliothèque. J'ai eu l'expérience avec les deux types.

Les petites bibliothèques auront moins de soucis avec les deux types de liaison. Le pire des cas avec une petite bibliothèque est de petites quantités de code inutilisé. De nombreuses petites bibliothèques peuvent augmenter le temps de construction. Le compromis serait le temps de construction par rapport à l'espace de code.

Un test intéressant de l'éditeur de liens est le classique Bonjour tout le monde Programme:

#include <stdio>
#include <stdlib>
int main(void)
{
  printf("Hello World\n");
  return EXIT_SUCCESS;
}

La fonction printf a beaucoup de dépendances en raison de tout le formatage que peut besoin. Un agent de liaison paresseux, mais rapide peut inclure une « bibliothèque standard » pour résoudre tous les symboles. Une bibliothèque plus efficace ne comprendra printf et ses dépendances. Cela rend l'éditeur de liens plus lent.

Le programme ci-dessus peut être comparé à celui-ci en utilisant puts:

#include <stdio>
#include <stdlib>
int main(void)
{
  puts("Hello World\n");
  return EXIT_SUCCESS;
}

En général, la version puts doit être inférieure à la version printf, car puts n'a pas de mise en forme doit donc moins de dépendances. linkers Lazy va générer la même taille de code que le programme printf.

En résumé, les décisions de taille de la bibliothèque ont plus de dépendances sur l'éditeur de liens. Plus précisément, l'efficacité de l'éditeur de liens. En cas de doute, de nombreuses petites bibliothèques comptent moins sur l'efficacité de l'éditeur de liens, mais rendre le processus de construction plus complexe et plus lent.

  1. La chose à faire avec les problèmes de performances, en général, est de ne pas les divertir, parce que de le faire est d'être devinant qu'ils sont un problème, parce que si vous ne le faites pas savent ils sont, vous deviner, et deviner est le concept central derrière « l'optimisation prématurée ». La chose à voir avec les problèmes de performance est, quand vous les avez, et pas avant , les diagnostiquer. Les problèmes ne sont presque jamais quelque chose que vous auriez deviné. Voici un exemple étendu.

  2. Si vous faites une bonne quantité, vous arriverez à reconnaître les approches de conception qui ont tendance à causer des problèmes de performance, que ce soit dans votre code ou dans une bibliothèque. (Les bibliothèques peuvent certainement avoir des problèmes de performance.) Lorsque vous apprenez et appliquez à des projets puis dans un sens vous optimisez prématurément, mais il a l'effet désiré de toute façon, d'éviter les problèmes. Si je peux résumer ce que vous apprendrez sans doute, il est que trop de couches d'abstraction, et des hiérarchies de classes surfaite (en particulier ceux complète de la mise à jour de style de notification) sont ce sont très souvent les raisons des problèmes de performance.

En même temps, je partage votre sujet des bibliothèques 3 circonspection parties et autres. Trop de fois j'ai travaillé sur des projets où certains paquet 3e parti était « effet de levier » pour « synergie », puis le vendeur soit allé en fumée ou abandonné le produit ou a aller obsolète parce que Microsoft a changé les choses dans le système d'exploitation. Ensuite, notre produit qui se penchait fortement sur le paquet 3ème partie commence à ne fonctionne pas, ce qui nécessite une grande dépense de notre part alors que les programmeurs sont révolus depuis longtemps d'origine.

« une autre balle et de la chaîne ». Vraiment?

Ou est-ce une plate-forme stable et fiable qui permet à votre application en premier lieu?

Considérez que certaines personnes peuvent, comme un « trop grand et ... pléthorique » bibliothèque parce qu'ils l'utilisent pour d'autres projets et vraiment faire confiance.

En effet, ils peuvent refuser de jouer avec votre logiciel spécifiquement parce que vous avez évité en utilisant l'évidence « trop grand et ... pléthorique » bibliothèque.

Techniquement, la réponse est que oui, ils le font. Cependant, ces inefficacités sont très rarement important dans la pratique. Je vais supposer un langage compilé statiquement comme C, C ++, ou D ici.

Quand un exécutable est chargé en mémoire sur un système d'exploitation moderne, l'espace d'adressage est simplement mis en correspondance avec elle. Cela signifie que, peu importe la taille du exectable est, s'il y a des blocs entiers de taille de la page de code qui ne sont pas utilisés, ils ne touchent la mémoire physique. Vous perdrez l'espace d'adressage, cependant, et parfois cela peut compter un peu sur les systèmes 32 bits.

Lorsque vous accédez à une bibliothèque, un bon éditeur de liens habituellement jeter l'excès des choses que vous ne l'utilisez pas, mais surtout dans le cas d'instanciation de modèle cela ne se produit pas toujours. Ainsi vos binaires pourraient être un peu plus grand que le strict nécessaire.

Si vous avez du code que vous n'utilisez pas fortement entrelacée avec le code que vous utilisez, vous pouvez finir par perdre de l'espace dans le cache de votre CPU. Cependant, comme les lignes de cache sont petites (généralement 64 octets), ce sera rarement arriver dans une mesure pratique importante.

Demandez-vous ce que votre cible. Est-ce un poste de travail en milieu de fin d'aujourd'hui - aucun problème. Est-il plus de matériel ou même un système embarqué limité, alors il pourrait être.

Comme les commentaires précédents ont dit, juste avoir le code, il ne vous coûte pas beaucoup dans la performance (il pourrait réduire la localité pour les caches et augmenter les temps de chargement).

FWIW, je travaille sur Microsoft Windows et lorsque nous construisons de Windows; build compilé pour Taille sont plus rapides que les builds compilé pour SPEED parce que vous prenez moins de défaut de page frappe.

FFTW et ATLAS sont deux bibliothèques assez grandes. Curieusement, ils jouent un grand rôle dans le logiciel le plus rapide dans le monde, les applications optimisées pour fonctionner sur des supercalculateurs. Non, à l'aide de grandes bibliothèques ne fait pas votre code lent, surtout quand l'alternative est la mise en œuvre FFT ou routines BLAS pour vous-même.

Vous avez raison d'être inquiet, surtout quand il vient d'augmenter. Ce n'est pas tellement dû à personne de les écrire étant incompétent mais en raison de deux problèmes.

  1. Les modèles ne sont que le code intrinsèquement pléthorique. Cela n'a pas d'importance il y a autant de 10 ans, mais de nos jours la CPU est beaucoup plus rapide que l'accès à la mémoire et cette tendance se poursuit. Je dirais presque que les modèles sont une caractéristique obsolescent.

Il est pas si mal pour le code utilisateur qui est généralement un peu pratique, mais dans de nombreuses bibliothèques tout est défini en termes d'autres modèles ou des modèles sur plusieurs éléments (ce qui signifie explosions exponentielles de code du modèle).

Il suffit d'ajouter à iostream ajoute environ 3 mb (!!!) à votre code. Maintenant, ajoutez dans certains non-sens de boost et vous avez 30 Mo de code si vous sinply déclarer deux structures de données particulièrement étranges.

Pire encore, vous ne pouvez pas le profil même facilement cela. Je peux vous dire la différence entre le code écrit par moi et le code des bibliothèques de modèle est DRAMATIQUE mais pour une approche plus naieve vous pouvez penser que vous faites pire à partir d'un simple test, mais le coût dans le code ballonnement prendrai son outil dans un grand realworld app.

  1. complexité. Quand vous regardez les choses dans Boost, ce sont toutes les choses qui compliquent votre code à un degré énorme. Des choses comme des pointeurs intelligents, foncteurs, toutes sortes de choses compliquées. Maintenant, je ne dis pas qu'il est jamais une bonne idée d'utiliser ce genre de choses, mais à peu près tout cela a un coût énorme d'une sorte. Surtout si vous ne comprenez pas exactement, je veux dire exactement, ce qu'il fait.

Mais les gens parlent avec enthousiasme et prétendre qu'il a quelque chose à voir avec la « conception » afin que les gens ont l'impression qu'il est la façon dont vous devriez tout faire, et pas seulement des outils extrêmement spécialisés qui devraient être utilisés que rarement. Si jamais.

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