Encore un pamphlet sur `inline`

Article original : Yet another pamphlet about inlining | Belay the C++ (belaycpp.com)
Traductrice : Chloé Lourseyre

Introduction

Le sujet de cette semaine sera le mot-cl√© inline.

C’est un sujet de longue date, qui pour moi est clos depuis longtemps. √Ä chaque fois que je le rouvre pour me re-documenter √† son sujet, j’en arrive aux m√™mes conclusions.

Cela dit, je lis très souvent du code qui utilise mal ce mot-clé, ce qui finit toujours par des situations dangereuses et contre-productives.

Je vais essayer ici de r√©sumer tout ce qu’il faut savoir √† propos de inline, les avantages, les inconv√©nients et lister les situations o√Ļ il faut ou ne faut pas l’utiliser.

Définition

Je vais commencer par une d√©finition acad√©mique donn√©e par inline specifier ‚Äď cppreference.com et traduite par mes soins:

Le but originel du mot-cl√© inline √©tait de servir d’indicateur pour l’optimiseur que la substitution du corps de la fonction √©tait pr√©f√©rable √† son appel, c’est-√†-dire au lieu d’ex√©cuter l’instruction CPU d’appel de la fonction pour transf√©rer le contr√īle au corps de la fonction, une copie de ce corps de fonction est cr√©√© par l’appel de fonction sans g√©n√©rer effectivement d’appel. Cela permet d’√©viter les instructions suppl√©mentaires cr√©√©es par l’appel de fonction (passer les argument et retourner le r√©sultat) mais peut avoir pour cons√©quences un plus gros ex√©cutable, vu que le corps de la fonction sera copi√© plusieurs fois.

√Čtant donn√© que ce mot-cl√© n’implique pas de contrainte forte, les compilateurs sont libres de substituer le corps de la fonction l√† o√Ļ le mot-cl√© inline n’est pas pr√©cis√© et de g√©n√©rer des appels de fonction l√† o√Ļ le mot-cl√© inline est pr√©cis√©. Ces choix d’optimisation ne changent pas les r√®gles √† propos des multiples d√©finitions.

Il faut retenir deux choses de cette définition :

  • Le mot-cl√© inline permet d’√©viter des instructions assembleur inutiles, rempla√ßant l’appel d’une fonction par directement le code qu’elle impl√©mente.
  • Il s’agit simplement d’une indication donn√©e au compilateur, qu’il est libre de respecter ou non.

Avec cela en tête, faisons un petit tour des avantages et des inconvénients.

Avantages

Tout d’abord, gardons en t√™te que m√™me s’il ne s’agit que d’une indication, le compilateur peut effectivement la suivre. Il a le choix de le faire, mais c’est une possibilit√© plausible. Il suffit d’imaginer le compilateur le moins intelligent du monde, qui prendrait √† la lettre les indications de inline. Il suit parfaitement le standard (selon le standard C++11 ¬ß12.1.5) et le mot-cl√© est utile dans ce cas.

Selon l’article What is C++ inline functions ‚Äď C++ Articles (cplusplus.com)2, les avantages sont :

  1. Cela acc√©l√®re le programme en √©vitant les instructions d’appel de fonction.
  2. Cela √©conomise de l’espace sur la stack car cela ne push/pull pas les param√®tres de fonction.
  3. Cela √©conomise l’instruction de retour de la fonction.
  4. Cela cr√©√© de la localit√© de r√©f√©rence, en utilisant le cache d’instruction.
  5. En la marquant comme inline, vous pouvez mettre la d√©finition d’une fonction dans un header (i.e. cela pourra √™tre inclus dans plusieurs unit√©s de compilation sans d√©ranger le linker).

Les points 1, 2 et 3 sont globalement les principaux b√©n√©fices de cette fonctionnalit√© et le but originel de ce mot-cl√©. Pour ceux qui connaissent un peu l’assembleur, cela √©vite notamment de pousser les param√®tre de la fonction sur la pile, ce qui co√Ľte de nombreuses instructions.

