JProfiler 도움말Download

프로브


CPU 및 메모리 프로파일링은 주로 객체와 메서드 호출, 즉 JVM에서 애플리케이션의 기본 빌딩 블록에 중점을 둡니다. 일부 기술에서는 실행 중인 애플리케이션에서 의미론적 데이터를 추출하여 프로파일러에 표시하는 보다 고급의 접근 방식이 필요합니다.

가장 두드러진 예는 JDBC를 사용한 데이터베이스 호출 프로파일링입니다. 호출 트리는 JDBC API를 사용할 때와 그 호출이 얼마나 오래 걸리는지를 보여줍니다. 그러나 각 호출에 대해 다른 SQL 문이 실행될 수 있으며, 이러한 호출 중 어느 것이 성능 병목 현상의 원인인지 알 수 없습니다. 또한, JDBC 호출은 애플리케이션의 여러 다른 위치에서 발생하는 경우가 많으며, 일반 호출 트리에서 검색하지 않고 모든 데이터베이스 호출을 보여주는 단일 뷰가 필요합니다.

이 문제를 해결하기 위해 JProfiler는 JRE의 중요한 하위 시스템에 대한 여러 프로브를 제공합니다. 프로브는 특정 클래스에 계측을 추가하여 데이터를 수집하고 "Databases" 및 "JEE & Probes" 뷰 섹션의 전용 뷰에 표시합니다. 또한, 프로브는 호출 트리에 데이터를 주석으로 추가하여 일반 CPU 프로파일링과 고급 데이터를 동시에 볼 수 있습니다.

JProfiler에서 직접 지원하지 않는 기술에 대한 추가 정보를 얻고자 하는 경우, 해당 기술에 대한 사용자 정의 프로브를 작성할 수 있습니다. 일부 라이브러리, 컨테이너 또는 데이터베이스 드라이버는 자체 임베디드 프로브를 제공할 수 있으며, 애플리케이션에서 사용될 때 JProfiler에 표시됩니다.

프로브 이벤트

프로브는 오버헤드를 추가하기 때문에 기본적으로 기록되지 않으며, 각 프로브에 대해 수동 또는 자동으로 녹화를 시작해야 합니다.

프로브의 기능에 따라 프로브 데이터는 여러 뷰에 표시됩니다. 가장 낮은 수준은 프로브 이벤트입니다. 다른 뷰는 프로브 이벤트를 누적하여 데이터를 보여줍니다. 기본적으로 프로브 이벤트는 프로브가 기록 중일 때도 유지되지 않습니다. 단일 이벤트가 중요해지면 프로브 이벤트 뷰에서 기록할 수 있습니다. 파일 프로브와 같은 일부 프로브의 경우 일반적으로 높은 비율로 이벤트를 생성하기 때문에 권장되지 않습니다. "HTTP 서버" 프로브나 JDBC 프로브와 같은 다른 프로브는 훨씬 낮은 비율로 이벤트를 생성하므로 단일 이벤트를 기록하는 것이 적절할 수 있습니다.

프로브 이벤트는 메서드 매개변수, 반환 값, 계측된 객체 및 발생한 예외를 포함한 다양한 소스에서 프로브 문자열을 캡처합니다. 예를 들어, JDBC 프로브는 실제 SQL 문자열을 구성하기 위해 준비된 문서에 대한 모든 setter 호출을 가로채야 하므로 여러 메서드 호출에서 데이터를 수집할 수 있습니다. 프로브 문자열은 프로브에 의해 측정된 고급 하위 시스템에 대한 기본 정보입니다. 또한, 이벤트에는 시작 시간, 선택적 지속 시간, 관련 스레드 및 스택 트레이스가 포함됩니다.

테이블 하단에는 표시된 이벤트의 총 수를 보여주고 테이블의 모든 숫자 열을 합산하는 특별한 행이 있습니다. 기본 열의 경우, 이는 지속 시간 열만 포함됩니다. 테이블 위의 필터 선택기와 함께 선택된 이벤트 하위 집합에 대한 수집된 데이터를 분석할 수 있습니다. 기본적으로 텍스트 필터는 모든 텍스트 필드 열에서 작동하지만, 텍스트 필드 앞의 드롭다운에서 특정 필터 열을 선택할 수 있습니다. 예를 들어, 선택한 이벤트의 지속 시간보다 큰 모든 이벤트를 필터링하기 위해 컨텍스트 메뉴에서 필터 옵션을 사용할 수도 있습니다.

