web-dev-qa-db-ja.com

JNI呼び出しが遅くなる原因は何ですか?

JavaでJNI呼び出しを行うときに「境界を越える」ことは遅いことを知っています。

しかし、私は知りたいですwhatそれが遅くなるのはなぜですか?基礎となるjvm実装は、JNI呼び出しを行ってそれを非常に遅くするときに何をしますか?

183
pdeva

まず、「遅い」ということは、数十ナノ秒かかる可能性のあることを言っていることは注目に値します。自明なネイティブメソッドの場合、2010年に、Windowsデスクトップでは平均40 ns、Macデスクトップでは11 nsでコールを測定しました。 多くの呼び出しを行っていない限り、気付かないでしょう。

ただし、ネイティブメソッドの呼び出しは、通常のJavaメソッド呼び出しよりもslowerになります。原因は次のとおりです。

  • ネイティブメソッドは、JVMによってインライン化されません。また、この特定のマシン用にジャストインタイムでコンパイルされることもありません。すでにコンパイルされています。
  • Java配列は、ネイティブコードでアクセスするためにコピーされ、後でコピーされます。コストは、配列のサイズに比例する場合があります。 100,000アレイのJNIcopyingを測定して、Windowsデスクトップでは平均約75マイクロ秒、Macでは82マイクロ秒でした。幸いなことに、直接アクセスは GetPrimitiveArrayCritical または NewDirectByteBuffer で取得できます。
  • メソッドにオブジェクトが渡された場合、またはコールバックを行う必要がある場合、ネイティブメソッドはおそらくJVMに対して独自の呼び出しを行っています。ネイティブコードからJavaフィールド、メソッド、およびタイプにアクセスするには、リフレクションに似たものが必要です。署名は文字列で指定され、JVMからクエリされます。これは遅いエラーが発生しやすいです。
  • Java文字列はオブジェクトであり、長さを持ち、エンコードされます。文字列にアクセスまたは作成するには、O(n)コピーが必要になる場合があります。

日付が付けられている可能性のある追加の議論は、「Java¿プラットフォームパフォーマンス:戦略と戦術」、2000年、スティーブウィルソンとジェフケッセルマンによるセクション「9.2:Examining JNI cost」にあります。約3分の1 このページ で、以下の@Philipのコメントで提供されています。

2009 IBM developerWorksのペーパー 「Java Native Interfaceを使用するためのベストプラクティス」 は、JNIのパフォーマンスの落とし穴を回避するためのいくつかの提案を提供しています。

166
Andy Thomas

nativeでマークされたすべてのJavaメソッドが「遅い」わけではないことに言及する価値があります。それらのいくつかは intrinsics であり、非常に高速になります。組み込みのものとそうでないものを確認するには、 vmSymbols.hppdo_intrinsicを探します。

23
Tema

基本的に、JVMは各JNI呼び出しのCパラメーターを解釈的に構築し、コードは最適化されません。

このペーパー で概説されている多くの詳細があります

JNI対ネイティブコードのベンチマークに興味がある場合 このプロジェクト ベンチマークを実行するためのコードがあります。

22
dmck