- PR -

JNI関数の処理速度について

1
投稿者投稿内容
さいばぁ
会議室デビュー日: 2006/04/11
投稿数: 13
投稿日時: 2008-08-28 18:36
さいばぁと申します。

先日、JNIを使用したプログラムについて質問をさせていただき、
皆様のおかげで解決いたしました。

しかし、そのプログラムで1種類のJNI関数の処理に時間がかかるという事象が発生して
います。
いろいろ調べているとJNI関数は呼び出しが遅く、そのせいで時間がかかっているのだと
推測しているのですが、遅いのが1種類の関数のみというのが解せないのです。
この事象について解決策または遅い理由が知りたいと思いますので、
よろしくお願いいたします。

事象:NewObject関数にて毎回ではないが、他のJNI関数に比べて時間がかかっている。
   (他の関数が0〜1秒程度なのですが、NewObject関数の遅いときは2〜6秒。
    遅い事象が発生するのは大概該当プロセスの1回目の処理です。
    このプロセスは並列で10個実行されており、上位アプリからランダムに
    選ばれた空きプロセスがキックされます。)

環境:HP-UX11、JRE5.0.10

該当部分:この関数より前にJVMの起動をして、この関数の後に実際に行いたい処理が走ります。
int jni_ap_init( char* DEST_ID )
{
JNIEnv *env; /* NativeMethodI/FPointer */
JNIEnv jni;
JavaVM *jvm; /* Java VM の指定 */
JavaVM vmi;
jclass cls = NULL; /* クラス の指定 */
jclass clsjsend = NULL;
jclass clsjsnds = NULL;
jmethodID midscns = NULL;
jmethodID midsend = NULL;
jmethodID midjtout = NULL; /* Timeoutの指定 */
jstring strjdid = NULL; /* 引数String の指定 */
jobject mobjsins = NULL;
jobject mobjsend = NULL;
int iRet = 0; /* 戻り値 */

/* Java VM の取得 */
jvm = getVM();
if ( jvm == NULL ) return ERROR_SYSCALL;
vmi = *jvm;

/* JNIEnvの取得 */
iRet = vmi->GetEnv( &vmi, (void **)&env, JNI_VERSION_1_4 );
if (iRet != JNI_OK) return ERROR_SYSCALL;
jni = *env;

/* セッション生成クラスをさがす */
cls = jni->FindClass( env, "<クラス名>;" );
if( cls == NULL )
{
iRet = ERROR_FILE;
goto INIT_END;
}

/* セッション コンストラクタをさがす */
midscns = jni->GetMethodID( env, cls, "<init>", "()V" );
if( midscns == NULL )
{
iRet = ERROR_FILE;
goto INIT_END;
}

/* セッション インスタンスを生成 */
/* ↓この部分が時々時間がかかります↓ */
mobjsins = jni->NewObject( env, cls, midscns );
iRet = throw_exception( env );
if( iRet != 0 )
{
iRet = ERROR_FILE;
goto INIT_END;
}

/* インスタンスからクラスを取得 */
clsjsend = jni->GetObjectClass( env, mobjsins );
if( clsjsend == NULL )
{
iRet = ERROR_FILE;
goto INIT_END;
}

/* メソッド セッション をさがす */
midsend = jni->GetMethodID( env, clsjsend, "<Method名>", "<I/F名>;" );
if( midsend == NULL )
{
iRet = ERROR_FILE;
goto INIT_END;
}

/* メソッド セッション の実行 */
mobjsend = jni->CallObjectMethod( env, mobjsins, midsend, NULL );
if( mobjsend == NULL )
{
iRet = ERROR_FILE;
goto INIT_END;
}
iRet = throw_exception( env );
if( iRet != 0 )
{
iRet = ERROR_FILE;
goto INIT_END;
}

/* セッションクラスを取得する */
clsjsnds = jni->GetObjectClass( env, mobjsend );
if( clsjsnds == NULL )
{
iRet = ERROR_SYSCALL;
goto INIT_END;
}

以下省略

よろしくお願いいたします。
AC
会議室デビュー日: 2004/04/15
投稿数: 18
投稿日時: 2008-08-29 11:38
JITコンパイルが走っている可能性は考えられませんか?
JITコンパイラをOFFにして再検証してみてはいかがでしょう。

_________________
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-08-29 12:30
引用:

さいばぁさんの書き込み (2008-08-28 18:36) より:
事象:NewObject関数にて毎回ではないが、他のJNI関数に比べて時間がかかっている。


あてずっぽうですが、たまたまその「NewObject関数」が「他のJNI関数」に比べて、メモリーを多く消費していて、そのためにガーベッジコレクションが動いて、それに時間がかかっているということはないでしょうか。
もしこれが原因だったら、処理の前後で空きメモリー量を比較すれば、ガーベッジコレクションが動いたかどうかを簡単に推定できます。
AC
会議室デビュー日: 2004/04/15
投稿数: 18
投稿日時: 2008-08-29 14:16
引用:
もしこれが原因だったら、処理の前後で空きメモリー量を比較すれば、ガーベッジコレクションが動いたかどうかを簡単に推定できます。


つ -verbose:gc
http://www.atmarkit.co.jp/fjava/rensai3/javavm02/javavm02_2.html
_________________
さいばぁ
会議室デビュー日: 2006/04/11
投稿数: 13
投稿日時: 2008-08-29 16:37
ACさま、unibonさま
ご回答ありがとうございました。

お二人の回答を元にテスト用の上位APのシェルに
export JAVA_COMPILER=NONE
を追加したところ、
それまで10のプロセスのうち時間がかかっていたのが6プロセス程度
でしたが、3プロセス程度まで減りました。

さらにヒープメモリ調整を行おうと、-Xloggcを試そうとしたのですが、
使い方が間違っていたのか、出力ができませんでした。
時間が潤沢にあるわけではなかったため、とりあえずそれまで
-Xmx16mで実行していたものを-Xmx48mで実行したところ、
時間がかかるプロセスの数は3個から減りませんでした。
(ちなみに他のオプションは-Xms8m、-Xss352kです。)

あまりメモリを増やしても、現在10プロセスで処理しているものが
20になったときにまたメモリを増やすということになり、
ナンセンスな話のように思えましたので、これ以上は試していません。

ヒープメモリの調整について現在の使用容量がわかれば、
もっと詳細な調整ができると思うのですが、
それがわかりません。

あと、http://www.atmarkit.co.jp/fjava/rensai3/javavm01/javavm01_2.htmlに
クライアント用VMについての記載がありました。
今回の処理では私が作成しているJNI関数を使用したプログラムは
上位APのAPIとして動作するもので、公開されたクラスライブラリを持つ
ソフトウェアに接続するというものです。
こういった場合は私が作成したAPIを含めた上位APがクライアントの位置づけとなり、
このオプション(-client)を使用するのが正解なのでしょうか。
また使用する場合は、やはり上位APのシェルに追加するやり方となるのでしょうか。

よろしくお願いいたします。
さいばぁ
会議室デビュー日: 2006/04/11
投稿数: 13
投稿日時: 2008-08-29 17:11
ちなみにガベージのメモリを出力するために指定した
オプションは以下です。
export JAVA_OPTS="-verbose:gc -Xloggc:/home/h_takagi/ap3/smp/gc.txt"

テスト用上位APのシェル内に追加しています。
よろしくお願いいたします。
さいばぁ
会議室デビュー日: 2006/04/11
投稿数: 13
投稿日時: 2008-08-29 18:50
先ほどから何度かテストを続けているのですが、
時間がかかるプロセスの数は一定しないようです。
先ほどのレスでは半減したと書いたのですが、
6プロセス程度遅くなったりすることもあります。

空きメモリ容量の計測についてご教授願います。
現在はテスト用上位APを起動するシェルに先ほどのレスで
書いたオプションを追加して起動しておりますが、
指定先のディレクトリにはファイルができておりません。

また、JITコンパイラの停止についても確認方法はありますでしょうか。

よろしくお願いいたします。
AC
会議室デビュー日: 2004/04/15
投稿数: 18
投稿日時: 2008-09-01 11:39
引用:
ヒープメモリの調整について現在の使用容量がわかれば、
もっと詳細な調整ができると思うのですが、
それがわかりません。


つ -Xeprof
http://docs.hp.com/en/JAVAPROGUIDE/hotspot.html#-Xeprof

つ HPjmeter
http://h50146.www5.hp.com/products/software/oe/hpux/developer/setup/java_guide/jmeter_guide/p01.html

引用:
JITコンパイラの停止についても確認方法はありますでしょうか。


つ -Xint
http://docs.hp.com/en/JAVAPROGUIDE/hotspot.html#-Xint
_________________
1

スキルアップ/キャリアアップ(JOB@IT)