2010-08-06 5 views
3

나는 다양한 Java 클라이언트의 스레드에 대한 스택 추적을 정기적으로 인쇄하기위한 짧고 간단한 프로파일 러 (C로 작성)를 작성 중입니다. GetStackTrace 대신 문서화되지 않은 AsyncGetCallTrace 함수를 사용하여 침입을 최소화하고 스레드 상태에 관계없이 스택 추적을 허용해야합니다. 이 기능의 소스 코드는 hotspot/src/share/vm/prims/forte.cpp의 http://download.java.net/openjdk/jdk6/promoted/b20/openjdk-6-src-b20-21_jun_2010.tar.gz 에서 찾을 수 있습니다. JVMTI, 신호 처리 및 타이밍을 문서화 한 man 페이지와 AsyncGetCallTrace 호출을 설정하는 방법에 대한 세부 정보가있는 블로그를 찾았습니다. http : // jeremymanson.blogspot.com/2007/05/profiling-with-jvmtijvmpi- sigprof-and.html.AsyncGetCallTrace를 호출하는 SIGPROF 처리기를 올바르게 작성하는 방법?

이 블로그에서 누락 된 것은 신호 처리기 내에서 실제로 함수를 호출하는 코드입니다 (작성자는 독자가 독자가이 작업을 수행 할 수 있다고 가정합니다). 나는 이것을 정확하게하는 데 도움을 청하고있다. 앞에서 언급 한 파일 forte.cpp에 정의 된대로 ASGCT_CallTrace 구조체 (및 내부 구조체 ASGCT_CallFrame)를 작성하는 방법 및 위치를 잘 모르겠습니다. 구조체 ASGCT_CallTrace는 AsyncGetCallTrace에 전달 된 매개 변수 중 하나이므로 만들 필요가 있지만 필드에 올바른 값을 얻는 방법을 모르겠습니다. JNIEnv * env_id, jint num_frames 및 JVMPI_CallFrame 프레임입니다. 또한, 나는 세 번째 매개 변수가 AsyncGetCallTrace (void ucontext)에 전달 된 것을 알 수 있습니까?

위의 문제는 제가 가지고있는 주요 문제입니다. 그러나 내가 직면 한 다른 문제는 다음과 같습니다. [1] SIGPROF가 타이머에 의해 지정된 간격으로 정확히 발생하지 않는 것 같지만 다소 빈번하지 않습니다. 즉, 매초마다 SIGPROF를 보내도록 타이머를 설정하면 5 초 동안 5 개의 SIGPROF 처리기 출력 (일반적으로 1-3)이 표시됩니다. [2] SIGPROF 처리기 출력은 Java 코드의 Thread.sleep 중에 전혀 나타나지 않습니다. 그래서 SIGPROF가 매 초마다 보내지고 Thread.sleep (5000)을 가지고 있다면, 그 코드를 실행하는 동안 어떤 핸들러 출력도 얻지 못할 것입니다.

도움을 주시면 감사하겠습니다. 추가 세부 정보 (코드 및 샘플 출력물의 일부)는 요청시 게시됩니다.

감사합니다.

+0

내가 도와 줄 수는 없지만, 당신이하려는 일에 대한 브라보! 또한 최소한의 방해가되기를 원하지만 샘플이 많이 필요하지 않기 때문에 실제로 필요하지는 않다고 생각합니다. I/O를 기다리는 동안 샘플을 가져올 수 있는지 확인해야합니다. 그 주제에 관한 전반적인 화제가 있습니다 : http://stackoverflow.com/questions/1777556/alternatives-to-gprof/1779343#1779343 –

+0

사실 C 언어로 제가 몇 년 전에했던 방식은 SIGALRM을 사용하는 것이 었습니다. 스레드가 차단되었는지 여부를 트리거하는 무언가가 필요합니다. 특히 정확하지 않은 경우에는 전혀 문제가되지 않습니다. 중요한 것은 프로그램이 샘플을 가져올 때 영향을 미치지 않는다는 것입니다. –

+0

@Mike Dunlavey : 정보를 제공해 주셔서 감사합니다.하지만 제안 된 접근 방식에는 몇 가지 문제가있을 수 있습니다. 1.이 프로파일 링 프로세스를 자동화하고 일반화하고 싶습니다. 즉, 내 JVMTI 코드는 모든 Java 클라이언트와 함께 실행될 수 있으며 단순히 하나의 jvmarg (.so 파일)에 대한 언급 만 필요합니다. 매번 수동으로 휴식을 취하는 것은 시간이 많이 걸리고 체계적이지 못합니다. – user400348

답변

0

나는 마침내 긍정적 인 결과를 얻었지만 여기서는 거의 논의가 이루어지지 않았기 때문에 내 대답은 간단해질 것입니다.

ASGCT_CallTrace 구조 (및 기본 ASGCT_CallFrame 배열)는 신호 처리기에서 간단히 선언 할 수 있으므로 스택 만 존재합니다. ASGCT_CallTrace trace; JNIEnv * env; global_VM_pointer-> AttachCurrentThread ((void **) & env, NULL); trace.env_id = env; trace.num_frames = 0; ASGCT_CallFrame storage [25]; trace.frames = storage;

다음은 uContext를 가져옵니다. ucontext_t uContext; getcontext (& uContext);

다음 호출은 단지 : AsyncGetCallTrace (& 추적, 25, & uContext);

나는 그 과정에서 돌봐야 할 몇 가지 뉘앙스가있을 것이라고 확신하지만, 실제로 그 사실을 문서화하지는 않았다. 내가 성공적으로 비동기 적으로 요청하고 고정 된 간격으로 모든 Java 프로그램의 스택 추적을 얻는 전체 현재 코드를 공개 할 수 있는지 확신 할 수 없습니다. 그러나 누군가가 같은 문제에 관심이 있거나 붙어 있다면 지금 나는 도울 수있다 (나는 생각한다).

다른 두 문제 : [1] 스레드가 잠자고 SIGPROF가 생성되면 스레드는 깨어 난 후에 만 ​​해당 신호를 처리합니다. 신호를 처리하는 것은 스레드의 작업이므로 정상입니다. [2] 타이머 불완전 성이 더 이상 나타나지 않는 것 같습니다. 아마도 나는 잘못 측정했을 것입니다.

관련 문제