4
votes

Coût des espaces de noms

Quel est le coût de la définition des espaces de noms en C ++? J'entends par là spécifiquement l'augmentation du temps de compilation / du temps d'exécution et / ou de l'empreinte mémoire. Disons que j'ai un programme trivial avec un fichier d'en-tête et un .cpp avec main. Est-ce que je remarquerais un changement dans ces statistiques susmentionnées si je définissais, par exemple, un namespace dans mon en-tête? Qu'en est-il de 10, 100 ou 1 000 espaces de noms? Et s'ils sont définis mais jamais utilisés: cela change-t-il la réponse? Je suppose que vous pourriez dire que je suis curieux de savoir comment cette construction interagit avec le (s) compilateur (s).

De même, je suis curieux de savoir l'effet des définitions de struct / class et de using , mais je ne pouvais pas penser à un bon titre pour une question englobant les trois.


8 commentaires

Cela peut augmenter le temps de compilation, cela n'a aucun effet sur le temps d'exécution car tout est compilé.


Vous devriez probablement lire sur la mutilation des noms. Même si les fichiers exécutables de version sont livrés sans symboles de débogage, les noms d'espaces de noms s'ajouteront toujours à la taille de la table d'importation / exportation et entraîneront l'exécutable à consommer plus d'espace.


Il y a un coût d'exécution théorique: les noms mutilés sont conservés dans le binaire, et sont donc en mémoire lors de l'exécution. Plus d'emboîtement d'espaces de noms = noms mutilés plus longs = plus de mémoire utilisée = plus de manque de cache = plus lent ... Cependant, je serais extrêmement surpris si vous parveniez à mesurer cette différence même avec une imbrication pathologique.


compile-time zéro (en pratique), run-time zéro, empreinte mémoire pour les dll-s presque zéro (les symboles ont des noms plus longs), pour lib / application zéro (en mode version).


Les noms mutilés @BoBTFish peuvent être conservés en binaire, c'est complètement optionnel


@BoBTFish Les noms plus longs mutilés n'ont pas d'impact sur la façon dont la fonction est appelée. Ce n'est que lorsque des noms mutilés sont utilisés que cela peut avoir un impact sur la vitesse et cela ne se produit que lors de la recherche de symboles dans les dll-s, ou lorsque le système crée un journal des plantages.


Si vous avez créé un fichier d'en-tête contenant 10 Go d'espaces de noms ouverts et fermés, cela augmenterait bien sûr le temps de compilation - ne serait-ce que parce que le compilateur doit travailler sur 10 Go de texte. De même, s'il y avait une plate-forme où les symboles mutilés pouvaient mesurer jusqu'à 10 Go de longueur, votre exécutable pourrait prendre plus de temps à s'exécuter car les noms de symboles mutilés font partie du binaire (ou du moins d'une bibliothèque) et donc cela prend plus de temps pour le binaire à charger depuis la mémoire. Mais rien de tout cela n'a vraiment d'importance dans le grand schéma des choses. La compilation C ++ est lente pour d'autres raisons.


Si vous êtes préoccupé par les temps de compilation en C ++, vous pouvez consulter le rule of Chiel et Le guide de l'auto-stoppeur pour des constructions plus rapides .


3 Réponses :


10
votes

Quel est le coût de la définition des espaces de noms en C ++?

Vous devez écrire des noms plus longs . Ce coût est compensé par le fait que les conflits de noms sont évités entre différents espaces de noms. Un nom court ne sert à rien si le nom a un conflit.

Pas vraiment cependant: un espace de noms vous permet de sortir avec moins d'écriture, car vous n'avez pas toujours besoin de retaper l'espace de noms en identificateurs non qualifiés.

J'entends spécifiquement le moment de la compilation

Potentiellement marginal.

augmentation du temps d'exécution

Aucun en pratique.

Est-ce que je remarquerais un changement dans ces statistiques susmentionnées si je définissais, par exemple, un espace de noms dans mon en-tête?

Vous pouvez le découvrir en mesurant.

Vous ne le remarquerez probablement pas.


7 commentaires

L'exécution peut augmenter là où les informations de type d'exécution (RTTI aka typeid ) ou les symboles de débogage (par exemple, l'impression des noms de fonction pendant le suivi de la pile) ou la macro __FUNCTION__ du compilateur sont utilisées.


@BenVoigt Cela pourrait également augmenter parce que vous avez dépensé plus d'énergie pour les taper, augmentant ainsi la température de votre pièce (et de l'univers entier), réduisant ainsi le plafond de chaleur thermique de votre processeur (et de n'importe qui d'autre). Tout cela est assez absurde si vous me demandez.


@BenVoigt Est-ce que yes_ns :: unique serait un symbole beaucoup plus grand que no_ns_unique ?


@eerorika: Votre propre réponse affirme, dans la première phrase, que les noms sont plus longs dans la version de l'espace de noms.


