Question

Bien qu'il soit très pratique d'utiliser des fonctions en ligne dans certaines situations,

Y a-t-il des inconvénients avec les fonctions en ligne ?

Conclusion:

Apparemment, il n'y a rien de mal à utiliser des fonctions en ligne.

Mais il convient de noter les points suivants !

  • La surutilisation de l'inline peut en fait ralentir les programmes.En fonction de la taille d'une fonction, son insertion peut entraîner une augmentation ou une diminution de la taille du code.L'intégration d'une très petite fonction d'accesseur réduira généralement la taille du code, tandis que l'intégration d'une très grande fonction peut augmenter considérablement la taille du code.Sur les processeurs modernes, un code plus petit s'exécute généralement plus rapidement grâce à une meilleure utilisation du cache d'instructions. - Consignes Google

  • Les avantages en termes de vitesse des fonctions en ligne ont tendance à diminuer à mesure que la fonction augmente en taille.À un moment donné, la surcharge de l'appel de fonction devient faible par rapport à l'exécution du corps de la fonction, et le bénéfice est perdu. - Source

  • Il existe quelques situations dans lesquelles une fonction en ligne peut ne pas fonctionner :

    • Pour une fonction renvoyant des valeurs ;si une instruction return existe.
    • Pour une fonction ne renvoyant aucune valeur ;si une instruction boucle, switch ou goto existe.
    • Si une fonction est récursive. -Source
  • Le __inline Le mot clé entraîne l'intégration d'une fonction uniquement si vous spécifiez l'option d'optimisation.Si optimiser est spécifié, que ce soit ou non __inline est honoré dépend du paramètre de l’option d’optimisation en ligne.Par défaut, l'option en ligne est en vigueur chaque fois que l'optimiseur est exécuté.Si vous spécifiez optimise , vous devez également spécifier l'option noinline si vous souhaitez que __inline mot-clé à ignorer. -Source

Était-ce utile?

La solution

Il convient de souligner que le mot-clé inline n'est en réalité qu'un indice pour le compilateur.Le compilateur peut ignorer le code en ligne et simplement générer du code pour la fonction quelque part.

Le principal inconvénient des fonctions en ligne est qu'elles peuvent augmenter la taille de votre exécutable (en fonction du nombre d'instanciations).Cela peut poser un problème sur certaines plateformes (par ex.systèmes embarqués), surtout si la fonction elle-même est récursive.

Je recommanderais également de créer des fonctions en ligne très petit - Les avantages en termes de vitesse des fonctions en ligne ont tendance à diminuer à mesure que la fonction augmente en taille.À un moment donné, la surcharge de l'appel de fonction devient faible par rapport à l'exécution du corps de la fonction, et le bénéfice est perdu.

Autres conseils

Cela pourrait augmenter la taille de l'exécutable, et je ne pense pas que les compilateurs les rendent toujours en ligne même si vous avez utilisé le mot-clé en ligne.(Ou est-ce l'inverse, comme quoi Vaibhavdit?...)

Je pense que c'est généralement OK si la fonction n'a que 1 ou 2 instructions.

Modifier: Voici ce que Linux Style de codage le document en dit:

Chapitre 15 :La maladie en ligne

Il semble y avoir une perception erronée commune selon laquelle GCC a une option magique "Make Me Faster" Speedup appelée "en ligne".Bien que l'utilisation des Inlines puisse être appropriée (par exemple comme moyen de remplacer les macros, voir le chapitre 12), ce n'est pas souvent le cas.Une utilisation abondante du mot-clé en ligne conduit à un noyau beaucoup plus grand, qui à son tour ralentit le système dans son ensemble, en raison d'une plus grande empreinte d'Icache pour le CPU et simplement parce qu'il y a moins de mémoire disponible pour le PageCache.Pensez-y ;Une Miss de Pagecache provoque une recherche de disque, qui prend facilement 5 missicondes.Il y a beaucoup de cycles de CPU qui peuvent entrer dans ces 5 milicecondes.

