Post

프로파일링

13. 프로파일링

프로파일링은 여러 가지 접근 방식이 있지만, 그중 다음 두 가지가 일반적

  • 실행
  • 할당

13.1 프로파일링 개요

JVM 프로파일링/모니터링 툴은 보통 저수준의 인스트루먼테이션(instrumentation, 다른 프로그램 또는 객체를 입력받아 대상 프로그램의 여러 지점에 끼워 넣고 원하는 로직을 실행하거나 특정 수치를 계측하는 행위)을 이용해서 작동하며, 수집한 데이터는 그래픽 콘솔에 피드백하거나 추후 분석 용도로 로그에 저장

프로파일링의 목표는 리팩터링 및 성능 최적화 대상 코드를 식별하는 것

성능 문제를 진단하고 바로잡는 첫걸음은 문제를 일으키는 리소스를 찾아내는 것

우수한 프로그래머는 핵심 코드를 주의깊게 잘 살펴봅니다. 그 전에 어떤 코드가 핵심 코드인지 식별합니다

프로파일링을 수행하기 전에 성능 문제를 밝혀내야 함

13.2 샘플링과 세이프포인팅 편향

실행 중인 코드의 자료점(data point, 스택 트레이스)을 대부분 샘플링을 통해 획득한다는 점

측정하는 행위 자체도 공짜는 아니므로 데이터 수집 비용을 조금이라도 줄이고자 메서드 입출구는 보통 추적하지 않음

샘플링 주기는 성능 엔지니어의 갈등을 일으키는 문제

성능에 예미한 애플리케이션에서 너무 자주 샘플링하면 오버헤드를 감당키 어려울 테고, 그렇다고 너무 뜸하게 샘플링하면 중요한 장면을 놓칠 가능성이 커짐

샘플링은 문제점이 데이터에 가려지게 만들 빌미를 제공할 뿐만 아니라, 대부분의 샘플링이 세이프포인트에서만 일어남 ->세이프포인팅 편향(safepointing bias)

  • 모든 스레드는 샘플을 뜨기 전에 세이프포인트에 다다라야 함
  • 세이프포인트 지점에 있는 애플리케이션 상태만 샘플링 가능

실행 프로파일러는 대부분 핫스팟 C++ API에 있는 GetCallTrace() 함수를 이용해 각 애플리케이션 스레드의 스택 샘플을 수집

GetCallTrace()는 적잖은 오버헤드를 일으킴

다음 JVM 플래그를 이용하면 세이프포인팅 시간이 높은 경우를 추적하는 데에 도움이 됨

1
-XX:+PrintGCApplicationStoppedTime

이 플래그는 GC로그에 세이프포인팅 시간에 관한 추가 정보를 로깅

세이프포인팅 편향이 일으키는 문제는 카운티드 루프(counted loop)로도 설명 가능

1
2
3
for (int i=0; i < LIMIT; i++) {
  // 단순 작업
}

LIMIT 값이 클 경우, JIT 컴파일러는 자바 코드를 루프 처음으로 되돌리는 백 브랜치를 포함헤서 즉시 동등한 컴파일드 코드로 옮김

반대로 LIMIT 값이 충분히 작을 경우에는 그런 일은 일어나지 않고, 대신 JIT 컴파일러가 루프를 펼침

따라서 세이프포인트에서만 샘플링하면 루프 크기와 우려가 그 안에서 하려는 작업 성격에 크게 좌우되는, 편행된 작동 모습을 보이게 됨

13.3 개발자용 프로파일링 툴

13.3.1 VisualVM 프로파일러

실행 프로파일러, 메모리 프로파일러가 모두 들어 있고 사용하기 쉬운 무료 툴

13.3.2 JProfiler

13.3.3 YourKit

13.3.4 JFR/JMC

13.3.5 운영 툴

현재 시스템 상태를 한눈에 보기 좋게 나타내고 전반적인 시스템 상황의 정상/비정상인지 알려주는 툴

