Extension inline

Un article de Wikipédia, l'encyclopédie libre.
Aller à : navigation, rechercher

En informatique, l'extension inline, ou inlining, est une optimisation d'un compilateur qui remplace un appel de fonction par le code de cette fonction. Cette optimisation vise à réduire le temps d'exécution ainsi que la consommation mémoire. Toutefois, l'extension inline peut augmenter la taille du programme (par la répétition du code d'une fonction).

Certains langages (par exemple le C ou le C++) ont un mot clé inline attachable à la définition d'une fonction. Ce mot clé indique au compilateur qu'il devrait essayer d'étendre cette fonction. Le compilateur pourra ensuite utiliser plusieurs heuristiques pour décider quelle fonction doit être étendue inline.

Implantation[modifier | modifier le code]

Dès que le compilateur décide d'étendre une fonction, l'opération est assez simple. La modification peut se faire au niveau du code source, d'une représentation intermédiaire (comme un arbre syntaxique abstrait) ou une représentation de bas niveau (bytecode ou autre).

Le principe est le calcul des valeurs des arguments, leur stockage dans des variables et finalement l'insertion du code de la fonction en lieu et place de l'appel.

Un éditeur de liens peut également implanter une extension inline. Cela permet de ne pas subir la frontière d'une bibliothèque dont le code n'est pas connu et ainsi potentiellement d'optimiser encore plus le code d'une application.

Finalement, un environnement d'exécution peut également inclure une extension inline. Par exemple, la machine virtuelle Java peut utiliser les statistiques d'exécution pour décider de fonctions à étendre.

Exemple[modifier | modifier le code]

Voici un exemple d'extension à la main sur du code en C:

int pred(int x) {
    if (x == 0)
       return 0;
    else
       return x - 1;
}

Avant extension :

 int f(int y) {
     return pred(y) + pred(0) + pred(y+1);
 }

Après extension :

int f(int y) {
    int temp = 0;
    if (y   == 0) temp += 0; else temp += y       - 1; /* (1) */
    if (0   == 0) temp += 0; else temp += 0       - 1; /* (2) */
    if (y+1 == 0) temp += 0; else temp += (y + 1) - 1; /* (3) */
    return temp;
}

Il s'agit d'un exemple à la main. Pour indiquer au compilateur C que la fonction peut être étendue, il faudrait ajouter le mot clé inline dans la déclaration de la fonction pred.

Avantages[modifier | modifier le code]

Une extension inline permet en soi d'éliminer le coût d'un appel de fonction, mais son intérêt principal est de rendre possible d'autres optimisations. En effet, le remplacement de l'appel de la fonction par le code permet au compilateur des optimisations qui ne sont pas possibles à travers un appel de fonction.

Par exemple, une condition peut être analysée comme toujours vrai (ou fausse) dans le contexte d'un appel particulier ce qui peut permettre au compilateur d'éliminer le test. L'extension inline peut également rendre possible la détection de code mort, l'optimisation d'invariant, ou encore l'élimination de variables d'induction.

Dans l'exemple précédent en C, on trouve les possibilités d'optimisation suivante

  • L'instruction temp += 0 aux lignes (1), (2) et (3) ne fait rien. Le compilateur peut les enlever.
  • La condition 0 == 0 est toujours vraie. Le compilateur peut remplacer la ligne (2) par temp += 0 (qui ne fait rien et peut donc être supprimée à son tour).
  • Le compilateur peut transformer y+1 == 0 par y == -1.
  • Le compilateur peut réduire l'expression (y + 1) - 1 à y.
  • Les expressions y et y+1 ne peuvent pas être nulles en même temps. Cela permet l'élimination d'un test.

Le résultat est alors:

int f(int y) {
    if (y == 0)
        return y;            /* or return 0 */
    else if (y == -1)
        return y - 1;        /* or return -2 */
    else
        return y + y - 1;
}

Inconvénients[modifier | modifier le code]

Le remplacement effectué lors d'une extension inline peut diminuer la performance :

  • Dans les applications où la taille de l'application est importante (plus importante que le gain de performance espéré), l'extension peut être néfaste pour des fonctions longues.
  • L'accroissement de la taille du code sur une partie cruciale du code peut entraîner un dépassement de la taille du cache CPU provoquant des cache miss avec un impact global négatif sur la performance.
  • Les variables additionnelles utilisées pour représenter les paramètres nécessitent l'utilisation de plus de registres processeur, ce qui peut provoquer des accès mémoires plus nombreux.
  • A language specification may allow a program to make additional assumptions about arguments to procedures that it can no longer make after the procedure is inlined.
  • Si la taille du code augmente au delà de la taille de la mémoire vive, il peut alors causer du thrashing. Cela arrive rarement sur des serveurs sauf en cas d'inlining très agressif. Ce problème arrive plus souvent sur des plateformes aux ressources limités (mobile, embarqué).

Les auteurs de compilateurs utilisent alors un ensemble d'heuristiques pour choisir quelles fonctions étendre dans le but d'améliorer la performance plutôt que de la dégrader.

Limitations[modifier | modifier le code]

Il n'est pas toujours possible de pratiquer une extension inline.

Le cas d'un fonction récursive est un problème. Le compilateur doit remplacer le code de la fonction à l'intérieur de son code, ce qui provoque une boucle sans fin.

Cela implique que chaque compilateur doit choisir quelle fonction étendre en fonction des mécanismes d'optimisation disponible.

Utilisation[modifier | modifier le code]

La plupart des compilateurs modernes utilisent beaucoup l'inlining car l'augmentation de la taille du code pose rarement problème et les progrès au niveau mémoire ont été plus rapides que ceux des processeurs.

L'inlining est une optimisation fondamentale pour les langages fonctionnels et objet. Dans ces cas, l'extension du code permet souvent d'appliquer de nombreuses optimisations permettant d'améliorer énormément la performance du code.

Voir aussi[modifier | modifier le code]

Liens externes[modifier | modifier le code]

Références[modifier | modifier le code]