18

最近、マイクロ ベンチマーク コードを書いているので、ベンチマーク情報と一緒に JVM の動作を出力する必要があります。私が使う

-XX:+PrintCompilation
-XX:+PrintGCDetails

JVMステータスを取得するためのその他のオプション。ベンチマーク情報については、単純にSystem.out.print()メソッドを使用します。印刷したメッセージと JVM 出力の順序を知る必要があるためです。

コンソールに出力するだけで良い結果が得られますが、JVM 出力でメッセージが破損することがありますが、それらは異なるスレッドにあるため、理解可能で許容範囲です。

バッチ ベンチマークを実行する必要がある場合は、Python を使用してファイルから結果を取得し、分析しredirect the output into a fileたいと思います。pipe (> in Linux system)

問題は次のとおりです。

The JVM output always overlapped with the messages I printed in the Java application.メッセージの完成を台無しにしました。

この状況に対処する方法はありますか?私は欲しいboth the JVM output and application output in the same place in order to preserve the sequence because it is important. And they do not overlap on each other so I don't lose anything.

4

9 に答える 9

9

少し回り道して、Java Instrumentation API の使用を検討することをお勧めします。これを行うには、単純なJava エージェントを使用 (作成) します。ベンチマークの観点からすると、これによりはるかに強力なパワーも得られます。Java エージェントを使用してすべてをログに記録できます (したがって、異なるロガー スレッド間で競合が発生することはありません)。

詳細については、http: //www.javabeat.net/2012/06/introduction-to-java-agents/またはhttp://today.java.net/pub/a/today/2008/04/24/を参照してください。 add-logging-at-class-load-time-with-instrumentation.html

于 2012-11-18T02:09:44.417 に答える
5

System.out.println()の代わりに使ってみてくださいSystem.out.print()System.out.println()同期化されたセクション内でストリームフラッシュを強制すると、少なくとも出力が混在しなくなります。

于 2013-02-19T16:13:39.510 に答える
5

ではなく、Log4J またはメッセージ駆動型ロギング フレームワークを使用しますSystem.out.println()

Log4J は、メッセージの順序を保証するメッセージ イベント モデルを使用します。さらに、さまざまな「アペンダー」を使用してデータベースまたはその他の出力/ファイルにログを記録できます。これにより、Java パッケージやその他の属性による分離が可能になり、データが混在しないようになります。

また、これらの方針に沿って、高性能タイマーの使用を検討するか、非常に短い (ミリ秒) イベントを測定しようとしないでください。その理由は、 をSystem.currentTimeMillis()呼び出すと、オペレーティング システムのクロックが呼び出されるからです。すべての OS には、基本的なシステム関数が同じ値を返すような「クロック ドリフト」とキャッシングがあり、実際の時間に +/- 30 ミリ秒のオフセットが生じます。これを改善するか、精度を上げるには、測定対象の関数を十分な大きさのサンプル サイズにグループ化し、反復回数で割ります。

たとえば、1 回の測定操作として平均 1 ~ 2 ミリ秒の操作を 10,000 回実行します。次に、10K で割り、操作あたりの時間を取得します。

それ以外の場合は、高性能タイマーが必要になります。

于 2013-02-21T23:07:20.123 に答える
4

System.out.print/println を介して直接ログを記録することは、お粗末な方法と見なされます。

なんで?

  1. 「スレッドセーフ」ではありません。複数のスレッドからログを記録すると、テキストが文字化けする
  2. ハードコーディングされ、構成されていないため、柔軟性がありません。
  3. ログに表示する詳細レベルを指定できないため、柔軟性がありません (詳細なトレース、特定のデバッグ ロジック、アプリの警告、アプリのエラー処理、アプリの致命的なエラーなど)。ログの過負荷を避けるために、常に多くのコード行をコメントする必要があります。
  4. どのパッケージ/クラスに興味があるか、または興味がないかを指定できないため、柔軟性がありません-繰り返しますが、常に多くのことを取得し、より単純で具体的なものについては多くの行にコメントする必要があります
  5. ログをデータベースのテーブルと列、ファイル、電子メール、メッセージ システム、SMS アラートなどにリダイレクトできないため、柔軟性がありません。
  6. さまざまなログ レベル/パッケージまたはクラスをさまざまなログ出力先にストリーミングできないため、柔軟性がありません。また、アプリサーバーと同じ宛先または別の宛先にログを記録するように構成することはできず、それは JVM です。
  7. 数千/数百万の行が物理ディスクに記録されていると遅い

