Published on

Optimizing Java Chap13

Authors
  • avatar
    Name
    ywj9811
    Twitter

들어가며

프로그래밍에서 프로파일링은 여러 접근 방식이 있지만 두가지 방식이 가장 일반적이다.

  • 실행
  • 할당

우선 실행 프로파일링을 집중적으로 살펴보면서 어플리케이션을 프로파일링하는 데 사용 가능한 툴을 살펴보고, 메모리 프로파일링 및 관련 기능을 제공하는 다양한 툴 사용법을 알아보도록 하자.

프로파일링 개요

JVM 프로파일링/모니터링 툴은 보통 저수준의 Instrumentation(다른 프로그램 또는 객체를 입력받아 대상 프로그램의 여러 지점에 기워 넣고 원하는 로직을 실행하거나 특정 수치를 계측 하는 행위, Ex. AOP) 를 이용한다.

우리는 넓은 의미에서 모니터링 툴(주로 시스템과 그 현재 상태를 살핌)과 경고 시스템(비정상적/변칙적인 움직임 감시) 그리고 프로파일러(실행 중인 어플리케이션의 심층 정보를 제공)를 명확히 구분해야 한다.

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

실행 중인 코드의 자료점을 대부분 샘플링을 통해 획득하는데, 측정하는 행위 자체도 공짜는 아니므로 데이터 수집 비용을 조금이라도 줄이고자 메소드 출입구는 보통 추적하지 않고 스레드 실행 스냅샷을 찍는다.

이때 비교적 낮은 빈도로 찍으면 오버헤드가 그리 크지 않다. 하지만 이러한 샘플링에 대한 설정은 굉장히 어려운 과정이다. 너무 잦은 빈도는 오버헤드를 크게 할 것이고, 적은 빈도는 중요한 포인트를 놓칠 수 있기 때문이다.

또한 대부분의 샘플링은 세이프포인트에서만 일어난다는 점 또한 문제가 된다. 이를 세이프포인트 편향이라고 하며 이를 통해 두가지 중요한 결과를 수반한다.

  • 모든 스레드는 샘플을 뜨기 전에 세이프포인트에 다다라야 한다.
  • 세이프포인트 지점에 있는 어플리케이션 상태만 샘플링할 수 있다.

이는 실행 중인 프로세스를 샘플링하기 전에 모든 스레드가 세이프포인트에 있어야 하므로 그만큼 오버헤드가 가중되며, 세이프포인트 지점에 있는 어플리케이션 상태만 샘플링하기 때문에 표본점 분포가 왜곡될 소지가 있다.

실행 프로파일러는 보통 GetCallTrace() 를 사용하는데, 활성 스레드가 N개일 때 스택 샘플을 수집하려면 결국 JVM이 세이프포인트를 N번 해야하기 때문에 오베헤드를 발생시킨다. 이 또한 샘플 수집 빈도의 상한선을 정해야 하는 근본적인 이유이다.

또한 세이프포인팅 편향이 일으키는 문제는 카운티드 루프로도 설명할 수 있다.

for(int i = 0; i < LIMIT; i++) {
	// '단순' 작업 진행
}

‘단순’ 작업은 예를 들면 기본형 값의 산술 연산이나 완전히 인라이닝된 메소드 호출이 있을 수 있을 것이다.

  • LIMIT이 클 경우
    • 한번 루프가 반복될 때 마다 세이프포인트를 할 기회가 주어진다.
  • LIMIT이 충분히 작을 경우
    • JIT 컴파일러가 루프 펼치기를 수행할 것이며, 끝까지 진행하기 전에는 세이프포인트를 할 기회가 없을 것이다.

이렇게 세이프포인트에서만 샘플링 하면 루프 크기와 내부의 작업에 따라 크게 좌우될 것이다.

개발자용 프로파일링 툴

VisualVM 프로파일러

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

무료이고 쉽지만 가능 범위가 상당히 제한적이라는 한계가 있긴 하다.

JProfiler

에이전트에 기반한, 유명한 상용 프로파일러이다.

YourKit