Le point 4 semble √™tre un effet de bord non n√©gligeable, mais comme le cache d’instruction est loin d’√™tre ma sp√©cialit√©, je ne m’√©pancherai pas sur ce sujet.

Le point 5 n’est un avantage que dans certaines situations sp√©cifique, mais un avantage malgr√© tout.

Désavantages

Selon l’article What is C++ inline functions ‚Äď C++ Articles (cplusplus.com)2, les d√©savantages sont :

  1. Cela augmente la taille de l’ex√©cutable.
  2. L’inlining est r√©solu √† la compilation. Cela signifie que si vous changez le code de la fonction inlin√©e, vous devrez re-compiler tous le code utilisant cette fonction.
  3. Ça augmente la taille de votre header avec des informations qui ne sont pas utiles pour les utilisateurs.
  4. Comme mentionn√© ci-dessus, cela augmente la taille de l’ex√©cutable, ce qui peut augmenter les fautes de pagination en m√©moire, et de ce fait diminuer les performances de votre programme.
  5. Cela peut être dérangeant dans les projets ayant des contraintes de mémoire, comme les projets embarqués.

Les point 1 et 4, qui sont m√©connus parmi les d√©veloppeurs, sont la raison principale pour laquelle le mot-cl√© inline peut diminuer les performances de votre programme. Il est important de s’en souvenir quand on l’utilise.

Le point 2 peut √™tre un inconv√©nient majeur, en fonction de la nature de votre projet, mais n’arrive pas excessivement souvent selon mon exp√©rience.

Le point 3 est, d’apr√®s moi, le plus gros d√©savantage de cette fonctionnalit√©. Pour avoir du code maintenable, vous vous devez d’√™tre clair et organis√©. inline est un point noir vis-√†-vis de cette notion.

Le point 5 concerne des projets sp√©cifiques, aussi je ne m’√©tendrai pas dessus. Mais gardez en t√™te que si vous avez des contraintes de m√©moire, inline peut avoir des cons√©quences.

Conclusion : quand faut-il utiliser inline ?

√Čviter les instructions d’appel de fonction en inlinant votre code est seulement utile dans les sections critiques de votre programme.

N’oubliez pas la loi de Paretos : ¬ę¬†80% de l’ex√©cution ne se d√©roule que dans 20% du code.¬†¬Ľ. Cela signifie que votre programme passe la plupart de son temps dans des goulots d’√©tranglement. De fait, si vous inlinez du code qui n’est pas dans un goulot, cela aura peu voire pas d’effet sur vos performances, tout en augmentant la taille de l’ex√©cutable et rendant votre code moins lisible.

Ce qui m’a pouss√© √† √©crire cet article est le fait que durant ma vie de codeur, un bon 95% des inline que j’ai pu voir sur des projets industriels √©taient utilis√© dans du code non-critique.

Il n’y a absolument aucun int√©r√™t √† r√©duire la lisibilit√© du code dans ce but.

Voici mon conseil : n’utilisez pas inline √† moins que vous soyez s√Ľr(e) √† 100% qu’il sera appel√© dans un goulot d’√©tranglement.

C’est le seul moyen d’avoir du code √† la fois propre et efficace.

Une autre mani√®re d’inliner √† √©viter

Je vais terminer cet article en disant un mot √† propos d’une pratique √† particuli√®rement √©viter.

Il s’agit des fonctions impl√©ment√©es de la mani√®re suivante :

inline void setValue(int i) { m_value = i; }

Cette pratique empêche certains debuggers de faire correctement leur travail.

Par exemple, sous VisualStudio, su vous mettez un point d’arr√™t dans cette fonction et qu’il percute, le debugger ne sera pas capable de vous donner la valeur de m_value.

Alors s’il vous pla√ģt, ne faites pas √ßa. Cela ne co√Ľte pas grand chose de rajouter un ou deux retours √† la ligne.

Sur ce, je vous dis à la semaine prochaine !

Article original : Yet another pamphlet about inlining | Belay the C++ (belaycpp.com)
Traductrice : Chloé Lourseyre

Laisser un commentaire