6
votes

Combien d'augmentation de la taille des fonctions en ligne provoque-t-elle?

J'ai récemment commencé à faire une emballeuse C ++ de GTK + (rien de spécial, tout simplement en enveloppant les classes C ++ pour un développement facile, d'être utilisé en interne) et de causer des performances minimales à la lent GTK + j'ai utilisé des fonctions en ligne presque partout. Jetez un coup d'œil à quelques fonctions de classe ... xxx

et bien qu'il existe un flucteur de performance presque inexistant et que l'heure de démarrage et l'utilisation de la mémoire sont exactement les mêmes, le fichier La taille a considérablement augmenté. Un exemple d'échantillon d'échantillon C GTK + 6.5 KB tandis qu'une fenêtre d'échantillonnage utilisant mon wrapper génère 22,5 kb. , j'ai donc besoin d'un peu de conseils. Devrais-je continuer à utiliser des fonctions en ligne? Je veux que mes applications soient efficaces et que je puisse compromettre un peu de taille de fichier comme si je peux le prendre, même si un programme 6,5 kb C GTK + est généré comme généré comme 400-500 kb à l'aide de mon wrapper mais pas plus. Je ne veux pas que mon emballage produise énorme exes comme WxWidgets ou MFC. Donc, c'est la peine d'utiliser des fonctions en ligne ou devrais-je utiliser des utilisations normales?

Note : toutes mes fonctions ne prennent que une ou parfois deux lignes et ne sont pas grandes comme vous pouvez le voir dans l'exemple.


10 commentaires

Que comparez-vous ici ... Vous dites "Une fenêtre d'échantillon C GTK + génère 6,5 kb tandis qu'une fenêtre d'échantillonnage utilisant mon wrapper génère 22,5 kb" ... Vous ne comparez pas un programme compilé avec un compilateur C sur votre version C ++. tu? Parce qu'il y aura un coût ponctuel pour l'environnement riche en temps d'exécution, son itinérance, son code de support d'exception, ses fonctions de bibliothèque standard, etc. Vous ne pouvez comparer que de manière significative à l'aide du même harnais de base du programme / compilateur / compilateur-drapeaux de base, puis avec / Sans votre emballage ....


Je compile tous les deux avec GNU G ++ (en utilisant Mingw). Les deux sont donc traités comme des programmes C ++. La fenêtre d'échantillon C GTK + désigne une fenêtre d'échantillon faite directement à l'aide des fonctions C GTK + et des macros.


Si les fonctions inlinettes contiennent uniquement un autre appel de fonction (à gtk_widget_show etc.), la taille supplémentaire est probablement causée par autre chose. Mais ils ne le font pas, ils font aussi gtk_widget , qui devrait être trivial mais pourrait ne pas être. Vérifiez que le code émis ou le code après pré-traitement, mais avant la compilation (GCC -E), reportez-vous à la question de savoir si les appels inlinés de ces fonctions membres consistent en réalité d'une quantité importante de code.


@ Steve Vous voulez dire que la fonction macro gtk_widget ajoute également à mes fonctions inlinettes? Je vois. Je vais vérifier que


@Steve j'ai vérifié. Gtk_widget (et la plupart des autres macros) ne sont qu'une ligne de long. Donc pas d'inquiétude là-bas


J'ai hébergé mon wrapper à code.google.com/p/gtknexus Veuillez contribuer et rejoindre . j'ai besoin d'aide


Pourquoi feriez-vous cela quand 1) Ce que vous voulez exister existe déjà et est activement développé: gtkmm.org/en < / A> et 2) GTK est conçu pour ne pas nécessairement être emballé manuellement, mais est capable de générer automatiquement des liaisons à d'autres langues!


Ptomato a raison. Il ne devrait pas y avoir de raison que vous souhaitez écrire votre propre wrapper C ++ pour GTK + lorsque GTKMM existe et est bien supporté.


Je n'essaie pas de concurrencer le wrapper C ++ standard (GTKMM), j'essaie simplement de créer une petite et haute performance.


@ptomato bec. Je n'ai rien d'autre à coder.


8 Réponses :


1
votes

Cela dépend de

  • Quelle est la taille de vos fonctions
  • Combien de fois vous les utilisez
  • Paramètres du compilateur (que vous pouvez influencer)
  • Mise en œuvre du compilateur (que vous ne pouvez pas)

    etc. etc. En d'autres termes, ne supposez pas, mesurez . Faites un morceau représentatif de votre projet avec et sans fonctions inline et voyez quel est l'effet dans votre situation particulière. Toute prédiction que vous recevez sur Internet sera au mieux des suppositions éduquées.


2 commentaires

