Qu’est-ce qui rend les appels JNI lents?

Je sais que «franchir les frontières» lors d’un appel JNI en Java est lent.

Cependant, je veux savoir ce qui le ralentit? Que fait l’implémentation JVM sous-jacente lors d’un appel JNI qui le rend si lent?

Tout d’abord, il convient de noter que “slow” parle de quelque chose qui peut prendre des dizaines de nanosecondes. Pour les méthodes natives sortingviales, en 2010, j’ai mesuré les appels en moyenne 40 ns sur mon bureau Windows et 11 ns sur mon bureau Mac. À moins que vous ne fassiez beaucoup d’ appels, vous ne remarquerez pas.

Cela dit, appeler une méthode native peut être plus lent que de faire un appel de méthode Java normal. Les causes comprennent:

  • Les méthodes natives ne seront pas incluses dans la JVM. Ils ne seront pas non plus compilés pour cette machine spécifique – ils sont déjà compilés.
  • Un tableau Java peut être copié pour un access en code natif et ultérieurement recopié. Le coût peut être linéaire dans la taille du tableau. J’ai mesuré la copie JNI d’une baie de 100 000 pixels en moyenne sur environ 75 microsecondes sur mon bureau Windows et 82 microsecondes sur Mac. Heureusement, un access direct peut être obtenu via GetPrimitiveArrayCritical ou NewDirectByteBuffer .
  • Si un object est transmis à la méthode ou si elle doit effectuer un rappel, la méthode native effectuera probablement ses propres appels à la machine virtuelle Java. L’access aux champs, méthodes et types Java à partir du code natif nécessite quelque chose de similaire à la reflection. Les signatures sont spécifiées dans les chaînes et interrogées à partir de la JVM. C’est à la fois lent et sujet aux erreurs.
  • Les chaînes Java sont des objects, ont une longueur et sont codées. L’access ou la création d’une chaîne peut nécessiter une copie O (n).

Des discussions supplémentaires, éventuellement datées, peuvent être trouvées dans “Performance de la plate-forme Java: stratégies et tactiques”, 2000, par Steve Wilson et Jeff Kesselman, dans la section “9.2: Examen des coûts JNI”. C’est à peu près le tiers de cette page , fourni dans le commentaire de @Philip ci-dessous.

Le document IBM developerWorks 2009 intitulé «Meilleures pratiques d’utilisation de l’interface Java native» fournit des suggestions pour éviter les problèmes de performances avec JNI.

Fondamentalement, la JVM construit de manière interprétative les parameters C pour chaque appel JNI et le code n’est pas optimisé.

Il y a beaucoup plus de détails décrits dans cet article

Si vous êtes intéressé par l’parsing comparative entre le code JNI et le code natif, ce projet a du code pour exécuter des tests de performances.

Il convient de mentionner que toutes les méthodes Java marquées avec native sont pas “lentes”. Certains d’entre eux sont insortingnsèques, ce qui les rend extrêmement rapides. Pour vérifier ceux qui sont insortingnsèques et ceux qui ne le sont pas, vous pouvez rechercher do_insortingnsic dans vmSymbols.hpp .