Une règle de base raisonnable consiste à ne pas mettre en ligne des fonctions qui contiennent plus de 3 lignes de code.Une exception à cette règle est les cas où un paramètre est connu pour être une constante de compilation, et à la suite de cette constante vous savoir Le compilateur sera en mesure d'optimiser la majeure partie de votre fonction à l'heure de la compilation.Pour un bon exemple de ce cas ultérieur, consultez la fonction Kmalloc () en ligne.

Souvent, les gens soutiennent que l'ajout de fonctions à des fonctions statiques et utilisées une seule fois est toujours une victoire car il n'y a pas de compromis d'espace.Bien que cela soit techniquement correct, GCC est capable de les endiner automatiquement sans aide, et le problème de maintenance de la suppression de l'instruction lorsqu'un deuxième utilisateur apparaît l'emporte sur la valeur potentielle de l'indice qui indique à GCC de faire quelque chose qu'il aurait fait de toute façon.

Je suis d'accord avec les autres posts :

  • inline peut être superflu car le compilateur le fera
  • inline peut gonfler votre code

Un troisième point est que cela peut vous obliger à exposer les détails de l'implémentation dans vos en-têtes, par exemple :

class OtherObject;

class Object {
public:
    void someFunc(OtherObject& otherObj) {
        otherObj.doIt(); // Yikes requires OtherObj declaration!
    }
};

Sans l'inline, une déclaration directe de OtherObject était tout ce dont vous aviez besoin.Avec l'inline, votre en-tête a besoin de la définition d'AutreObject.

Comme d'autres l'ont mentionné, le mot-clé inline n'est qu'un indice pour le compilateur.En réalité, la plupart des compilateurs modernes ignoreront complètement cette astuce.Le compilateur a sa propre heuristique pour décider d'intégrer ou non une fonction et, franchement, ne veut pas de votre avis, merci beaucoup.

Si vous voulez vraiment, vraiment créer quelque chose en ligne, si vous l'avez réellement profilé et examiné le démontage pour vous assurer que le remplacement de l'heuristique du compilateur a réellement du sens, alors c'est possible :

  • Dans VC++, utilisez le mot-clé __forceinline
  • Dans GCC, utilisez __attribute__((always_inline))

Le mot-clé inline a cependant un deuxième objectif valable : déclarer des fonctions dans les fichiers d'en-tête mais pas dans une définition de classe.Le mot-clé inline est nécessaire pour indiquer au compilateur de ne pas générer plusieurs définitions de la fonction.

Il y a un problème avec inline - une fois que vous avez défini une fonction dans un fichier d'en-tête (ce qui implique en ligne, explicite ou implicite en définissant le corps d'une fonction membre à l'intérieur de la classe), il n'existe pas de moyen simple de la modifier sans forcer vos utilisateurs à recompiler. (par opposition à relink).Cela pose souvent des problèmes, surtout si la fonction en question est définie dans une bibliothèque et que l'en-tête fait partie de son interface.

J'en doute.Même le compilateur intègre automatiquement certaines fonctions d'optimisation.

Je ne sais pas si ma réponse est liée à la question mais :

Être très faites attention aux méthodes virtuelles en ligne !Certains compilateurs bogués (les versions précédentes de Visual C++ par exemple) généraient du code en ligne pour les méthodes virtuelles où le comportement standard consistait à ne rien faire d'autre que descendre dans l'arborescence d'héritage et appeler la méthode appropriée.

L'intégration de fonctions plus volumineuses peut rendre le programme plus volumineux, ce qui entraîne davantage d'échecs de cache et le ralentit.

Décider quand une fonction est suffisamment petite pour que l’inline augmente les performances est assez délicat. Guide de style C++ de Google recommande uniquement l'insertion de fonctions de 10 lignes ou moins.

