JNI vs. JNA performance

Nous avons une application native c/asm utilisant GPU (OpenCL) pour une grande encrypt/decrypt données avec une méthode spécifique, et cela fonctionne parfaitement, pas de problème. Une partie du projet (web et distribution) est développée 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 changer le code C en Code Java, mais la performance est morte. Sauf en exécutant le 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 le processus par code natif, et d'accéder à la mémoire GPU(partagée) via le code Java (OpenCL lib)?
  3. qu'en est-il la performance? JNA est-il plus rapide que JNI?

Nous avons deux périphériques AMD W7000 clustered sur Redhat Linux6 x64.

24
demandé sur juan.facorro 2014-03-10 02:14:35

4 réponses

JNA est beaucoup plus lent que JNI, mais beaucoup plus facile. Si la performance n'est pas un problème, utilisez JNA.

L'utilisation de tampons directs a 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 les moyens qu'ils se transforment en instructions de code machine unique.

Si le code Java est significativement plus lent que C, il est probable que le code n'a pas été suffisamment optimisé. Généralement le GPU devrait faire tout le travail donc si Java est un peu plus lent ceci ne devrait pas faire beaucoup de différence.

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

34
répondu Peter Lawrey 2014-03-09 22:54:53

Le nombre important de crunching est fait en C / GPU, tout ce que votre interface Java C fait est de mélanger les données in / out. Je serais surpris si c'est 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, mesurez 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 spéciales.

8
répondu vonbrand 2014-03-09 22:57:08

De FAQ officielle de la JNA :

Comment les performances JNA se comparent - elles à celles du 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 une surcharge.

La surcharge d'appel pour un seul appel natif utilisant le mappage d'interface JNA peut être d'un ordre de grandeur (~10X) supérieur au temps JNI personnalisé équivalent (que ce soit réellement 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 le temps total d'appel. Cette ampleur est typique de la différence entre les systèmes utilisant des informations de type gérées dynamiquement et les systèmes où les informations de type sont compilées statiquement. JNI hard-codes tapez des informations dans l'invocation de la méthode, où JNA le mappage d'interface 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 passant au mappage direct JNA, et un facteur de deux ou trois passant de là à JNI personnalisé. La différence réelle varie 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 combien de différence il y a en effectuant des optimisations ciblées. La facilité de tout programmer en Java l'emporte généralement sur de petits gains de performances lors de l'utilisation de JNI personnalisé.

8
répondu Benoit Blanchon 2016-03-10 10:08:23

J'ai développé une dll simple et mis une fonction vide qui ne fait rien. Ensuite, j'ai appelé cette fonction de dll avec JNA et aussi JNI, donc j'ai essayé de calculer le coût de les appeler. En regardant la performance après de nombreux appels, JNI était 30-40 fois plus rapide que JNA.

7
répondu Mustafa Kemal 2014-08-07 05:57:18