@MaxLanghof: Oui, regarder des effets d'ordre 14 n'est pas sensé. Cela ne rend pas ridicule de regarder les effets de second ordre.


@BenVoigt ouais. Mais je suis sarcastique dans cette partie de ma réponse :)


@BenVoigt Le temps de copie / impression des longueurs de nom de fonction est encore une partie absolument insignifiante de l'obtention d'une trace de pile. De même, toutes les autres choses que vous mentionnez ne concernent que la taille des chaînes stockées quelque part dans le binaire. Une application réelle passe-t-elle vraiment beaucoup de temps à traiter les résultats de typeid ou les valeurs des extensions __FUNCTION__ ? Je ne le crois pas (et si c'est le cas, il y a clairement des problèmes de conception beaucoup plus importants). Sans un exemple concret, je pense que c'est aussi pertinent que ma considération d'entropie.



1
votes

Je n'y peux rien, mais voici un exemple réel (bien qu'anecdotique) du coût réel des espaces de noms.

Il y a plusieurs années, je travaillais dans une grande entreprise avec une très forte présence technologique (on n'en dirait plus ici). L'un des aspects distinctifs de leur base de code était qu'il s'agissait principalement de binaires Unix côté serveur compilés en mode 32 bits . L'une des conventions de codage utilisées dans l'entreprise était que chaque nom aurait dû être placé dans 3 espaces de noms imbriqués - l'espace de noms plutôt long du nom de l'entreprise, suivi d'un espace de noms de nom de 3 caractères et d'un autre de 5 caractères . (Il y avait des exceptions pour l'ancien code).

La base de code était énorme (car dans la liaison de l'exécutable prendrait jusqu'à 15 minutes sur une machine très puissante) et ils arrivaient à la limite naturelle de la taille de l'exécutable pour 32 bits. À venir rapidement - le nouveau code a été ajouté et la limite de la catastrophe s'est approchée. De nombreuses solutions ont été discutées dans un mode d'urgence de vente d'incendie, et la première était que si nous utilisions simplement le raccourci pour le nom de l'entreprise dans l'espace de noms, et que nous pouvions utiliser moins de caractères dans les espaces de noms imbriqués, nous reporterions la perte de 32 bits. limitation de plusieurs mois!

Divulgation complète - Je ne sais pas comment cette sutuation a été résolue, j'ai quitté l'entreprise avant l'apocalypse.


3 commentaires

Etes-vous sûr que le long temps de liaison a été causé par les espaces de noms?


Remplacez tous les opérateurs de résolution d'étendue d'espace de noms par des traits de soulignement et obtenez cette limite beaucoup plus rapidement; à l'intérieur d'un espace de noms, des noms locaux sont utilisés et réduisent les coûts. Je doute que le code soit même compilé - en raison de l'épuisement global des espaces de noms.


@eerorika non, je n'ai jamais voulu dire ça, si ça ressemblait à ça, je n'étais pas assez clair. Le long temps de liaison a été causé par la quantité de code lié, je souligne ce fait pour montrer la taille de la base de code.



4
votes

J'entends spécifiquement le moment de la compilation

L'espace de noms peut réduire considérablement les temps de compilation car le compilateur peut avoir moins de surcharge à vérifier lors de l'utilisation d'une fonction.

Cet avantage est perdu lors de l'utilisation de en utilisant l'espace de noms xyz;

Une amélioration supplémentaire du temps de compilation peut être effectuée en utilisant des fonctions ami au lieu de la fonction libre, car ADL aura encore moins de surcharge à vérifier (dans le cas d'opérateurs ou si vous utilisiez déjà ADL)


5 commentaires

Bonne perspicacité. +1.


Pouvez-vous fournir du papier / des mesures à l'appui. Je ne dis pas que vous vous trompez, mais je me demande comment cela est possible. Les surcharges sont si rares que même si vous avez raison, l'impact ne devrait pas être mesurable. De plus, lorsque vous n'utilisez pas d'espace de noms, certains préfixes sont généralement utilisés, de sorte que «l'argument de surcharge» n'est pas non plus valide.


Vous ne prenez pas non plus en compte tout le travail supplémentaire que le compilateur doit effectuer pour maintenir les espaces de noms utilisés et ce qu'ils contiennent.


Combien vaut significativement ? De plus, les espaces de noms n'augmentent-ils pas également le temps de compilation (peut-être marginalement) des recherches non qualifiées dans le cas où la surcharge est trouvée dans l'espace de noms global?


@MarekR Je pourrais écrire un article de blog ou quelque chose du genre, je n'ai pas pensé à partager mon résultat. Je pourrais faire ça quand je suis moins occupé. Cependant, je pense que la plupart de mes gains ont été lors du déplacement de la fonction gratuite vers les fonctions ami.