유어킷이 개발한 상용 프로파일러로 JProfiler와 여러 방면에서 닮았다.

JFR/JMC

자바 비행 기록기(JFR), 자바 관제 센터(JMC)는 오라클이 BEA 시스템즈를 인수하면서 손에 넣은 프로파일링/모니터링 기술이다.

이는 오라클JVM에서만 사용할 수 있는 상용 툴이라서 OpenJDK를 비롯한 다른 JVM에서는 사용할 수 없었지만 자바9 이후부터 자사가 배포하는 메인 JDK는 오라클 JDK가 아닌 OpenJDK가 될 것이라 밝힌 만큼 무료 사용 가능한 오픈 소스가 될 것이다.

운영 툴

원래 프로파일러는 개발자가 문제점을 진단하거나 어플리케이션이 런타임에 저수준에서 어떻게 작동하는지 파악하려 사용하지만, 운영계 모니터링 툴로도 많이 쓰인다.

  • 레드햇 서모스탯
    • 서모스탯은 레드햇이 개발한 핫스팟 기반의 JVM 전용 오픈 소스 서비서빌리티/모니터링 솔루션이다.
  • 뉴 렐릭
    • 뉴 렐릭은 클라우드 기반 어플리케이션용 SaaS 제품으로 JVM 뿐만 아니라 사용 범위가 넓은 범용 툴 세트이다.
  • jClarity 일루미네이트
    • jClarity 일루미네이트는 개발자 프로파일링 툴과 운영 모니터링 툴 사이의 징검다리 역할을 한다.

최신 프로파일러

어니스트 프로파일러

기존 프로파일러보다 성능 수치가 더 정확하고 더 나은 통찰력을 제시하는 최신 오픈소스 툴중 하나이다.

이는 다음과 같은 주목표를 가지고 있다.

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

이는 핫스팟 내부의 AsyncGetCallTrace라는 프라이빗 API를 활용하는데, 따라서 논-OpenJDK 계열의 JVM에서는 사용할 수 없다.

할당 프로파일링

할당 프로파일링은 어플리케이션의 할당 동작을 살피는 표준 메모리 프로파일링이다.

이를 위해서는 여러 방식이 있는데, 그중 단순한 방식은 힙에 있는 모든 객체를 방문하는 방식이다.

혹은, 에이전트를 통해 할당 프로파일링을 수행하는 방법도 있다.

이를 위해서는 바이트 코드 Instrumentation이 그중 제일 간단하다.

즉, 다음과 같이 JVM에서 메모리 할당을 지시하는 바이트 코드에 들어가는 것이다.

  • NEW

    주어진 타입의 객체 생성할 공간 할당

  • NEWARRAY

    기본형 배열 공간 할당

  • ANEWARRAY

    주어진 타입의 객체 배열 공간 할당

이렇게 세가지의 바이트 코드에만 Instrumentation하면 된다.

혹은 TLAB을 이용해 할당 프로파일링 하는 방법도 있다. Async 프로파일러는 핫스팟 전용 콜백을 이용해 다음 시점에서 알림을 수신하는 TLAB 샘플링 기법을 지원한다.

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

즉, 객체 할당을 일일이 전부 다 세지 않고, 매 n(TLAB크기)킬로바이트 단위로 뭉뜽그려 할당을 기록하는 것이다.

힙 덤프 분석

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

hprof

JDK5 부터 내장된 hprof 프로파일러는 제품급 프로파일러라기 보다는 처음부터 JVMTI 기술의 기준 구현체로 의도한 툴이지만 hprof가 문서에서 자주 언급되면서 개발자 입장에서 이 툴이 실무용으로도 쓰기 좋다고 생각하게 되었다.

하지만 자바9 이후로 hprof는 JDK에서 사라졌다.

마치며

이번 장의 경우 다양한 프로파일링 툴을 소개하며 사용법을 알려주는 장으로 세세하게 정리하지는 않았지만, 책에는 세세하게 나와있으므로 실제 필요시에 정리를 참고 후 자료를 통해 구현하도록 하자.