다른 프로브 뷰에서도 프로브 이벤트를 필터링할 수 있는 옵션을 제공합니다: 프로브 텔레메트리 뷰에서는 시간 범위를 선택할 수 있고, 프로브 호출 트리 뷰에서는 선택한 호출 스택에서 이벤트를 필터링할 수 있으며, 프로브 핫스팟 뷰는 선택한 백 트레이스 또는 핫스팟을 기반으로 프로브 이벤트 필터를 제공합니다. 제어 객체 및 타임 라인 뷰는 선택한 제어 객체에 대한 프로브 이벤트를 필터링하는 작업을 제공합니다.

선택한 프로브 이벤트의 스택 트레이스는 하단에 표시됩니다. 여러 프로브 이벤트가 선택된 경우, 스택 트레이스는 누적되어 호출 트리, 백 트레이스가 있는 프로브 핫스팟 또는 백 트레이스가 있는 CPU 핫스팟으로 표시됩니다.

스택 트레이스 뷰 옆에는 이벤트 지속 시간 및 선택적으로 기록된 처리량에 대한 히스토그램 뷰가 표시됩니다. 마우스를 사용하여 이러한 히스토그램에서 지속 시간 범위를 선택하여 위의 테이블에서 프로브 이벤트를 필터링할 수 있습니다.

프로브는 다양한 종류의 활동을 기록하고 프로브 이벤트에 이벤트 유형을 연결할 수 있습니다. 예를 들어, JDBC 프로브는 문서, 준비된 문서 및 배치 실행을 다른 색상으로 이벤트 유형으로 표시합니다.

단일 이벤트가 기록될 때 과도한 메모리 사용을 방지하기 위해 JProfiler는 이벤트를 통합합니다. 이벤트 캡은 프로파일링 설정에서 구성되며 모든 프로브에 적용됩니다. 가장 최근의 이벤트만 유지되며, 오래된 이벤트는 삭제됩니다. 이 통합은 고급 뷰에 영향을 미치지 않습니다.

프로브 호출 트리 및 핫스팟

프로브 녹화는 CPU 녹화와 긴밀히 협력합니다. 프로브 이벤트는 프로브 호출 트리에 집계되며, 프로브 문자열은 "페이로드"라고 불리는 리프 노드입니다. 프로브 이벤트가 생성된 호출 스택만 해당 트리에 포함됩니다. 메서드 노드에 대한 정보는 기록된 페이로드 이름을 참조합니다. 예를 들어, 특정 호출 스택에서 SQL 문이 총 9000ms 동안 42회 실행된 경우, 이는 모든 상위 호출 트리 노드에 이벤트 수 42와 시간 9000ms를 추가합니다. 기록된 모든 페이로드의 누적은 프로브 특정 시간을 가장 많이 소비하는 호출 경로를 보여주는 호출 트리를 형성합니다. 프로브 트리의 초점은 페이로드에 있으며, 뷰 필터는 기본적으로 페이로드를 검색하지만, 컨텍스트 메뉴에서도 클래스를 필터링하는 모드를 제공합니다.

CPU 녹화가 꺼져 있으면, 백 트레이스에는 "No CPU data was recorded" 노드만 포함됩니다. CPU 데이터가 부분적으로만 기록된 경우, 이러한 노드와 실제 백 트레이스가 혼합될 수 있습니다. 샘플링이 활성화된 경우에도 JProfiler는 기본적으로 프로브 페이로드에 대한 정확한 호출 트레이스를 기록합니다. 이 오버헤드를 피하고 싶다면, 프로파일링 설정에서 이를 끌 수 있습니다. 데이터 수집을 늘리거나 오버헤드를 줄이기 위해 조정할 수 있는 여러 다른 프로브 녹화 조정 옵션이 있습니다.