Je ne cherche pas de prédictions, j'ai besoin de conseils, devrais-je utiliser des fonctions intégrées pour la construction de l'emballage ou non? Je veux dire, c'est qu'il vaut la peine de compromettre la taille afin de stimuler la performance?


@burning: Et la réponse à celle-ci est: peut-être. Vous ne savez même pas où cela vient de ce gonflement ... Tracez cela, et il pourrait y avoir des conseils concrets à donner.



0
votes

Les exemples que vous donnez devraient inciter aucune augmentation de code au côté appel. Remplacement d'une fonction en ligne qui n'appelle qu'un appel et rien d'autre, devrait être optimisé par n'importe quel compilateur décent.

Vous devez enquêter lorsque l'augmentation réelle est. Regardez l'assembleur qui est produit, cela donne généralement une bonne vue sur les frais généraux.


0 commentaires

3
votes

Pour causer des performances minimales BLOCOIR à la GTK + SLOW SLOW + J'ai utilisé des fonctions en ligne presque partout

Les compilateurs sont assez bons à savoir quand en ligne et en cas de fonctionnement en ligne. Le mot clé inline ne signifie pas réellement que la fonction sera inline, seules que les définitions de cette fonction dans différentes unités de traduction ne cassent pas la règle d'une définition (ODR).

Concernant la taille du code, cela dépendra des options du compilateur et de quelques autres choses, mais pour le code que vous présentez, il ne devrait y avoir aucun effet, comme si la fonction est inlinée, l'appel à une seule fonction sera remplacé pour l'appel à l'autre, ce sont des doublures. Notez que de nombreux compilateurs créent la fonction et laissent la fonction binaire, même si toutes les utilisations sont inlinées, vous pouvez envisager la documentation du compilateur / lieur sur la manière de les éliminer, mais même si elles sont créées, la taille du projet ne devrait pas être affecté beaucoup.

Si vous êtes prêt à permettre à votre projet de pousser de 6,5 Ko à 400 ko, vous devriez être plus ample.


0 commentaires

6
votes

La différence de taille est plus susceptible d'être due aux bibliothèques tirées pour C ++, plutôt que dans votre équivalent C, il y a moins de frais de bibliothèque.

Si tout votre code d'emballage suit ce qui précède, alors très peu à aucun en termes de gonfleur.

me semble que votre solution est une bonne valeur pour la mise en œuvre de l'emballage.


3 commentaires

Si vous ne saviez pas Linux, l'utilitaire de taille vous indiquera la taille de code statique $ Taille


J'aimerais avoir Linux. Malheureusement, je suis coincé avec Windows (et gagnez XP à cela!)


Ah oui - exactement ce que je viens d'écrire dans un commentaire :-). Voyons si c'est vraiment ce qui a été fait ....



0
votes

Il n'y a pas de réponse facile. Cela dépend de nombreux facteurs:

  • la complexité de la fonction
  • L'architecture de la CPU et le modèle de mémoire
  • Procédure de mise en œuvre Conventions appelantes Conventions
  • le mécanisme de passage de paramètre, y compris comment l'objet accède à ceci

    La taille n'est pas la seule efficacité à considérer. Sur de nombreux processeurs modernes, l'exécution de tout type d'instruction de succursale ou d'appel peut étaller la CPU pour l'heure équivalente de nombreuses instructions. Le remplacement souvent d'une instruction d'appel avec quelques instructions du corps de la fonction est un gain de temps important. Il peut également s'agir d'un avantage de taille de code car les registres de la CPU peuvent déjà avoir des paramètres de fonction de fonction afin de ne pas avoir besoin d'être poussés ou déplacés.

    Ne transpirez pas de petites optimisations jusqu'à ce qu'il y ait un espace d'espace ou de vitesse connu. Ensuite, recherchez la solution de 10% qui affecte 90% du problème.


0 commentaires

1
votes

Si vos fonctions ne sont qu'une ou deux lignes, il est très peu probable qu'ils augmentent la taille de votre binaire résultant par une quantité considérable. En fait, ils pourraient le rendre plus petit si le code lui-même est inférieur au code temporel d'un appel de la fonction.

Notez que de toute façon, les frais généraux seraient négligeables. Il suffit de supprimer un seul appel à std :: Trier ou une instanciation de std :: map compenserait n'importe quel gonfleur. Si vous vous souciez de la taille du code, de petites fonctions inlinées sont le moindre de vos soucis.


0 commentaires

6
votes

Je soupçonne fortement que vous comparez des pommes aux oranges.

Avez-vous compilateur avec exactement le même compilateur, les mêmes drapeaux compilés et une application avec la même fonctionnalité exacte même?

Si tel est le cas, désassemblez l'exécutable et voyez ce que le code supplémentaire est .

