CHAPTER 5. 마이크로벤치마킹과 통계

AMUD·2024년 5월 7일
0

자바최적화

목록 보기
5/6

  • 자바 성능 수치를 직접 측정하는 내용을 자세히
  • 목표는 잠재적 위험을 이해하고 기준으로 삼을 만한 성능 수치만 산출하도록 안내하는 것

🗳️ 5.1 자바 성능 측정 기초

  • 성능 분석: 기초 실험과학 분야로 귀결된 다양한 기술 측면을 종합한 것
  • 벤치마크 = 하나의 과학 실험 = 입출력을 지닌 일종의 블랙 박스 ≠ 단순히 데이터 수치 분석
  • 목표: 벤치마크로 공정한 테스트를 하는 것
  • 가급적 시스템의 어느 한곳만 변경하고 다른 외부 요인은 벤치마크 안에 두고 통제

100,000개 숫자 정렬하는 벤치마크 코드 예시

public class ClassicSort {
  private static final int N = 1_000;
  private static final int I = 150_000;
  private static final List<Integer> testData = new ArrayList<>();

  public static void main(String[] args) {
    Random randomGenerator = new Random();
    for (int i = 0; i < N; i++) {
      testData.add(randomGenerator.nextInt(Integer.MAX_VALUE));
    }

    System.out.println("정렬 알고리즘 테스트");

    double startTime = System.nanoTime();

    for (int i = 0; i < I; i++) {
      List<Integer> copy = new ArrayList<>(testData);
      Collections.sort(copy);
    }

    double endTime = System.nanoTime();
    double timePerOperation = ((endTime - startTime) / (1_000_000_000L * I));
    System.out.println("결과: " + (1/timePerOperation) + "op/s");
  }
}
  • 문제점1) JVM 웜업을 전혀 고려하지 않음
    • JIT 컴파일러는 호출 계층을 최적화하므로 벤치마크 캡처 타이밍에 따라 달라짐
    • 불확정적인 가비지 수집도 고려하지 않음 → GC가 일어날 가능성이 큰 시기에는 타이밍을 캡처하지 않도록 하기
  • 문제점2) 테스트하려는 코드에서 생성된 결과를 실제로 사용하지 않는 것
    • JIT는 벤치마크하려던 것 자체를 최적화할 수도
  • 해결방안
    • 시스템 전체를 벤치마크
    • 연관된 저수준의 결과를 의미있게 비교하기 위해 앞서 언급한 많은 문제를 공통 프레임워크를 이용해 처리하는 것

💙 5.2 JMH 소개

5.2.1 될 수 있으면 마이크로벤치마크하지 말지어다

  • 애플리케이션이 아닌 인프라 문제였던 일화
  • 개발자라면 큰 그림 보기

5.2.2 휴리스틱: 마이크로벤치마킹은 언제 하나?

  • 자바 플랫폼은 원래 천성이 동적이고, 가비지 수집 및 공격적인 JIT 최적화와 같은 특성으로 성능 가늠 어렵
  • 저수준 분석이나 마이크로벤치마킹을 하는 중요 유스케이스
    • 사용 범위가 넗은 범용 라이브러리 코드를 개발한다.
    • OpenJDK 또는 다른 자바 플랫폼 구현체를 개발한다.
    • 지연에 극도로 민감한 코드를 개발한다(예: 저지연 거래)
  • 마이크로벤치마킹을 수행하였을 때 가치 있는 결과 도출 조건
    • 총 코드 경로 실행 시간은 적어도 1밀리초, 실제로는 100마이크로초 보다 짧아야 한다.
    • 메모리 할당률을 측정하는데, 그 값은 1MB/s 미만, 가급적 0에 가까운 값이어야 한다.
    • 100%에 가깝게 CPU를 사용하며 시스템 이용률은 낮게(10% 밑으로) 유지해야 한다.
    • 실행 프로파일러로 CPU를 소비하는 메서드들의 분포를 이해해야 한다. (보통 2~3개만이 많은 영향)

5.2.3 JMH 프레임워크

  • 거론한 이슈들을 해소하고자 개발된 프레임워크
  • JVM을 빌드한 사람들이 직접 만든 프레임워크라서 최적화 베어 트랩을 어떻게 피할 때 유용
  • 벤치마크 프레임워크는 컴파일 타임에 벤치마크 내용을 알 수 없으므로 동적이어야 함
  • 벤치마크 코드가 결과 신뢰도에 영향을 미칠 수 있음
  • JMH는 벤치마크 코드가 루프 최적화에 걸리지 않을 정도로 회수 조정

5.2.4 벤치마크 실행

  • 메이븐 프로젝트에서 @Bennchmark 어노테이션을 메서드에 붙여 실행
  • 주요 강력 기능
    • 컴파일러를 제어한다.
    • 벤치마크 도중 CPU 사용 수준을 시뮬레이션한다.

🔮 5.3 JVM 성능 통계

  • 결과 데이터 분포를 다루는 일은 필수
  • 모든 측정은 어느 정도의 오차 수반

