- PR -

CPU使用時間とヒープ消費量

投稿者投稿内容
がっさん
常連さん
会議室デビュー日: 2003/10/03
投稿数: 24
投稿日時: 2003-10-03 12:53
はじめまして、はじめて投稿させていただきます。

Javaコマンドオプションを使ってCPUの使用時間やヒープ消費量などの測定はできますが、
そのほかの方法としてJavaのソースからそれらを測定する方法などは
あるのでしょうか??(例えば、そういうメソッドがあるなど)
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2003-10-03 16:03
JVM内のオブジェクトヒープサイズで良ければ、
コード:

Runtime aRuntime = Runtime.getRuntime();
final int aHeapSize = aRuntime.totalMemory() - aRuntime.freeMemory();


で概算できます。ただしこれはあくまでオブジェクトヒープサイズであり、実際の使用量とは異なります。

CPU使用時間はSystem.currentTimeMills()で現在の時間を取得することで、概算することは可能です。
この値はGCの発動具合により、変動するので複数回の測定の平均値などで評価しないといけないかもしれません。

[ メッセージ編集済み 編集者: かずくん 編集日時 2003-10-03 16:09 ]
raccoon
ベテラン
会議室デビュー日: 2002/12/18
投稿数: 58
投稿日時: 2003-10-03 17:23
System.currentTimeMillis()はCPU時間ではなく実時間では?
そのプロセスの平均的なCPU利用率がわかれば概算できるでしょうが・・・。

CPU時間は,JVMPIを使ってC言語で実装すればできそうな気がしますが,
私はJVMPIは使ったことないのでよくわかりません。
識者の方,フォローいただければ。
さくらば
大ベテラン
会議室デビュー日: 2002/11/12
投稿数: 145
投稿日時: 2003-10-04 06:15
こんにちは、さくらばです。

引用:

raccoonさんの書き込み (2003-10-03 17:23) より:

CPU時間は,JVMPIを使ってC言語で実装すればできそうな気がしますが,
私はJVMPIは使ったことないのでよくわかりません。



JVMPI を使えば、ヒープに関してはかなり詳細な情報を得ることができます。
オブジェクトのアロケーション、リリースのイベントがあり、そのときに
オブジェクトのクラス、サイズなどの情報も一緒に取れます。

また、GC の情報も取れるますが、これは -verbose:gc で得られるものと
同じ情報です。

ただ、残念ながら CPU 時間はとれません。また、実時間から概算するとしても、
JVMPI を使うとかなり重たくなってしまうので、そこから得られた結果が
普通に動作させたときのものと比較できなくなってしまいます。

JVMPI に関しては
http://java.sun.com/j2se/1.4/ja/docs/ja/guide/jvmpi/jvmpi.html

また、私が以前講演した時の資料でよろしければ以下のURLにあります。
http://www5.airnet.ne.jp/sakuraba/java/publication/20030414-JIAE-Seminar/20030414JIAE-profiler.pdf


CPU 時間などの JVM のモニタリングに関しては JSR-174 で標準化が始まって
いるので、気長に待ちましょう。

http://jcp.org/en/jsr/detail?id=174

さくらば
大ベテラン
会議室デビュー日: 2002/11/12
投稿数: 145
投稿日時: 2003-10-04 06:22
補足です。

引用:

さくらばさんの書き込み (2003-10-04 06:15) より:
ただ、残念ながら CPU 時間はとれません。また、実時間から概算するとしても、
JVMPI を使うとかなり重たくなってしまうので、そこから得られた結果が
普通に動作させたときのものと比較できなくなってしまいます。



JVMPI でメソッドの開始と終了のイベントが取れるので、実時間を計測しておけば、
メソッドごとの合計処理時間は算出することができます。それは CPU 時間とは違い
ますが、ボトルネックは見つけることが可能です。

Emacs信者
常連さん
会議室デビュー日: 2003/08/10
投稿数: 38
投稿日時: 2003-10-04 23:11
僕が使っている、CPU使用率を取得するコードを記載します。
とは言っても、ベタな方法で取得しているだけですが…
しかも「CPU時間」ではないです。
まぁ、参考になればどうぞ。
一応、VineLinux2.5で動作確認済みです。

