Javaアプリケーションがありますが、Solaris10サーバーの方がWindowsPCよりも大幅に低速です。
アプリケーションのプロファイル(-Xprof)を行い、UnixFileSystem.getBooleanAttributes0メソッドがネイティブ呼び出しで約40%のCPU時間を消費することを確認しました。
検索を追跡して、動作が遅い原因を特定するにはどうすればよいですか?
更新:
dtrace
を実行し、CPU時間は0.489秒であるのに対し、time
の結果は
real 0m40.759s
user 0m47.669s
sys 0m2.287s
時間はCPUではなく別の場所で費やされているようです。このdtrace
の結果を得て、さらに調査を進めるにはどうすればよいですか?別のdtrace
オプションを使用して、より多くの情報を表示できますか?
どうもありがとうございました。
# /dtrace-toolkit/DTraceToolkit-0.99/procsystime -aTp 5695
Tracing... Hit Ctrl-C to end...
dtrace: 1032 dynamic variable drops with non-empty dirty list
^C
Elapsed Times for PID 5695,
SYSCALL TIME (ns)
gtime 7799
sysconfig 8018
lwp_kill 10105
getsockname 10215
systeminfo 10984
getrlimit 11093
lwp_self 20210
schedctl 26361
lwp_continue 27349
priocntlsys 33390
unlink 53050
lwp_sigmask 136303
setcontext 143447
so_socketpair 202427
lwp_create 223626
brk 227141
so_socket 263276
memcntl 461091
ioctl 1094955
lwp_cond_broadcast 1946728
lwp_mutex_wakeup 2579492
lwp_cond_signal 2903277
mmap 3082973
access 4446250
mprotect 4534229
getdents64 5713309
mmap64 6272480
fsat 6925239
stat 6926115
open 8324983
fcntl 8840868
close 11264404
llseek 11678791
munmap 11867401
fstat64 17852129
lwp_park 22098570
open64 23549922
stat64 39673214
read 41876097
resolvepath 81905859
yield 175946072
write 225507878
lwp_mutex_timedlock 887174392
pollsys 20393318412
lwp_cond_wait 345099369278
TOTAL: 367108549202
CPU Times for PID 5695,
SYSCALL TIME (ns)
gtime 1208
sysconfig 1647
lwp_self 2198
systeminfo 2856
lwp_kill 3186
getsockname 3625
getrlimit 4613
lwp_continue 13839
schedctl 14059
priocntlsys 14498
lwp_sigmask 20541
unlink 45801
setcontext 96874
brk 121804
lwp_park 158601
so_socketpair 195178
lwp_create 209017
so_socket 241199
memcntl 365972
ioctl 606397
lwp_cond_broadcast 1367556
lwp_mutex_wakeup 1561103
lwp_cond_signal 1803831
access 1885436
mmap 2655710
llseek 3266410
open 3614795
fsat 4043369
getdents64 4253373
mprotect 4345864
close 4547395
fcntl 4871095
stat 5183012
mmap64 5308789
fstat64 8141116
munmap 10774529
pollsys 11928811
lwp_mutex_timedlock 19212980
open64 19443958
lwp_cond_wait 23144761
read 28043647
stat64 31710269
resolvepath 70641662
yield 77731698
write 137678654
TOTAL: 489282936
Syscall Counts for PID 5695,
SYSCALL COUNT
getrlimit 1
getsockname 1
gtime 1
lwp_kill 1
rexit 1
so_socketpair 1
sysconfig 1
systeminfo 1
unlink 1
lwp_continue 2
lwp_create 2
schedctl 2
lwp_self 3
priocntlsys 3
so_socket 3
lwp_exit 4
setcontext 7
lwp_park 11
memcntl 14
brk 16
lwp_sigmask 19
mprotect 25
mmap 56
access 67
lwp_cond_broadcast 86
ioctl 87
open 100
fsat 129
mmap64 133
lwp_mutex_wakeup 148
munmap 153
lwp_cond_signal 162
getdents64 224
stat 283
pollsys 348
lwp_cond_wait 537
lwp_mutex_timedlock 558
open64 590
fcntl 625
close 777
stat64 1146
llseek 1368
read 1404
fstat64 1559
resolvepath 1644
yield 10049
write 13416
TOTAL: 35769
更新2:
これがdtraced Javaアプリケーションのソースです。1つの.jarファイルから数千のクラスをロードするだけで、より大きなアプリで観察されるのと同じ動作を再現します。
import Java.io.IOException;
import Java.io.InputStream;
import Java.util.Enumeration;
import Java.util.Properties;
public class TestCL {
public static void main(String[] args) {
Properties properties = new Properties();
InputStream in = TestCL.class.getClassLoader().getResourceAsStream("TestCL.properties");
if (in == null) {
System.err.println("TestCL.properties not found");
System.exit(-1);
}
try {
properties.load(in);
} catch (IOException e) {
System.err.println("TestCL.properties loading error");
e.printStackTrace();
System.exit(-2);
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Enumeration e = properties.keys();
while (e.hasMoreElements()) {
String className = (String) e.nextElement();
try {
Class.forName(className);
System.out.println("OK " + className);
} catch (Throwable t) {
System.err.println("KO " + className + " " + t.getClass().getName() + " " + t.getMessage());
}
}
}
}
更新3:
すべてのクラスは、単一の.jarファイルにパックされています。また、すべてのクラスを解凍してテストを実行しましたが、パフォーマンスに大きな改善はありません。
Java -cp library.jar:. TestCL
Solarisを使用している場合は、dtraceを使用できるのは幸運です。これにより、カーネルレベルでプロファイルを作成し、jvmがカーネルとどのように相互作用しているかについてより多くの手がかりを得ることができます。
詳細はこちら
http://www.devx.com/Java/Article/3394
Jvmが何をしているのかを知りたい場合は、jvmプローブを使用してdtraceを実行します。
http://Java.Sun.com/javase/6/docs/technotes/guides/vm/dtrace.html
http://www.solarisinternals.com/wiki/index.php/DTrace_Topics_Java#DTrace_Topics:_Java
これにより、プログラムに関連してはるかに意味のある出力が得られます。 「メソッドタイム」セクションをご覧ください。
http://www.princeton.edu/~unix/Solaris/troubleshoot/diskio.html
i/Oボトルネックを見つけるための優れたガイドです。
これも役立つかもしれません http://prefetch.net/blog/index.php/2007/03/03/viewing-busy-code-paths-with-dtrace/
このような問題を追跡する際の厳格なルールはありませんが、情報が重要です!!。これらのガイドに従えば、忍者システムエンジニアになるための道を進んでいます。
Jprofilerを使用できる場合があります http://www.ej-technologies.com/products/jprofiler/overview.html
オープンソースではありませんが、Javaパフォーマンスの問題を追跡することに大成功しました。
また、Java vmとアプリケーションを完全なデバッグログで実行する必要があります。カーネルログにアクセスできる場合は、異常なイベントがないか確認してください。
幸運を。
サーバー障害のある他の誰かが、このような問題を見つけるための忍者のヒントを持っていますか?私は独自のデバッグ方法を持っていますが、他の人がどう思うかを知ることは興味深いでしょうか?
- - - - - - - - -更新 - - - - - - -
トレースをもう一度見てみましたが、多くのresolvepathを実行しているようです。
これは修正する必要があります。非常に長いパスを使用していますか、それともシンボリックリンクされたディレクトリから実行していますか。シンボリックリンクを削除するか、ハードリンクを使用して、より良い結果が得られるかどうかを確認してください。
アプリは多くのディレクトリトラバーサルを実行し、相対パスではなく絶対パスを使用してみますか?.
繰り返しになりますが、私はチーズケーキを食べ過ぎていました。 Javaプローブを使用してdtraceを実行します。これにより、ドリルダウンして、Javaクラス/メソッドが最も時間を費やしているものを確認できます。
幸運(再び)。今はあきらめないでください、私たちは解決に非常に近いと思います。
Solarisシステムでsys_diag -G -I1 -l -v
を実行するだけで、すべてのパフォーマンス情報(CPU /メモリ/ネットワーク/ディスクIO/Dtrace /カーネル...)が集約され、結果の単一の色分けされた.htmlレポートで出力が分析されます。サブシステムごとにワークロードを特徴付ける/ bottlenecks ..これにより、発生している可能性のあるロック(lockstat、..)だけでなく、すべてのボトルネックが表示されます。最新バージョンはv8.1HTHです。
最終結果を投稿するだけです。
サーバー(Sun Tシリーズ)は、シングルスレッドのJavaアプリケーションの場合は非常に低速です。図を参照してください。
回答とサポートをありがとうございました。
dtrace出力は、アプリケーションがほとんどの時間を書き込みに費やしていることを示しています。チェックする必要があります(dtraceもちろん:-)を使用)whereこれらの書き込みは実行されます。彼らがsolarisファイルシステムに行く場合は、ファイルシステムがボトルネックではないかどうかを確認する必要があります。
Iostatを調べて、ディスクアクセスが予想よりも遅くなる原因となっている問題があるかどうかを確認することをお勧めします。数千のクラスをロードしても、特にブロックがキャッシュにあるように数回実行した場合は、多くのディスクIOを消費することはありません。
試してみてください
iostat -nxtcmpz 3
テストの実行中に、ビジー/待機の割合が特に高いデバイスがあるかどうか、または平均サービス時間が特に長いかどうかを確認します。死にかけているディスク、または応答しないNFSマウントの強制終了パフォーマンスがある可能性があります。