5.3.1 오차 유형

  • 랜덤 오차(random error): 측정 오차 또는 무관계 요인이 어떤 상관관계 없이 결과에 영향을 미침
    • 정밀도↑ == 랜덤오차↓
  • 계통 오차(systematic error): 원인을 알 수 없는 요인이 상관관계 있는 형태로 측정에 영향을 미침
    • 정확도↑ == 계통오차↓
  • 예시
    • image

계통 오차

  • 상황: JSON을 주고받는 백엔드 자바 웹 서비스의 성능 테스트 수행
  • 작용하고 있는 두 가지 계통 효과
    • 선형 패턴으로 증가하는 위쪽 그래프(특이점 서비스)를 보니 어떤 한정된 서버 리소스가 조금씩 소모 → 메모리 누수나 스레드가 요청 처리 도중 다른 리소스를 점유하고 안 놔주는 상황에서 나타나는 패턴
    • 다른 서비스는 대부분 180밀리초 안팎의 일정한 응답 시간을 보임 → 서버 장거리 영향으로 120~150밀리초 범위의 지연 시간이 대부분 → 큰 계통 효과 때문에 실제 응답 시간의 차이가 묻혀버림
  • 계통 오차는 애플리케이션 문제가 아니라 테스트 설정부터 잘못돼서 발생한 것

랜덤 오차

  • 원인을 알 수 없는, 또는 예기치 못한 환경상의 변화 때문에 일어남
  • 소프트웨어세너는 랜덤 오차의 근원은 오직 운영 환경 뿐
  • 대부분 정규 분포를 따름 → JVM에는 이 모델이 맞지 않음

허위 상관

  • “상관은 인과를 나타내지 않는다”
  • JVM과 성능 분석 영역에서는 그럴싸해 보이는 상관관계만 보고 측정값 간의 인과 관계를 넘겨짚지 않도록 조심해야 함

5.3.2 비정규 통계학

  • 정규 분포와 같은 분석 기법은 분포 그래프에 동떨어진 특이점이 몇 개만 있어도 결과가 왜곡되기 쉬운 단점
  • 정상적인 응답 시간보다, 특이점을 유발하는 이벤트가 더 중요한 관심사
  • JIT 컴파일돼서 GC 사이클이 없는 핫 패스의 존재는 긴 꼬리형을 초래하고, 정규 분포와 대치 됨

백분위 수

  • JVM의 긴 꼬리형 비정규 분포 다루는 데 유용한 기법
  • 전체 분포를 단일 결과값으로 표현하는 평균 x, 구간별 샘플링 o
50.0% level was 23 ns
90.0% level was 30 ns
99.0% level was 43 ns
99.9% level was 164 ns
99.99% level was 248 ns
99.999% level was 3,458 ns
99.9999% level was 17,463 ns
  • 메서드 결과에서, 긴 꼬리형 분포임으로 평균, 90% 백분위 수를 차례로 구한 뒤, 이후에는 대수적 샘플링
  • 1,000개당 한크기 정도, 100,000개당 하나는 실행 시간이 두 크기 정도 나ㅈ빠짐
  • 긴 꼬리형 분포 == 고동적 범위 분포
    • 측정값의 동적 범위 = 최댓값을 최소값으로 나눈 값

💊 5.4 통계치 해석

  • 애플리케이션을 측정해서 얻은 결과값을 해석하는 일은 매우 어려움

웹 애플리케이션 응답 예시

  • image
  • 200, 400, 500대와 같은 응답 코드가 있다는 사실만 알고 있으면 응답 히스토그램 해석 가능
  • 응답 유형마다 응답 시간 분포는 다름
  • image
  • 클라이언트 오류
  • 매핑되지 않은 URL을 클라이언트가 요청하면 웹 서버는 곧장 응답
  • image
  • ↑ 서버 오류
  • 서버 에러는 장시간 처리하다가 발생하는 편
  • image
  • ↑ 성공 요청
  • 성공한 요청은 긴 꼬리형 분포를 보이지만, 실제로는 극대값이 여럿인 다봉 분포를 나타냄
  • image
  • ↑ 모든 값을 합치니 위와 같음
  • 일반적인 측정값을 보다 유의미한 하위 구성 요소들로 분해하는 개념은 아주 유용
  • 분석자는 결괏값을 보고 결론을 도출하기 전에 먼저 본인이 데이터 및 도메인을 충분히 이해해야 함

🧰 5.5 마치며

  • 마이크로벤치마킹은 어둠의 마법과도 같음
  • 유의점
    • 유스케이스를 확실히 모르는 상태에서 마이크로벤치마킹하지 않기
    • 그래도 마이크로벤치마킹을 해야 한다면 JMH를 이용
    • 여러분이 얻은 결과를 가능한 한 많은 사람과 공유하고 회사 동료들과 함께 의논
    • 항상 잘못될 가능성을 염두에 두고 여러분의 생각을 지속적으로 검증

🦴 참고

profile
210's Velog :: Ambition Makes Us Diligent

0개의 댓글