制限事項としては、

・当然、vmstatがないとダメ
・1秒未満の間隔で値を取得できない(これはvmstatの制限なので仕方ないです)

です。
コード:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Vmstat{
private Vmstat(){}

///////////////////////////////////////////////////////////////////////////

public static void main(String[] args)throws Exception{
while(true){
System.out.println("cpu load="+getCpuLoad());
Thread.sleep(200);
}
}

///////////////////////////////////////////////////////////////////////////

private static BufferedReader reader;
private static Process proc;
private static boolean commandNotFound;
private static volatile boolean initialized;
private static volatile boolean terminated;

private static volatile String vmstatLine="";

///////////////////////////////////////////////////////////////////////////

private static void classFinalize(){kill();}

///////////////////////////////////////////////////////////////////////////

private static synchronized void init()throws IOException{
initialized=true;

try{
proc=Runtime.getRuntime().exec("vmstat -n 1");
}catch(IOException e){ //'vmstat' not found
commandNotFound=true;
e.printStackTrace();
return;
}

reader=new BufferedReader(new InputStreamReader(proc.getInputStream()));

//dispose header lines
reader.readLine();
reader.readLine();

vmstatLine=reader.readLine();
}

///////////////////////////////////////////////////////////////////////////

/**
* プロセスを殺す
*/
public static synchronized void kill(){
terminated=true;

if(proc!=null)
try{
proc.destroy();
proc=null;
}catch(Throwable e){
}
}

///////////////////////////////////////////////////////////////////////////

/**
* vmstatの出力文字列を取得する
*/
public static String getVmstatOutput(){
if(commandNotFound||terminated)
return null;

try{
if(!initialized)
init();
else
while(reader.ready())
vmstatLine=reader.readLine();
}catch(IOException e){
throw new RuntimeException(e);
}

return vmstatLine;
}

/**
* ユーザ使用率とシステム使用率の合計を出す
*/
public static int getCpuLoad(){
final String line=getVmstatOutput();

if(line==null)return -1;

final int length=line.length();

//output format of standard vmstat command (linux)
//ex.
//
// cpu <-- output once at first (dispose)
// us sy id <-- output once at first (dispose)
// 95 0 5 <-- substring(69,72)=="95 " , substring(73,76)==" 0 "
// 95 0 5 <-- substring(69,72)=="95 " , substring(73,76)==" 0 "
// 5 8 86 <-- substring(69,72)==" 5 " , substring(73,76)==" 8 "
// 0 0 100 <-- substring(69,72)==" 0 " , substring(73,76)==" 0 "

try{
if(length<76)return -1;

final String us=line.substring(69,72);
final String sy=line.substring(73,76);

return Integer.parseInt(us.trim())+Integer.parseInt(sy.trim());
}catch(NumberFormatException e){
return -1;
}
}
}



[ メッセージ編集済み 編集者: Emacs信者 編集日時 2003-10-04 23:16 ]
がっさん
常連さん
会議室デビュー日: 2003/10/03
投稿数: 24
投稿日時: 2003-10-06 10:41
皆さんの返信、ありがとうございます。
JVMPIまで自分で操作できるか分からないですけれども、
いろいろ試してみたいと思います。

また、何かありましたらよろしくお願いします。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-10-06 11:11
unibon です。こんにちわ。

余談になるのですが、
「CPU 時間」に GC の時間は含めるべきなのかどうかで悩みます。
と言うのも、Java が絡まない場合にページングにかかる時間は、
User CPU time に含めないと思います(これは正しい?)が、
Java の場合の GC は、ページングに相当すると思うので。
もっとも、ページングと GC を同じ土俵で比べるのもそもそもヘンな感じもしますが、
どちらもメモリがふんだんにあればそれなりに端折ることができる時間なので。

同様に、ヒープ使用量も、totalMemory を見るべきか、
(totalMemory - freeMemory) を見るべきかで悩みます。

#Java というバーチャルな環境だからなのでしょうけど。

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