레드햇 서모스택

이력 데이터와 특정 시점 별 상태 정보는 몽고DB에 저장

  • 유저가 직접 만든 커스텀 지표 수집, 분석
  • 필요 시 인스트루먼테이션용 커스텀 코드 주입
  • 커스텀 플러그인 작성하고 툴링을 통합 가능

뉴 렐릭

jClarity 일루미네이트

13.4 최신 프로파일러

어니스트 프로파일러(Honest Profiler)

어니스트 프로파일러의 주목표

  • 다른 대부분의 프로파일러에 있는 세이프포인트 편향을 없앰
  • 오버헤드가 아주 낮은 상태로 작동

어니스트 프로파일러는 핫스팟 내부의 AsyncGetCallTrace라는 프라이빗 API를 활용

스레드만 따로 인터럽트하므로 전역 동기화 이벤트 X

따라서 과거 프로파일러에서 고질적이었던 경합 오버헤드 현상 X

perf는 리눅스 애플리케이션의 경량급 프로파일링 툴

perf-map-agent느 브리지 역할을 수행하는 에이전트

Async 프로파일러

어니스트 프로파일러와 같은 내부 API를 쓰며 핫스팟 JVM에서만 실행 가능한 오픈소스 툴

perf에 전적으로 의존하는 툴

13.5 할당 프로파일링

대부분의 애플리케이션은 일정 수준의 메모리 프로파일링도 병행해야 함

할당 프로파일링(allocation profiling)은 애플리케이션 할당 동작을 살피는 표준 메모리 프로파일링

JVM에서 메모리 할당을 지시하는 바이트코드는 다음 세 가지

  • NEW: 주어진 타입의 객체를 생성할 공간을 할당
  • NEWARRAY: 기본형 배열 공간을 할당
  • ANEWARRAY: 주어진 타입의 객체 배열 공간을 할당

가장 단순한 인스트루먼테이션은 할당 옵코드를 지니 인스턴스를 하나하나 찾아내 실제 할당 옵코드가 실행되기 직전에 로깅하는 정적 메서드 호출부를 삽입하는 것

하지만, 이 방법은 운영계에서는 적절하지 않음

TLAB을 이용해 할당 프로파일링하는 방법도 있다.

Async 프로파일러는 핫스팟 전용 콜백을 이용해 다음 시점에 알림을 수신하는 TLAB 샘플링 기능을 지원

  • 새로 만든 TLAB 객체가 할당될 때
  • TLAB 밖에 객체가 할당될 때(느린 경로)

객체 할당을 일일이 전부 다 세지 않고, 매 n킬로바이트 단위로 뭉뚱그려 할당을 기록하는 것

덕분에 운영계에 써도 괜찮을 정도의 저렴한 비용으로 힙을 샘플링 가능

반면, 수집한 데이터는 샘플링한 데이터라 불완전

13.6 힙 덤프 분석

전체 힙의 스냅샷을 툴로 자세히 뜯어보면서 어떤 객체가 살아 있는지, 그 개수화 타입은 어떤지 등의 중요한 팩트와 객체 그래프의 형상/구조 파악

힙 덤프는 크기가 문제

힙 파일 생성은 힙을 샅샅이 뒤져 덤프 파일을 쓰는 과정이므로 STW 이벤트도 불가피함

13.6.1 hprof

JDK 5부터 내장된 hprof 프로파일러는 제품급 프로파일러라기보다는 처음부터 JVMT1 기술의 기준 구현체로 의도한 툴

자바9 이후로 hprof는 JDK에서 사라짐

hprof 신뢰 X

참조

  1. Optimizing Java(자바 최적화)
  2. https://perf.wiki.kernel.org/index.php/Main_Page
  3. https://github.com/jvm-profiling-tools/honest-profiler
This post is licensed under CC BY 4.0 by the author.