Fonctions inline en Kotlin : quand sont-elles vraiment nécessaires et quand nuisent-elles

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Fonctions inline en Kotlin : magie d'optimisation ou piège pour débutant ?



Si vous avez déjà écrit en Kotlin et jeté un œil à la bibliothèque standard, vous avez sûrement vu le mot mystérieux inline avant la déclaration de fonctions. Peut-être l'avez-vous même ajouté à votre code, en suivant l'exemple de collègues « expérimentés ». Mais comprenez-vous vraiment quand une fonction inline apporte un bénéfice, et quand elle ne fait que gonfler le bytecode et ralentir la compilation ?



Cette question est l'une des plus populaires sur Stack Overflow (des milliers de vues !), et ce n'est pas pour rien. Nous n'allons pas copier des manuels arides. Au lieu de cela, nous allons analyser trois scénarios réels où les fonctions inline deviennent vos meilleures amies, et un où il vaut mieux les éviter. C'est parti !



Qu'est-ce qu'une fonction inline en 30 secondes (rafraîchissons la mémoire)



Lorsque vous marquez une fonction avec le mot-clé inline, le compilateur ne crée pas d'objet séparé en mémoire pour elle. Au lieu de cela, il « colle » littéralement le corps de la fonction à chaque endroit où elle est appelée. Imaginez que vous copiez un morceau de code et le collez directement au point d'appel — voilà ce qui se passe sous le capot.



Sans inline :

fun measureTime(action: () -> Unit) {    val start = System.currentTimeMillis()    action()    println("Time: ${System.currentTimeMillis() - start}ms")}

fun main() { measureTime { /* votre code */ }}


Avec inline :

inline fun measureTime(action: () -> Unit) {    val start = System.currentTimeMillis()    action()    println("Time: ${System.currentTimeMillis() - start}ms")}

fun main() { measureTime { /* votre code */ }}


La différence est invisible à l'œil, mais le compilateur créera un bytecode complètement différent. Dans le premier cas, un objet lambda anonyme sera créé, dans le second, le code sera simplement copié. Voyons maintenant quand cela est vraiment important.



Scénario n°1 : Fonctions d'ordre supérieur avec lambdas (le cas le plus fréquent)



Si votre fonction accepte une autre fonction comme paramètre (ce qu'on appelle une higher-order function), chaque appel de lambda crée une classe anonyme. Sur une section de code chaude, appelée des milliers de fois par seconde, cela peut entraîner :

  • Des allocations d'objets inutiles dans le tas
  • Une charge sur le ramasse-miettes
  • Une perte de performance allant jusqu'à 10-20%


Quand inline sauve la mise :

  • Vous appelez fréquemment la même fonction avec des lambdas dans une boucle
  • Votre fonction fait partie d'une bibliothèque et vous ne savez pas comment elle sera utilisée
  • La lambda capture beaucoup de variables (inline réduit les frais généraux)


// Mauvais sans inline (si appelé fréquemment)fun repeatAction(times: Int, action: () -> Unit) {    for (i in 0 until times) {        action()    }}

// Bon avec inlineinline fun repeatAction(times: Int, action: () -> Unit) { for (i in 0 until times) { action() }}


Mais il y a un hic : si votre fonction est appelée rarement (une fois par minute) ou si la lambda est grande, l'avantage de inline tend vers zéro. Ne faites pas inline « au cas où ».



Scénario n°2 : Reified generics — le seul moyen de travailler avec les types à l'exécution



En Java et Kotlin, les génériques sont effacés lors de la compilation. Vous ne pouvez pas écrire if (value is T) ou T::class.java à l'intérieur d'une fonction normale. Mais avec inline et reified, cela devient possible !



Exemple concret — création d'une instance par type :



// Cela NE compilera PASfun <T> createInstance(): T {    return T::class.java.newInstance() // Erreur !}

// Mais cela fonctionne !inline fun <reified T> createInstance(): T { return T::class.java.newInstance()}


Sans inline, vous ne pouvez pas utiliser reified. C'est le seul cas où inline est obligatoire, et pas simplement

Blogs

Book Recommendations