Je suppose que c'est que c'est un code de bibliothèque unique utilisé pour prendre en charge les fonctionnalités C ++ précédemment inutilisées.

Mais comme toujours, ne devinez pas, mesurez.

Vous avez un seul point de données. Cela ne vous dit pas beaucoup. Nous pourrions envisager une augmentation de 350% de la taille du fichier dans les cas tous les cas , ou nous pourrions envisager une surcharge fixe de 16 kb. Vous devez découvrir lequel c'est. Alors obtenez quelques points de données supplémentaires. Étendez votre demande. Faites-le ouvrir dix fenêtres au lieu d'un ou ajouter une fonctionnalité supplémentaire. "Votre" version est-elle trois fois plus grosse dans ce cas aussi? Ou est-ce 16kb plus grand? Ou quelque part entre les deux? Obtenez quelques points de données supplémentaires et vous pourrez voir comment la taille du fichier échelle .

Mais probablement, vous vous inquiétez sur rien, pour plusieurs raisons:

  • Le compilateur C ++ traite en ligne comme indice. Vous facilitez le compilateur d'aligner la fonction, mais la décision repose sur le compilateur lui-même, et il essaie de rendre la demande rapidement. Si la taille du fichier commence à devenir hors de contrôle, cela ralentira votre code, votre compilateur tentera donc d'optimiser davantage vers une taille de fichier plus petite.
  • Vous regardez quelques kilobytes . À un âge Terabyte HardDrives. Si cela pourrait devenir un problème, vous devriez être capable de provoquer ce problème dans un cas de test. Si vous ne pouvez pas écrire un test qui provoque une croissance de plus de 16 kb de la taille du fichier, il ne vaut pas la peine de vous inquiéter.
  • Si la taille du fichier est-elle un problème, les compilateurs ont généralement un drapeau "optimiser la taille".
  • Les grands exécutables gagnent généralement leur taille car ils contiennent beaucoup de données et de ressources. Le code lui-même est très rarement le problème (à moins que vous ne soyez complètement bonkers avec des métaprogramming de modèle)

4 commentaires

Point 2: Je sais que j'étais toujours un peu trop obsédé par la taille et la performance, c'est peut-être parce que la première langue que j'ai jamais essayée d'apprendre était l'ASM. Sans parler que j'utilise délibérément mon ancien Pentium 4 pour programmer des choses et utilisez C / C ++ autant que je peux même que je connais C # / Java et Python.


@burningProdigy: aucun de ceux qui ne justifie d'être trop obsédé par la taille et la performance. Les deux sont importants, mais seulement où cela compte . Obsessing à leur sujet dans des cas où il ne fait aucune différence n'est simplement connu sous le nom de «perdre votre temps». surtout Si vous demandez des gourous de performance chevronnée. Vous, le développeur, jamais avez le temps d'optimiser tout pleinement. Donc, chaque minute passée à optimiser une place dans le code est une minute pas épuisé d'optimiser d'autres parties du code. Donc, si vous vous souciez vraiment de la taille et des performances, vous devez choisir vos batailles et les optimiser où cela compte


Essayer d'optimiser chaque partie de votre code ne va que vous conduire à un code, ironiquement, lent et gonflé. Parce que cela signifie que vous n'avez tout simplement pas le temps d'optimiser les parties importantes des parties du code.


D'accord. Donc, peut-être que je devrais terminer mon programme, puis faire les optimisations.



0
votes

Félicitations, vous réinventez GTKMM , les liaisons officielles C ++ pour GTK +.


4 commentaires

Je ne crée pas de Binding Je crée un wrapper à utiliser avec le code C et non fournir une nouvelle interface C ++.


Quel avantage cela vous apporte-t-il? GTKMM fournit déjà une interface C ++. Et il est mis à jour lorsque GTK change, pendant que vous devrez maintenir votre emballage vous-même.


Mon wrapper donne deux avantages principaux performance et qu'il peut être utilisé avec le code C existant. Comme je l'utilise C GTK pendant un certain temps, il est utile de disposer d'une bibliothèque compatible avec mon code C GTK + précédent.


Ensuite, appelez simplement directement le code C de votre code C ++ et vous obtiendrez la performance maximale ... Si vous souhaitez vraiment une interface C ++, utilisez simplement les liaisons GTKMM, ce qui devrait vous donner des performances acceptables de toute façon. Je pense vraiment que vous êtes sur le mauvais chemin, car: Vous faites une sorte de micro-optimisation sans même que les numéros de Havig pour comparer la performance (pourquoi pensez-vous que GTKMM serait lent?) Et ce que vous faites va Contre la réutilisabilité et la simplicité du code ... faire vos propres trucs quand quelque chose sera bismaring pour les personnes qui mettront leur main sur le code après vous ...