핫스팟은 프로브 호출 트리에서 계산할 수 있습니다. 핫스팟 노드는 이제 CPU 뷰 섹션과 같은 메서드 호출이 아니라 페이로드입니다. 이는 종종 프로브의 가장 즉각적으로 유용한 뷰입니다. CPU 녹화가 활성화된 경우, 최상위 핫스팟을 열고 일반 CPU 핫스팟 뷰와 마찬가지로 메서드 백트레이스를 분석할 수 있습니다. 백 트레이스 노드의 숫자는 핫스팟 바로 아래의 노드에서 가장 깊은 노드까지 확장된 호출 스택을 따라 측정된 프로브 이벤트가 몇 개이며 총 지속 시간이 얼마인지 나타냅니다.

프로브 호출 트리와 프로브 핫스팟 뷰 모두 스레드 또는 스레드 그룹, 스레드 상태 및 메서드 노드에 대한 집계 수준을 선택할 수 있습니다. CPU 뷰와 비교하여 데이터를 비교할 때, 프로브 뷰의 기본 스레드 상태가 "Runnable"이 아닌 "All states"임을 염두에 두는 것이 중요합니다. 이는 프로브 이벤트가 종종 데이터베이스 호출, 소켓 작업 또는 프로세스 실행과 같은 외부 시스템을 포함하기 때문에 현재 JVM이 작업한 시간뿐만 아니라 총 시간을 보는 것이 중요하기 때문입니다.

제어 객체

외부 리소스에 대한 액세스를 제공하는 많은 라이브러리는 리소스와 상호 작용하는 데 사용할 수 있는 연결 객체를 제공합니다. 예를 들어, 프로세스를 시작할 때 java.lang.Process 객체를 사용하여 출력 스트림에서 읽고 입력 스트림에 쓸 수 있습니다. JDBC를 사용할 때는 SQL 쿼리를 수행하기 위해 java.sql.Connection 객체가 필요합니다. JProfiler에서 이 종류의 객체에 사용되는 일반 용어는 "제어 객체"입니다.

프로브 이벤트를 제어 객체와 함께 그룹화하고 그들의 생명 주기를 보여주는 것은 문제의 원인을 더 잘 이해하는 데 도움이 될 수 있습니다. 또한, 제어 객체를 생성하는 것은 종종 비용이 많이 들기 때문에 애플리케이션이 너무 많이 생성하지 않고 적절히 닫도록 하는 것이 중요합니다. 이를 위해 제어 객체를 지원하는 프로브는 "타임 라인" 및 "제어 객체" 뷰를 제공하며, 후자는 예를 들어 JDBC 프로브의 경우 "Connections"와 같이 더 구체적으로 명명될 수 있습니다. 제어 객체가 열리거나 닫힐 때, 프로브는 이벤트 뷰에 표시되는 특별한 프로브 이벤트를 생성하여 관련 스택 트레이스를 검사할 수 있습니다.

타임 라인 뷰에서는 각 제어 객체가 막대로 표시되며, 색상은 제어 객체가 활성화된 시점을 나타냅니다. 프로브는 다양한 이벤트 유형을 기록할 수 있으며 타임 라인은 이에 따라 색상이 지정됩니다. 이 상태 정보는 이벤트 목록에서 가져오지 않으며, 통합되거나 사용할 수 없을 수도 있지만, 마지막 상태에서 매 100ms마다 샘플링됩니다. 제어 객체에는 식별할 수 있는 이름이 있습니다. 예를 들어, 파일 프로브는 파일 이름으로 제어 객체를 생성하고, JDBC 프로브는 연결 문자열을 제어 객체의 이름으로 표시합니다.

제어 객체 뷰는 모든 제어 객체를 표 형식으로 보여줍니다. 기본적으로 열려 있거나 닫힌 제어 객체가 모두 표시됩니다. 상단의 컨트롤을 사용하여 열려 있거나 닫힌 제어 객체만 표시하거나 특정 열의 내용을 필터링할 수 있습니다. 제어 객체의 기본 생명 주기 데이터 외에도, 테이블은 각 제어 객체의 누적 활동에 대한 데이터를 보여줍니다. 예를 들어, 이벤트 수와 평균 이벤트 지속 시간이 포함됩니다.

다른 프로브는 여기에서 다른 열을 표시합니다. 예를 들어, 프로세스 프로브는 읽기 및 쓰기 이벤트에 대한 별도의 열 세트를 표시합니다. 이 정보는 단일 이벤트 기록이 비활성화된 경우에도 사용할 수 있습니다. 이벤트 뷰와 마찬가지로, 하단의 총 행은 필터링과 함께 사용하여 제어 객체의 부분 집합에 대한 누적 데이터를 얻을 수 있습니다.