Vous devez également noter que le mot-clé en ligne n'est qu'une requête.Le compilateur peut choisir de ne pas l'intégrer, de même, le compilateur peut choisir de créer une fonction en ligne que vous n'avez pas définie comme étant en ligne s'il pense que le compromis vitesse/taille en vaut la peine.

Cette décision est généralement prise en fonction d'un certain nombre de choses, telles que le réglage entre optimiser la vitesse (évite l'appel de fonction) et optimiser la taille (l'inline peut provoquer une surcharge du code, ce qui n'est donc pas idéal pour les grandes fonctions utilisées à plusieurs reprises).

avec le compilateur VC++, vous pouvez annuler cette décision en utilisant __forceinline

DONC en général :Utilisez en ligne si vous voulez vraiment avoir une fonction dans un en-tête, mais ailleurs, cela ne sert à rien car si vous voulez en tirer quelque chose, un bon compilateur la rendra de toute façon en ligne pour vous.

Une intégration excessive de fonctions peut augmenter la taille de l'exécutable compilé, ce qui peut avoir un impact négatif sur les performances du cache, mais de nos jours, le compilateur décide lui-même de l'intégration des fonctions (en fonction de nombreux critères) et ignore le mot-clé en ligne.

Parmi les autres problèmes liés aux fonctions en ligne, que j'ai vus très surutilisés (j'ai vu des fonctions en ligne de 500 lignes), vous devez être conscient des éléments suivants :

  • créer de l'instabilité

    • Changer la source d'une fonction en ligne entraîne la recompilation de tous les utilisateurs de l'en-tête
    • #includes fuite dans le client.Cela peut être très désagréable si vous retravaillez une fonction en ligne et supprimez un en-tête qui n'est plus utilisé sur lequel certains clients se sont appuyés.
  • taille de l'exécutable

    • Chaque fois qu'un inline est intégré au lieu d'une instruction d'appel, le compilateur doit générer l'intégralité du code de l'inline.C'est OK si le code de la fonction est court (une ou deux lignes), pas si bon si la fonction est longue
    • Certaines fonctions peuvent produire beaucoup plus de code qu’il n’y paraît à première vue.Mon exemple est un destructeur « trivial » d’une classe qui a beaucoup de variables non membres du pod (ou deux ou trois variables membres avec des destructeurs plutôt compliqués).Un appel doit être généré pour chaque destructeur.
  • temps d'exécution

    • cela dépend beaucoup de votre cache CPU et de vos bibliothèques partagées, mais la localité de référence est importante.Si le code que vous pourriez insérer se trouve dans le cache du processeur à un seul endroit, un certain nombre de clients peuvent trouver le code et ne pas souffrir d'un manque de cache et de la récupération de mémoire ultérieure (et pire, si cela se produit, une récupération de disque) .Malheureusement, c’est l’un de ces cas où vous devez vraiment effectuer une analyse des performances.

La norme de codage sur laquelle je travaille limite les fonctions en ligne à de simples setters/getters, et dit spécifiquement que les destructeurs ne doivent pas être en ligne, à moins que vous n'ayez des mesures de performances pour montrer que l'inline confère un avantage notable.

  1. Comme d'autres personnes l'ont dit, la fonction en ligne peut créer un problème si le code est volumineux. Comme chaque instruction est stockée dans un emplacement de mémoire spécifique, la surcharge de la fonction en ligne fait qu'un code prend plus de temps à s'exécuter.

  2. il existe peu d'autres situations dans lesquelles l'inline peut ne pas fonctionner

    1. ne fonctionne pas en cas de fonction récursive.
    2. Cela peut également ne pas fonctionner avec une variable statique.
    3. cela ne fonctionne pas non plus en cas d'utilisation d'une boucle, d'un commutateur, etc. ou nous pouvons dire cela avec plusieurs instructions.
    4. Et la fonction main ne peut pas fonctionner comme fonction en ligne.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top