web-dev-qa-db-fra.com

Performances JNI vs. JNA

Nous avons une application native c/asm Utilisant le GPU (OpenCL) pour un gros encrypt/decrypt Avec une méthode spécifique, et cela fonctionne parfaitement, pas de problème. Une partie du projet (web et distribution) est en cours de développement par JEE, et nous avons juste besoin d'appeler une application/bibliothèque native.

Nous avons essayé de l'appeler comme un processus externe séparé en utilisant la classe Process. Le problème est que nous ne pouvons pas contrôler l'application (événement, gestionnaires, threads, etc ...). Nous avons également essayé de simplement basculer le code C en Java, mais les performances sont mortes. À l'exception de l'exécution du code natif en tant que processus, je pense à JNA et JNI, mais il y a quelques questions.

Questions:

  1. Pour une meilleure solution de lecture/écriture (plus rapide), est-il possible d'échanger des données par une mémoire directe (non gérée) [Java (ByteBuffer#allocateDirect())] dans JNI et JNA?
  2. Est-il possible de gérer et de gérer les processus par du code natif et d'accéder à la mémoire GPU (partagée) via Java code (lib OpenCL))?
  3. Et la performance? JNA est-il plus rapide que JNI?

Nous avons deux appareils en cluster AMD W7000 sur Redhat Linux6 x64.

30
user2889419

JNA est beaucoup plus lent que JNI, mais beaucoup plus facile. Si les performances ne sont pas un problème, utilisez JNA.

L'utilisation de tampons directs présente l'avantage que les opérations les plus critiques n'utilisent pas JNI ou JNA et sont donc plus rapides. Ils utilisent intrinsèque quand ils sont transformés en instructions de code machine unique.

Si Java est nettement plus lent que C, il est probable que le code n’ait pas été suffisamment optimisé. En général, le GPU devrait faire tout le travail, donc si Java est un peu plus lent, cela ne devrait pas faire beaucoup de différence.

par exemple. si vous passez 99% du temps dans le GPU et Java prend deux fois plus de temps, le total sera 99 + 2% ou 1% plus lent.

34
Peter Lawrey

J'ai développé une DLL simple et mis une fonction vide qui ne fait rien. Ensuite, j'ai appelé cette fonction à partir de dll avec JNA et également JNI, j'ai donc essayé de calculer le coût de leur appel. Lors de la recherche de performances après de nombreux appels, JNI était 30 à 40 fois plus rapide que JNA.

10
Mustafa Kemal

De FAQ officielle de la JNA :

Comment les performances JNA se comparent-elles à JNI personnalisé?

Le mappage direct JNA peut fournir des performances proches de celles du JNI personnalisé. Presque toutes les fonctionnalités de mappage de type du mappage d'interface sont disponibles, bien que la conversion automatique de type entraînera probablement des frais généraux.

La surcharge d'appel pour un seul appel natif utilisant le mappage d'interface JNA peut être un ordre de grandeur (~ 10X) plus longue que JNI personnalisé équivalent (que ce soit le cas dans le contexte de votre application est une question différente). En termes bruts, la surcharge d'appel est de l'ordre de centaines de microsecondes au lieu de dizaines de microsecondes. Notez que c'est la surcharge d'appel, pas la durée totale de l'appel. Cette ampleur est typique de la différence entre les systèmes utilisant des informations de type maintenues dynamiquement et les systèmes où les informations de type sont compilées statiquement. JNI codent les informations de type dans l'appel de méthode, où le mappage d'interface JNA détermine dynamiquement les informations de type au moment de l'exécution.

Vous pouvez vous attendre à une accélération d'environ un ordre de grandeur vers le mappage direct JNA, et un facteur de deux ou trois à partir de là vers JNI personnalisé. La différence réelle variera en fonction de l'utilisation et des signatures de fonction. Comme pour tout processus d'optimisation, vous devez d'abord déterminer où vous avez besoin d'une augmentation de vitesse, puis voir la différence en effectuant des optimisations ciblées. La facilité de tout programmer en Java l'emporte généralement sur les petits gains de performances lors de l'utilisation de JNI personnalisé.

10
Benoit Blanchon

Le crunching des nombres lourds se fait en C/GPU, tout votre Java <--> interface C fait est de mélanger les données in/out. Je serais surpris s'il s'agit d'un goulot d'étranglement.

Dans tous les cas, écrivez le code le plus simple et le plus clair qui fait le travail. S'il s'avère que les performances ne suffisent pas, mesure où se trouvent les goulots d'étranglement, et abordez-les un par un jusqu'à ce que les performances soient correctes. Le temps du programmeur est beaucoup plus précieux que le temps de l'ordinateur, sauf dans des circonstances très particulières.

8
vonbrand