프로브는 중첩된 테이블에서 특정 속성을 게시할 수 있습니다. 이는 메인 테이블의 정보 과부하를 줄이고 테이블 열에 더 많은 공간을 제공하기 위해 수행됩니다. 파일 및 프로세스 프로브와 같은 중첩 테이블이 있는 경우, 각 행에는 왼쪽에 확장 핸들이 있어 속성-값 테이블을 열 수 있습니다.

타임 라인, 제어 객체 뷰 및 이벤트 뷰는 탐색 작업과 연결되어 있습니다. 예를 들어, 타임 라인 뷰에서 행을 마우스 오른쪽 버튼으로 클릭하여 다른 뷰로 이동하여 선택한 제어 객체의 데이터만 표시할 수 있습니다. 이는 제어 객체 ID를 선택한 값으로 필터링하여 달성됩니다.

텔레메트리 및 트래커

프로브에 의해 수집된 누적 데이터에서 여러 텔레메트리가 기록됩니다. 모든 프로브에 대해 초당 프로브 이벤트 수와 평균 지속 시간 또는 I/O 작업의 처리량과 같은 프로브 이벤트에 대한 평균 측정값이 제공됩니다. 제어 객체가 있는 프로브의 경우, 열린 제어 객체의 수 또한 표준 텔레메트리입니다. 각 프로브는 추가 텔레메트리를 추가할 수 있으며, 예를 들어 JPA 프로브는 쿼리 수 및 엔티티 작업 수에 대한 별도의 텔레메트리를 보여줍니다.

핫스팟 뷰와 제어 객체 뷰는 시간이 지남에 따라 추적할 수 있는 누적 데이터를 보여줍니다. 이러한 특별한 텔레메트리는 프로브 트래커로 기록됩니다. 추적을 설정하는 가장 쉬운 방법은 핫스팟 또는 제어 객체 뷰에서 선택 항목을 트래커에 추가 작업을 사용하여 새 텔레메트리를 추가하는 것입니다. 두 경우 모두 시간을 추적할지 수를 추적할지 선택해야 합니다. 제어 객체를 추적할 때, 텔레메트리는 모든 다른 프로브 이벤트 유형에 대한 누적 영역 그래프입니다. 추적된 핫스팟의 경우, 추적된 시간은 다른 스레드 상태로 나뉩니다.

프로브 텔레메트리는 "텔레메트리" 섹션에 추가하여 시스템 텔레메트리 또는 사용자 정의 텔레메트리와 비교할 수 있습니다. 그런 다음 텔레메트리 개요의 컨텍스트 메뉴 작업을 통해 프로브 녹화를 제어할 수도 있습니다.

JDBC 및 JPA

JDBC 및 JPA 프로브는 협력하여 작동합니다. JPA 프로브의 이벤트 뷰에서, JPA 프로브와 함께 JDBC 프로브가 기록된 경우, 관련된 JDBC 이벤트를 보기 위해 단일 이벤트를 확장할 수 있습니다.

마찬가지로, 핫스팟 뷰는 JPA 작업에 의해 트리거된 JDBC 호출을 포함하는 모든 핫스팟에 특별한 "JDBC 호출" 노드를 추가합니다. 일부 JPA 작업은 비동기적이며 즉시 실행되지 않고 세션이 플러시될 때 임의의 나중 시점에 실행됩니다. 성능 문제를 찾을 때, 해당 플러시의 스택 트레이스는 도움이 되지 않으므로 JProfiler는 기존 엔티티가 획득되었거나 새 엔티티가 지속된 위치의 스택 트레이스를 기억하고 이를 프로브 이벤트에 연결합니다. 이 경우, 핫스팟의 백 트레이스는 "지연된 작업"이라는 레이블이 붙은 노드 내에 포함되며, 그렇지 않으면 "직접 작업" 노드가 삽입됩니다.

