3

ここからこの dtrace スクリプトを使用して、Java プログラムのスレッドでコンテキスト スイッチがいつ発生するかを見つけようとしています。

スクリプトから収集されたデータを、実行中のプログラムから収集されたトレース データ (メソッドのエントリ/終了など) と照合しようとしています。単純に pthread_self() の値を返す短い JNI メソッドを使用して、実行中のスレッドの pthread ID を取得します。

私が抱えている問題は、pthread_self() を呼び出して取得したスレッド ID が、dtrace スクリプトで取得したスレッド ID とはまったく異なることです。pthread_self() はポインターを返すため、間違って呼び出しているためではないかと思いますが、mac osx で実際に pthread_t が何であるかに関する情報を見つけるのは困難でした。

4

4 に答える 4

3

だから私は自分の質問に答えます。dtrace の curthread 変数と tid 変数は、カーネル スレッド構造のポインター値です。これらの値を取得して、dtrace をユーザー空間のスレッド データと比較します。これらの内部値を取得するには、カーネル拡張機能を作成する必要がありました。ユーザー空間のスレッド用。

一般に、これは移植性がなく、カーネルが変更された場合に簡単に壊れる可能性があり、おそらくセキュリティ上のリスクになるため、悪い考えです。残念ながら、私が望むものを達成する別の方法は見つかりませんでした。

于 2009-09-15T09:34:17.347 に答える
2

から/usr/include/pthread.h:

typedef __darwin_pthread_t pthread_t;

から/usr/include/sys/_types.h

struct _opaque_pthread_t {
  long __sig;
  struct __darwin_pthread_handler_rec* __cleanup_stack;
  char __opaque[__PTHREAD_SIZE__];
};
typedef struct _opaque_pthread_t* __darwin_pthread_t;

ソースコードはあなたの友達です:)

于 2009-09-06T22:58:00.000 に答える
1

pidユーザーランド コードを処理するプロバイダーを使用して、もう少し洗練されたものはどうでしょうか。

# dtrace -n 'pid$target::pthread_self:return {printf("%p", arg1)}' -c 'java'
dtrace: description 'pid$target::pthread_self:return ' matched 1 probe
dtrace: pid 87631 has exited
CPU     ID                    FUNCTION:NAME
  0  90705              pthread_self:return 1053a7000
  0  90705              pthread_self:return 1054ad000
  2  90705              pthread_self:return 7fff7b479180
  2  90705              pthread_self:return 7fff7b479180
  2  90705              pthread_self:return 7fff7b479180
  2  90705              pthread_self:return 7fff7b479180
  2  90705              pthread_self:return 7fff7b479180
  4  90705              pthread_self:return 10542a000
  4  90705              pthread_self:return 10542a000

ハザ!

arg1プローブの戻り値を参照します。この場合はポインターです。それが指すものが必要な場合は、結果を使用して、それが何であるかを考えてキャストします(@Nikolaiの投稿を参照してください。コマンドラインのオプションを覚えている限り、DTraceスクリプトでcopyin(arg1, size_of_struct)使用できることを忘れないでください)。プロバイダー名は に展開されます。ここで、 はオプションで実行されたコマンドのプロセス ID です。この場合は.#include-Cpid$targetpid12341234-cjava

詳細については、Brendan Gregg のブログ(dtrace 情報の優れた一般情報源) を参照してください。

于 2013-05-29T23:01:35.057 に答える
0

Linux では、プロセス コンテキストの切り替えを特定するために私が見つけた最も信頼できる方法は、次のコマンドを使用することです。

pidstat -hluwrt  | grep "processname"

「tid」列 (#3) は「gettid()」と同じであるため、開発者は、CPU とコンテキストの切り替えを使用しているスレッドを直接関連付けることができます。プログラムが gettid() 値を吐き出すためにスレッドが生成されたときに、printf("%lul",gettid())を実行することをお勧めします。

プロセス コマンド ラインの前の最後の 2 列は、1 秒あたりの「cswtch/s」(自発的) および「nvcswtch/s」(非自発的) コンテキスト スイッチ カウントです。

「cswtch/s」が高い (1000 秒) 場合、プロセスは「ウェイク」と「スリープ」を過度に循環しています。スレッドを提供するために何らかの種類のバッファを検討して、より長い起動時間とスリープ時間を許可することをお勧めします。例: バッファがいっぱいでない場合、スレッドはより長くスリープ状態になります。バッファーがいっぱいになると、スレッドはバッファーが空になるまで起動されます。

「nvswtch/s」が高い (1000 の) 場合、これはシステムの負荷が高く、個々のスレッドが CPU 時間を競合している兆候です。サーバーの負荷、サーバー上のアクティブなプロセスとスレッドの量を調査することをお勧めします。「top」または「htop」はあなたの友人です。

次のスクリプトは、プロセスのスレッド化をデバッグ/最適化するのに役立ちます (20 秒ごとに出力します)。

stdbuf -oL pidstat -hluwrt  20 | stdbuf -oL grep -e "processname" -e "^#"

gettid のドキュメント: (ドキュメントはこちら)
pidstat のドキュメント: (ドキュメントはこちら)
stdbuf のドキュメント: (ドキュメントはこちら)

于 2014-10-02T15:56:05.203 に答える