2000 年に Log4J が導入されました。
これらすべての問題に対処し、それ以来、多かれ少なかれ標準的なソリューションとなっています。Log4J を超えようとする最新かつ最高のロギング ツールがいくつかありますが、Log4J を使用しても強力で柔軟な結果を得ることができます。すべての System.out.print 呼び出しを Log4J に切り替えると、引用された問題と他の多くの問題が消えます。

http://logging.apache.org/log4j/1.2/manual.html

于 2013-02-22T14:22:36.943 に答える
2

の場合、代わりにフラグを-XX:+PrintCompilation使用-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilationして、別の「hotspot.log」ファイルに「詳細」出力を取得できます。このファイルは XML 形式であり-XX:+PrintCompilation、そのようなコンパイルからの情報と原因の両方が含まれています。ファイル パスは、 で変更できます-XX:LogFile=<new_hotspot_log>。参考:https ://wiki.openjdk.java.net/display/HotSpot/LogCompilation+overview

の場合、 GC 出力を指定したファイルにリダイレクトするために-XX:+PrintGCDetails使用できます。-Xloggc:<gc_log>参照:java -X

于 2013-10-11T03:18:24.343 に答える
0

JVMとアプリケーションの出力を分割してみてください。

  • JVMの情報をstdoutに出力します
  • 「System.err.println()」を使用して、アプリケーションの情報をstderrに出力します
  • お気に入りのツールを使用して出力を分析します。

したがって、コマンドラインは次のようになります。

$java -XX:+PrintCompilation -XX:+PrintGCDetails MainClass 1>stdout.txt 2>stderr.txt
于 2013-02-21T06:03:49.913 に答える
0

出力が重複しないようにするには、System.out.println を使用します。次に、次のように同じファイルにリダイレクトできます。

java -XX:+PrintCompilation -XX:+PrintGCDetails MainClass 1>stdout.txt 2>&1

これには、すべてのエラーと通常のコンソール出力がファイル名 stdout.txt にあります。

また、ログに何らかの形式のスレッド/時間情報がある場合は、単純に使用できます

sort -n -k 1

-k 1 は、スレッド/データ (エポック) 情報がある列を表します。

于 2013-02-23T05:56:44.200 に答える
0

以下を試すことをお勧めします。これはハックのようなものであり、いじくり回す必要があります。しかし、このアプローチをマスターすることは、おそらく長期的に見れば報われるでしょう。特に、多くのベンチマークを行う場合。

私は、HS (現在では Oracle) がコンパイラ出力をファイルにリダイレクトするオプションを持つべきだと確信しています。あなたはそれを十分に探す必要があります:-) HSには、すべてのJVMおよびコンパイラオプションを出力するオプションが必要であり、その中には出力をファイルにリダイレクトするものがあるかもしれません.

とにかく脱線しました…

1) $JAVA_HOME または %JAVA_HOME% に src.zip があるはずです。Java クラス ライブラリのソース コードが含まれています。

2) System.out を変更して、すべての出力を特定のエラーにリダイレクトするか、grep して stdout と stderr をキャプチャできる特別なシンボルを挿入するようにします。残念ながら、この特定の手順についてこれ以上具体的に説明することはできません。これは、当社のポリシーにより、src.zip の内容を検査することが禁止されているためです。このステップがどれほど難しいか想像することしかできませんでした。おそらく、出力ストリームで「アウト」を交換するのと同じくらい簡単な場合もあれば、アプリが直接使用するすべての印刷方法を変更するのと同じくらい難しい場合もあります。System.out が使用するネイティブの数さえわかりません

3) コンパイルしたバージョンを jar ファイルに入れます。

4) コマンド ラインに次のオプションを追加します。「P」はプリペンドを表します。

うまくいけば、これは役に立ちます...

于 2012-11-18T06:11:38.703 に答える
0

まず、System.out.println() の使用について @barracel が指摘したことを試してみます。

私は Java についてあまり知りませんが、すべてのデバッグ メッセージを stderr に書き出し、stdout を JVM 用に残すこともできます。これにより、複数のスレッドが同じファイル記述子に書き込むときに明らかに発生している stdout の汚染を防ぐことができます。

于 2013-02-19T20:24:53.497 に答える