MongoDB 프로브와 같은 다른 프로브는 직접 및 비동기 작업을 모두 지원합니다. 비동기 작업은 현재 스레드에서 실행되지 않지만, 동일한 JVM의 하나 이상의 다른 스레드 또는 다른 프로세스에서 실행됩니다. 이러한 프로브의 경우, 핫스팟의 백 트레이스는 "직접 작업" 및 "비동기 작업" 컨테이너 노드로 정렬됩니다.

JDBC 프로브의 특별한 문제는 ID와 같은 리터럴 데이터가 SQL 문자열에 포함되지 않은 경우에만 좋은 핫스팟을 얻을 수 있다는 것입니다. 이는 준비된 문서가 사용되는 경우 자동으로 발생하지만, 일반 문서가 실행되는 경우에는 그렇지 않습니다. 후자의 경우, 대부분의 쿼리가 한 번만 실행되는 핫스팟 목록을 얻을 가능성이 높습니다. 해결책으로, JProfiler는 준비되지 않은 문서에서 리터럴을 대체하기 위한 JDBC 프로브 구성에서 기본이 아닌 옵션을 제공합니다. 디버깅 목적으로 이벤트 뷰에서 리터럴을 여전히 보고 싶을 수 있습니다. 해당 옵션을 비활성화하면 JProfiler가 너무 많은 다른 문자열을 캐시할 필요가 없으므로 메모리 오버헤드가 줄어듭니다.

반면에, JProfiler는 준비된 문서의 매개변수를 수집하고 이벤트 뷰에서 자리 표시자가 없는 완전한 SQL 문자열을 보여줍니다. 이는 디버깅 시 유용하지만, 필요하지 않은 경우 메모리를 절약하기 위해 프로브 설정에서 이를 끌 수 있습니다.

JDBC 연결 누수

JDBC 프로브에는 데이터베이스 풀로 반환되지 않은 열린 가상 데이터베이스 연결을 보여주는 "연결 누수" 뷰가 있습니다. 이는 풀링된 데이터베이스 소스에 의해 생성된 가상 연결에만 영향을 미칩니다. 가상 연결은 닫힐 때까지 물리적 연결을 차단합니다.

누수 후보에는 "닫히지 않은" 연결과 "수집되지 않은 닫히지 않은" 연결의 두 가지 유형이 있습니다. 두 유형 모두 데이터베이스 풀에서 제공한 연결 객체가 여전히 힙에 있지만 close()가 호출되지 않은 가상 연결입니다. "수집되지 않은 닫히지 않은" 연결은 가비지 수집되었으며 확실한 연결 누수입니다.

"닫히지 않은" 연결 객체는 여전히 힙에 있습니다. 열린 이후 지속 시간이 길수록 그러한 가상 연결이 누수 후보일 가능성이 높습니다. 가상 연결은 10초 이상 열려 있을 때 잠재적인 누수로 간주됩니다. 그러나 close()가 여전히 호출될 수 있으며, 그러면 "연결 누수" 뷰에서 항목이 제거됩니다.

연결 누수 테이블에는 연결 클래스의 이름을 보여주는 클래스 이름 열이 포함되어 있습니다. 이를 통해 어떤 유형의 풀이 연결을 생성했는지 알 수 있습니다. JProfiler는 많은 수의 데이터베이스 드라이버 및 연결 풀을 명시적으로 지원하며, 가상 및 물리적 연결이 어떤 클래스인지 알고 있습니다. 알려지지 않은 풀이나 데이터베이스 드라이버의 경우, JProfiler는 물리적 연결을 가상 연결로 착각할 수 있습니다. 물리적 연결은 종종 장기간 지속되므로, "연결 누수" 뷰에 표시될 수 있습니다. 이 경우, 연결 객체의 클래스 이름은 이를 잘못된 긍정으로 식별하는 데 도움이 됩니다.

기본적으로 프로브 녹화를 시작할 때, 연결 누수 분석은 활성화되지 않습니다. 연결 누수 뷰에는 JDBC 프로브 설정의 연결 누수 분석을 위한 열린 가상 연결 기록 체크 박스에 해당하는 별도의 녹화 버튼이 있습니다. 이벤트 기록과 마찬가지로, 버튼의 상태는 지속되므로 한 번 분석을 시작하면 다음 프로브 녹화 세션에서도 자동으로 시작됩니다.

호출 트리의 페이로드 데이터

