Un modèle écrit imprudent ici, une incroyance excessif là-bas - elle est trop facile à écrire de code ballonné en C ++. En principe, refactoring pour réduire ce ballon n'est pas trop difficile. Le problème est de suivre les pires modèles d'incrimination et des inlines - traçage de ces articles qui causent un véritable gonflement dans des programmes réels. P>
Avec cela à l'esprit, et parce que je suis certain que mes bibliothèques sont un peu plus chies qu'aucune autre chose ne devrait être, je me demandais s'il y a des outils pouvant accueillir automatiquement ces pires délinquants - c'est-à-dire identifier ces éléments qui contribuer la plupart (y compris toutes leurs instanciations répétées et appels) à la taille d'une cible particulière. P>
Je ne suis pas très intéressé par la performance à ce stade - il s'agit de la taille du fichier exécutable. P>
Y a-t-il des outils pour ce travail, utilisable sous Windows et montage avec MINGW GCC ou Visual Studio? P>
edit strong> - un contexte p>
J'ai un ensemble de modèles multi-arbres qui servent de remplacement pour les conteneurs standard d'arbre rouge-noir. Ils sont écrits comme des wrappers autour du code non-TypeAsafe non-Modèles, mais ils ont également été écrits il y a longtemps et comme une "convivialité de cache meilleure renforcera la performance réelle". Le point d'être, ils n'étaient pas vraiment écrits pour une utilisation à long terme. P>
Parce qu'ils soutiennent des astuces pratiques, cependant (recherche basée sur des comparaisons personnalisées / clés partielles, un accès spécifique efficace, la recherche de la plus petite clé inutilisée), ils ont fini par être utilisées à peu près partout dans mon code. Ces jours-ci, je n'utilise presque jamais std :: map. P>
superposé sur ceux-ci, j'ai des conteneurs plus complexes, tels que des cartes bidirectionnelles. En plus de ceux-ci, j'ai des classes d'arbres et de digraphe. Sur ces ... p>
À l'aide de fichiers de carte, je pourrais suivre si les méthodes de modèle non en ligne provoquent BLOAT. C'est juste une question de trouver toutes les instanciations d'une méthode particulière et d'ajouter les tailles. Mais qu'en est-il des méthodes inlinées imprudentes? Après tout, les modèles ont été conçus pour être des wrappers minces autour du code non-modèles, mais historiquement ma capacité à juger si quelque chose ne devrait pas être inliné ou non n'a pas été très fiable. L'impact de BLOAT de ces tentatives de modèle n'est pas si facile à mesurer. P>
J'ai une idée de quelles méthodes sont fortement utilisées, mais c'est l'erreur bien connue d'oximisation - sans profilage. P>
5 Réponses :
J'ai vu un problème comme celui-ci il y a quelque temps, et j'ai fini par écrire un outil personnalisé que le fichier de carte analysé (Visual Studio Linker peut être chargé de le produire). La sortie d'outil était: p>
Le fichier de carte d'analyse est relativement facile (la taille du code de fonction peut être calculée comme une différence entre la ligne actuelle et suivante), la partie la plus difficile de gérer probablement des noms mutilés de manière raisonnable. Vous trouverez peut-être des bibliothèques prêtes à utiliser pour les deux, je l'ai fait il y a quelques années et je ne connais pas la situation actuelle. P>
Voici un court extrait d'un fichier de carte, de sorte que vous sachiez À quoi s'attendre: P>
Address Publics by Value Rva+Base Lib:Object 0001:0023cbb4 ?ApplyScheme@Input@@QAEXPBVParamEntry@@@Z 0063dbb4 f mainInput.obj 0001:0023cea1 ?InitKeys@Input@@QAEXXZ 0063dea1 f mainInput.obj 0001:0023cf47 ?LoadKeys@Input@@QAEXABVParamEntry@@@Z 0063df47 f mainInput.obj
À première vue, il répond à la question "Quelles fonctions sont les plus grandes?", PAS "Quels articles causent le plus de gonflement dans d'autres fonctions?". Encore intéressant, bien sûr, et pour le nom Mangling, il y a toujours un brouillard Agner.
Je pars souvent des fichiers de carte de cette manière pour trouver des fonctions sur la taille d'une taille dans le code C intégré. Une fois que vous avez accroché à la main, vous devriez être capable d'écrire un script pour le faire pour vous (le format MapFile est spécifique au compilateur, malheureusement, mais l'idée est la même). Sachez que certains compilateurs ne génèrent pas de fichiers de carte par défaut, mais la plupart doivent avoir (si rien d'autre) une option de ligne de commande à le faire.
Vous pouvez regrouper des éléments (somme) par des critères que vous souhaitez, non seulement par fichier source. Une fois que vous avez démangué le nom, vous pouvez par exemple. groupe basé sur le nom de la classe de modèle et ignorer le reste.
En ce qui concerne la démanglation, il y a undoname.exe code> pour basé sur script et
undecoratesymbolname () code> pour des solutions programmatiques - plus la pièce plus gênante est filtrant le bruit.
Fondamentalement, vous recherchez des choses coûteuses que vous n'avez pas besoin. Supposons qu'il existe une certaine catégorie de fonctions que vous n'avez pas besoin de prendre un grand pourcentage de l'espace, comme 20%. Ensuite, si vous avez choisi 20 octets aléatoires hors de la taille de l'image, 4 d'entre eux (20 * 20%) seront dans cette catégorie et vous pourrez les voir. Donc, fondamentalement, vous prenez ces échantillons, regardez-les, et si vous voyez un modèle évident de fonctions dont vous n'avez pas vraiment besoin, alors retirez-les. Alors le refaire em> parce que d'autres catégories de routines utilisées moins d'espace prennent désormais un pourcentage plus élevé. P>
Alors je suis d'accord avec Suma que l'analyse du fichier de carte est un bon début. Ensuite, j'écrirais une routine pour parcourir et tous les 5% du chemin (Space-Wise) imprimer la routine que je suis dans. De cette façon, j'ai 20 échantillons. Souvent, je trouve qu'un gros morceau d'espace d'objet résulte d'un très petit nombre (comme 1) de lignes de code source que j'aurais facilement pu faire d'une autre manière. P>
Vous êtes également inquiet pour trop d'intensifier les fonctions d'inlinage que nécessaire. Pour comprendre cela, je prendrais chacun de ces échantillons et, comme cela représente une adresse spécifique dans une fonction spécifique, je retrouverais cela à la ligne de code. De cette façon, je peux dire si c'est dans un Fonction étendue. C'est un peu de travail, mais faisable. P>
Un problème similaire est de savoir comment trouver des tumeurs lorsque les disques sont pleins. La même idée doit marcher dans l'arborescence de répertoire, en ajoutant les tailles de fichiers, puis vous le remettez à nouveau, et lorsque vous passez chaque point de 5%, vous imprimez le chemin du fichier dans lequel vous vous trouvez. Cela vous indique non seulement si Vous avez des fichiers volumineux, il vous indique si vous avez un grand nombre de petits dossiers, et cela n'a pas d'importance, il est profondément enterré ou à quel point ils sont largement dispersés. Lorsque vous nettoyez une catégorie de fichiers dont vous n'avez pas besoin, vous pouvez le faire à nouveau pour obtenir la catégorie suivante, etc. P>
bonne chance. P>
J'ai donné à cette pensée et ma conclusion semble que la réponse de Ben Straubs peut être plus utile que je pensais (éventuellement - pas encore sûr). Une bonne idée - mais peut-être que je peux obtenir les mêmes résultats plus rapidement.
@ Steve314: Si je ne le fais qu'une fois, je le fais juste à la main - obtenez la taille totale, divisez-la en 20 adresses séparées uniformément, puis recherchez chacune de chacune de la carte. C'est un peu fastidieux, mais généralement, je n'ai pas besoin de regarder tous avant de trouver quelque chose à éliminer de manière fructueuse. Si une catégorie gaspilleuse apparaît sur au moins 2 échantillons, je sais que cela prend suffisamment d'espace pour valoir la peine d'être éliminé.
Consultez Symbole Trier . Je l'ai utilisé un moment pour savoir pourquoi notre installateur avait augmenté d'un facteur de 4 en six mois (il s'avère que la réponse était la liaison statique du runtime C et de la libxml2). P>
On dirait que cela me donnera à peu près les mêmes informations que l'approche de fichiers de carte déjà suggérée, mais les œuvres déjà faites. Vaut certainement un +1.
Cet utilitaire est vraiment génial. Il fait même que le modèle fusionne.
Cela ressemble à mes deux à court terme juste-get-quelque chose-chose-chose-chose-chose - maintenant, répondez et (avec Georgs Commenter à Sumas Répondre) une réponse à long terme si je décidais d'investir une durée substantielle. C'est - j'aime bien le fait que la source soit disponible et que c'est (non coché mais évident) à l'aide de la bibliothèque DBGHELP, ce qui signifie qu'il devrait être assez facile de s'étendre sans avoir besoin de bouger dans des problèmes de format de fichier.
Alors, ce que je lis en fonction de votre question et de vos commentaires, c'est que la bibliothèque est pas em> réellement trop grande. p>
Le seul outil dont vous avez besoin pour déterminer ceci est un shell de commande ou de l'explorateur de fichiers Windows. Regardez la taille du fichier. Est-ce si gros que cela provoque des problèmes réels réels? (Horaires de téléchargement inacceptable, ne correspondra pas à la mémoire sur la plate-forme cible, ce genre de chose)? p>
Sinon, alors vous devriez vous soucier de la lisibilité et de la maintenabilité du code et rien d'autre. Et l'outil pour que em> est vos yeux. Lisez le code et prenez les mesures nécessaires pour le rendre plus lisible si nécessaire. P>
Si vous pouvez pointer sur une raison réelle pour laquelle la taille exécutable est un problème Cependant, en supposant que la taille du fichier est em> réellement un problème: p>
Les fonctions inlinettes ne sont généralement pas un problème, car le compilateur, et personne d'autre, choisit qui fonctionne en ligne. Il suffit de marquer quelque chose Si vous êtes inquiet que les fonctions inlinées provoquent le code de code de code, compilez simplement avec le drapeau "Optimiser la taille". Ensuite, le compilateur limitera l'affranchissement des cas où cela n'affecte pas sensiblement la taille exécutable. P>
Pour déterminer quels symboles sont plus grands, analysez le fichier de carte comme @suma suggéré. P>
Mais vraiment, vous l'avez dit vous-même lorsque vous avez mentionné "l'erreur bien connue d'oximisation - sans profilage". p>
Le tout premier acte de profilage que vous devez faire est de demander Profil. Rassemblez des données et identifiez les points de difficulté. Avant de s'inquiéter de la manière de réduire la taille exécutable, découvrez quelle est la taille exécutable et identifiez s'il s'agit ou non d'un problème. Vous ne l'avez pas encore fait cela. Vous lisez dans un livre que "Code BLOAT est un problème en C ++", et vous supposez donc que le code BLOAT est un problème dans votre programme. Mais est-ce? Pourquoi? Comment déterminez-vous que c'est? P> inline code> ne fait pas état du code généré réel. Le compilateur s'installe s'il détermine le compromis entre un code plus vaste et moins d'indirection pour en valoir la peine. Si une fonction est appelée souvent, elle ne sera pas induite, car cela affecterait considérablement la taille du code, ce qui ferait mal aux performances. P>
C'est la chose - la bibliothèque compilée est grande. Mais je ne sais pas à quel point il devrait être i>. Même quelques minutes à voir quelle différence refactorise les causes absolues des pires contrevenants constitueraient une grande idée - si c'est facile de réaliser des réductions significatives, c'est une indication juste qu'il y a un véritable gonfleur. Peu ou pas de gain - bien, revenez le changement inutile et soyez heureux. Collecte de données et identification des problèmes de problèmes est précisément ce que j'essaie de faire! En ce qui concerne une bonne raison - en pensant à la diffusion de leur source en public, je soupçonne que beaucoup de gens s'inquiètent un peu plus sur la sale.
Sur la chose en ligne-ne méchant-signature-inine, bon point. Bien sûr, je sais, mais cela ne signifie pas que je le prends toujours en compte.
"La bibliothèque compilée est grande" - bibliothèque compilée? Je me soucie de la taille exécutable. Quel genre de bibliothèque est-ce? DLL ou Libary destiné à une liaison statique? Si la DLL, la même approche que pour EXE s'applique toujours (DLL est essentiellement un EXE). En ce qui concerne les Libs statiques, je ne sais pas que leur taille est pertinente à aucun égard.
"Sinon, alors vous devriez vous soucier de la lisibilité du code et de la maintenabilité et rien d'autre." +1
Vous constatez que votre bibliothèque est en fait trop grande? Ou est-ce juste un sentiment?
À ce stade, c'est un sentiment assez fort. Bien sûr, cet outil pourrait m'aider à trouver certains que ce sentiment soit justifié.
En ce qui concerne ceux qui sont inlinés, ma technique ne fonctionne malheureusement que de manière indirectement et à une mesure limitée - vous verrez souvent les fonctions qui appellent les fonctions inlinettes.
Si vous pouvez ouvrir un
typique de la fonction de taille code>, mettez trois programmeurs compétents devant cela, et personne ne peut comprendre un lécher - que vous ne pouvez vous assurer que vous avez trouvé BLOAT. Cette technique fonctionne pour n'importe quelle langue.