12
votes

Frais généraux dans le code inutilisé

Je me demande quelle est la surcharge de fonctions inutilisées dans votre code.

Dites par exemple, vous avez une journalisation de débogage, et vous donnez ensuite la plupart de vos objets une fonction Tostring () utilisée dans les journaux de débogage.

Dans une version de déverrouillage, la journalisation de débogage n'est pas utilisée. Est-ce alors la peine d'éliminer le code source de ces fonctions Tostring ()? (par exemple, via macro?)

ou font-ils simplement l'exécutable légèrement plus grand et sinon n'a pas d'impact sur la performance? par exemple. Aucun impact rapide? Ou le compilateur ou la lieur éventuellement supprime-t-il même les fonctions si elles ne sont pas utilisées? Si le compilateur ou la liaison ne supprime pas le code, si les fonctions de tostring () ont été définies en ligne? Vraisemblablement, il essaierait de souscrire le code et, étant donné que la fonction n'est jamais appelée, elle disparaîtrait?

J'imagine que toutes les fonctions doivent être conservées dans une LIB statique, mais une fois compilée à un exécutable, beaucoup de choses sont certainement ignorées par la liaison?

sur une autre note similaire, si le compilateur choisit de ne pas souscrire une fonction inline, de sorte que la fonction inline est définie comme fonction dans plusieurs unités de compilation, le lieur voudra-t-il éliminer les définitions superflues et lier seulement l'un d'entre eux À la fin?

merci


7 commentaires

Cela pourrait dépendre du compilateur et des optimisations de son utilisation.


"L'optimisation prématurée est la racine de tout mal" - Donald Knuth


Je suis tellement fatigué du mantra d'optimisation prématurée. Oui merci de votre aide. Aussi: "Comprendre ce que vous faites pourrait vous aider à bien le faire bien." Ou êtes-vous en désaccord? Sûrement une compréhension des compilateurs et des liaiseurs n'est pas mal. Mais merci pour votre contribution.


@ Maurits: Je n'aime pas les citations incomplètes. N'oubliez pas que le disait 97% des temps devant cela.


La citation complète semble être: «Nous devrions oublier de petites gains d'efficacité, selon environ 97% du temps: l'optimisation prématurée est la racine de tout le mal»


Les journaux de débogage sont assez célèbres pour leurs frais généraux potentiels. Les implémentations naïves construisent de grandes chaînes, synchronisez des threads pour éviter que les messages de journalisation soient mélangés, puis supprimer tout. La fausse synchronisation est particulièrement dangereuse car elle peut même conduire à des blocages. Pour ces raisons, j'élimine toujours la journalisation via des macros.


«Sinon de débogage, quittez, quittez» au sommet de l'appel de l'enregistreur est une surcharge triviale. The'debug 'Global pourrait être défini par un paramètre de ligne de commande ou similaire. Je suis d'accord avec votre autre point - Strings de journal doit être mis en file d'attente sur un fil d'affichage - le seul thread pour toucher le fichier journal - et l'appel de journal renvoie "immédiatement". Le seul synchro devrait être autour de la touche de la file d'attente de l'enregistreur - Nice et courte.


4 Réponses :


5
votes

Cela dépend du compilateur et, je suppose que le niveau d'optimisation.

G ++ et MSVC ++ Supprimez les fonctions intégrées inutilisées mais conserve des fonctions non inutilisées non lignes. Par exemple, vous n'utilisez qu'une petite fraction de la STL dans un programme normal. Toutes les fonctions inutilisées sont supprimées, car elles sont définies comme inline.

GCC d'autre part conserve toutes les fonctions, même non utilisées en ligne.

Réponse à votre autre question: Si une fonction est définie d'une manière ou d'une autre dans plusieurs unités de compilation, la liaison froncera et refusera de lien, sauf si elle est définie comme inline.


1 commentaires

