현이의 개발 이야기

제미나이로 JMH 공부하기 - 0. 학습 플랜 짜기


작년 6월, Medium에 Java의 Stream과 반복문을 비교하는 글을 올렸다.

https://medium.com/better-programming/can-streams-replace-loops-in-java-f56d4461743a

 

Can Streams Replace Loops in Java?

Code readability, performance, and limitations of Streams

betterprogramming.pub

 

Stream이 반복문을 대체할 수 있는 부분과 그러기 힘든 부분을 다루었는데,

댓글 중 JMH로 성능 측정을 한다면 확연한 성능 차이를 볼 수 있을 것이라는 얘기가 있었다.

 

JMH는 생소했기에 공부를 해야 했는데, 구글 제미나이(Gemini)를 활용해 학습 플랜을 짜고,

이 플랜에 맞게 설명과 예제를 부탁하면 쉽게 공부를 할 수 있을 것 같았다.

 

  • 제미나이 버전: Gemini Advanced
  • 프롬프트 언어: 영어

다음과 같이 학습 커리큘럼을 부탁했다.

내가 쓴 자바 코드의 성능을 측정하기 위해 JMH에 대해 학습하고 싶어. JMH의 기능들에 대해 배울 수 있는 커리큘럼과 따라 할 수 있는 예제들을 만들어줘.
더보기
I want to learn about using JMH to measure the performance of my Java code. Make me a curriculum for learning the features of JMH with examples that I can follow along.

제미나이가 작성해 준 JMH 커리큘럼

(아래 내용은 제미나이의 답변을 직접 번역한 것이다.)

모듈 1. JMH 입문

JMH란 무엇인가?

  • 마이크로 벤치마킹(Microbenchmarking)의 필요성과 왜 JMH가 자바 개발자들에게 가치 있는 툴인지 알아보기
  • Java에서 성능 측정을 할 때 발생하는 어려운 점들 알아보기 (JIT compilation, Garbage collection)
  • 위의 어려운 점들을 해결하기 위해 JMH가 어떤 역할을 하는지 알아보기

JMH 구성하기

  • Maven이나 Gradle을 이용해 프로젝트에 JMH를 어떻게 적용하는지 명확하게 설명하기

기본적인 JMH 어노테이션

  • @Benchmark: 이 어노테이션이 벤치마킹을 하려는 메서드에 어떻게 적용되는지 설명하기
  • @BenchmarkMode: 여러 다른 모드에 대해 설명하기. (Throughput, AverageTime, SampleTime, SingleShotTime)
  • @OutputTimeUnit: 결과에 대해 시간 단위를 어떻게 설정할지 알아보기
  • @State: 벤치마크 상태와 스코프의 개념에 대해 알아보기. (Thread, Group, Benchmark)

JMH 벤치마크 체험해보기

  • 문자열을 잇는 여러 방법들이 걸리는 시간을 측정하는 간단한 JMH 벤치마크 작성하기 (StringBuilder, StringBuffer, + 연산자)

모듈 2. JMH 핵심 기능들

벤치마크 파라미터

  • @Param: 벤치마크에서 여러 파라미터를 사용하는 방법 알아보기 (input size, algorithm variation)
  • @Fork: JVM 프로세스를 포크하여 더 신뢰성 있는 결과를 얻는 방법 살펴보기
  • @Warmup: JVM warm up의 중요성과 iteration을 조정하는 방법 살펴보기
  • @Measurement: 측정을 반복하는 횟수를 조정하는 방법 살펴보기

벤치마크 Best Practices

  • 현실적인 벤치마크 작성의 중요성 (dead code elimination 피하기 등)
  • 여러 하드웨어에서 벤치마크를 해야 하는 이유 알아보기
  • 벤치마크의 결과를 해석하고, 병목을 파악하는 방법 살펴보기

예시: Collection 벤치마크하기

  • Java의 여러 Collection의 추가, 검색, 삭제 연산 성능을 비교하는 벤치마크 작성하기. (ArrayList, LinkedList, HashSet)

모듈 3. JMH 심화

JMH 프로파일링

  • 코드에서 성능 병목이 일어나는 부분을 파악하기 위해 JMH 프로파일러 (-prof 옵션) 살펴보기
  • 최적화할 수 있는 부분을 짚어내기 위해 JMH 프로파일러를 사용하는 방법

블랙홀과 컨트롤 어노테이션

  • @CompilerControl: 더욱 정확한 결과를 얻기 위해 컴파일러 최적화를 조정하는 방법 살펴보기
  • @Blackhole: JVM이 연산을 최적화하는 것 방지하는 방법 살펴보기

커스텀 어노테이션

  • 구체적인 벤치마크 시나리오를 정의하기 위해 사용자 정의 어노테이션을 만드는 방법 살펴보기

예시: 동시성 코드 벤치마크하기

  • 여러 thread-safe한 자료구조의 성능을 비교하는 벤치마크 작성하기 (ConcurrentHashMap, CopyOnWriteArrayList 등)
  • 자원에 대한 경합(contention)이 성능에 미치는 영향 분석하기

커리큘럼을 보고 느낀 점

JMH에 대해 잘 모르지만, 이 커리큘럼대로라면 충분히 원하는 기본적인 벤치마크 정도는 만들 수 있을 것 같다는 생각이 들었다.

 

특히, 벤치마크를 공부해야겠다고 생각한 것이 미디엄에 올린 글 때문인데, 이 내용이 동시성 있는 코드를 다루기 때문이었다. 그런데 커리큘럼의 제일 마지막에 동시성 코드 벤치마크의 예제를 제공하여 더욱 마음에 들었다.

 

앞으로 모듈별로 학습을 진행해 나가면서 결국 원래 목표였던 Stream과 반복문의 성능 차이에 대해서도 다시 다뤄 보아야겠다.

코딩 테스트를 준비하고 있다면? 더 좋은 코드를 작성하고 싶다면?
79개 문제 풀이, 코딩전문역량인증시험(PCCP) 대비까지!

합격에 한 걸음 더 가까워지는 실전형 코딩 테스트 문제 풀이 가이드
취업과 이직을 위한 프로그래머스 코딩 테스트 문제 풀이 전략 : 자바편