CPU 호출 트리를 볼 때, 프로브가 페이로드 데이터를 기록한 위치를 보는 것이 흥미롭습니다. 해당 데이터는 측정된 CPU 시간을 해석하는 데 도움이 될 수 있습니다. 이러한 이유로 많은 프로브가 CPU 호출 트리에 교차 링크를 추가합니다. 예를 들어, 클래스 로더 프로브는 클래스 로딩이 트리거된 위치를 보여줄 수 있습니다. 이는 호출 트리에서 보이지 않으며 예상치 못한 오버헤드를 추가할 수 있습니다. 호출 트리 뷰에서 불투명한 데이터베이스 호출은 단일 클릭으로 해당 프로브에서 추가 분석할 수 있습니다. 이는 호출 트리 분석에서도 작동하며, 분석이 프로브 호출 트리 뷰의 컨텍스트에서 자동으로 반복될 때 프로브 링크를 클릭하면 작동합니다.

또 다른 가능성은 CPU 호출 트리에 직접 페이로드 정보를 인라인으로 표시하는 것입니다. 모든 관련 프로브는 해당 목적으로 구성에 호출 트리에 주석 추가 옵션을 가지고 있습니다. 이 경우, 프로브 호출 트리에 대한 링크는 사용할 수 없습니다. 각 프로브는 자체 페이로드 컨테이너 노드를 가지고 있습니다. 동일한 페이로드 이름을 가진 이벤트는 집계되며, 호출 횟수와 총 시간이 표시됩니다. 페이로드 이름은 호출 스택별로 통합되며, 가장 오래된 항목은 "[earlier calls]" 노드로 집계됩니다. 호출 스택당 기록된 최대 페이로드 이름 수는 프로파일링 설정에서 구성할 수 있습니다.

호출 트리 분할

일부 프로브는 호출 트리에 페이로드 데이터를 주석으로 추가하기 위해 프로브 문자열을 사용하지 않습니다. 대신, 각 다른 프로브 문자열에 대해 호출 트리를 분할합니다. 이는 서버 유형 프로브에 특히 유용하며, 각 다른 유형의 수신 요청에 대해 호출 트리를 별도로 보고자 할 때 유용합니다. "HTTP 서버" 프로브는 URL을 가로채고 URL의 어떤 부분이 호출 트리를 분할하는 데 사용되어야 하는지에 대한 세밀한 제어를 제공합니다. 기본적으로 매개변수 없이 요청 URI 경로만 사용합니다.

더 유연하게 하기 위해, 분할 문자열을 결정하는 스크립트를 정의할 수 있습니다. 스크립트에서는 현재 javax.servlet.http.HttpServletRequest를 매개변수로 받고 원하는 문자열을 반환합니다.

더 나아가, 단일 분할 수준에 국한되지 않고 여러 중첩된 분할을 정의할 수 있습니다. 예를 들어, 요청 URI 경로로 먼저 분할한 다음 HTTP 세션 객체에서 추출한 사용자 이름으로 분할할 수 있습니다. 또는 요청 메서드로 요청을 그룹화한 다음 요청 URI로 분할할 수 있습니다.

중첩된 분할을 사용하면 호출 트리의 각 수준에 대한 별도의 데이터를 볼 수 있습니다. 호출 트리를 볼 때, 특정 수준이 방해가 될 수 있으며 "HTTP 서버" 프로브 구성에서 이를 제거해야 할 필요성을 느낄 수 있습니다. 더 편리하게, 기록된 데이터의 손실 없이, 해당 분할 노드의 컨텍스트 메뉴를 사용하여 호출 트리에서 분할 수준을 일시적으로 병합하고 병합 해제할 수 있습니다.

호출 트리를 분할하면 상당한 메모리 오버헤드가 발생할 수 있으므로 주의해서 사용해야 합니다. 메모리 과부하를 방지하기 위해 JProfiler는 최대 분할 수를 제한합니다. 특정 분할 수준에 대한 분할 캡이 도달하면, 캡 카운터를 재설정하는 하이퍼링크가 있는 특별한 "[capped nodes]" 분할 노드가 추가됩니다. 기본 캡이 목적에 비해 너무 낮은 경우, 프로파일링 설정에서 이를 늘릴 수 있습니다.