Juste votre dernière phrase: à moins que cela ne soit défini comme inline. Cela devrait empêcher votre compilateur de fronçant les sourcils, même s'il serait froncé s'il n'y avait pas défini en ligne.



2
votes

Les liaiseurs suppriment les fonctions en double et ils suppriment les données non référencées (le Microsoft Linker propose le / OPF: ref et / opt: ICF Bascule pour modifier ces paramètres).

Vous êtes certainement correct que, dans la plupart des cas, cela n'auront tout simplement pas d'importance si le linkeur fait un bon travail lors de la perte de choses qui n'est pas nécessaire ou non redondante - l'impact sur la taille exécutable pour quelques petites fonctions (par rapport à IE la Montant de code généré si vous utilisez une utilisation intensive des bibliothèques STL ou d'autres modèles) est minimale.

qui dit, si vous avez besoin de votre exécutable pour être aussi petit que possible (ou si vous découvrez que votre code de débogage vraiment prend la majeure partie de la taille de l'image), #Ifdef Tout est le moyen le plus simple d'appliquer certaines fonctions à ne pas être incluses. Il rend le code un peu laids à lire, mais il a l'avantage de ne pas manquer accidentellement peu de spots de code de débogage dans votre version de votre version depuis toute tentative d'invoquer une fonction inexistante entraînera une erreur de compilateur.

Un autre avantage de #Ifdef est qu'il est portable et ne dépend pas d'un système de compilateur particulier: - /


2 commentaires

Souhaitez-vous alors qu'il est préférable de définir de telles fonctions de Tostring de débogage comme inline?


Étant donné que le compilateur est toujours libre d'entrer en ligne ou non une fonction, j'ai tendance à utiliser en ligne uniquement à un seul but: pour pouvoir avoir des définitions de fonction dans des fichiers d'en-tête partagés. Comme cela est implicite pour les fonctions des membres définies dans les organismes de classe, je ne spécifierais pas en ligne . Mais veuillez noter que ceci est juste mon approche personnelle de en ligne .



3
votes

1. En ce qui concerne les compilateurs et les liens

Cela dépend vraiment de la manière dont vous créez votre exécutable.

Les exécutables typiquement sont dépouillées de tout ce qui n'est pas utilisé. Par conséquent, si vous liez statiquement (et avec les bonnes options d'optimisation), les fonctions seront supprimées.

Toutefois, si vous liez de manière dynamique, ils seront là, car dans la mesure où la bibliothèque est concernée, elles sont exportées et donc utilisées.

Quant aux multiples définitions, cela dépend si le symbole est faible. Si c'est faible, le linkier choisit l'une des définitions, sinon elle étouffe dessus.

Enfin, ils représentent probablement une partie marginale de votre programme.

2. Comment résoudre le problème?

C'est un problème difficile, vous pouvez toujours utiliser le préprocesseur pour enlever certaines choses, mais le code qui est jonché de directives de préprocesseur est vraiment gênant de lire.

Personnellement, je ne dérangerais pas ... surtout parce que je me connecte aussi (comment les autres suivent les problèmes de production?).

Une solution pourrait être de définir les fonctions incriminées dans un fichier distinct et de ne pas les relier à la libération. Remarque: je ne pense pas que cela fonctionne pour des fonctions virtuelles, car elles sont au moins utilisées dans la tablette


0 commentaires

0
votes

Si vous mettez une fonction non virtuelle dans un fichier séparé dans une bibliothèque et lien statiquement, il ne devrait être ajouté qu'à l'exécutable s'il est utilisé. Mais la seule vraie différence sera de la taille de la exécutable; Cela pourrait avoir une incidence sur la localité et donc la performance, mais je serais très surpris si cela a jamais réalisé une vraie différence en pratique. Donc généralement, je dirais que cette technique ne vaut pas la peine déranger dans une application. (Si vous livrez des bibliothèques tiers, D'autre part, vous voulez certainement chaque fonction non virtuelle dans un fichier séparé.)


0 commentaires