JVM (Java Virtual Machine) 성능 튜닝

JVM Heap Area 의 구성

  • new 연산자로 생성된 객체와 배열을 저장하는 공간입니다.
  • GC 로 사용하지 않는 객체들은 메모리로 반환됩니다.
  • Heap Area 종류
    • Permanent Generation: 생성된 객체들의 정보의 주소값이 저장된 공간
    • New Area
      • Eden: 객체들이 최초로 새성되는 공간
      • Survivor: Eden에서 참조되는 객체들이 저장되는 공간
      • 실제 통계로도 생성된 98% 객체가 곧바로 쓰레기 객체가 된다고 한다.
    • Old Area
      • New Area 에서 일정시간이상 참조되고 있는 객체들이 저장되는 공간

GC (Gabage Colector) 의 종류와 특징

대부분의 내용은 아래 참고 링크에서 발췌하였음,

  • Serial GC
  • Parallel GC
  • CMS GC
    • 일반적으로 많이 사용함.
  • G1 GC
    • 4G 이상의 힙 영역이 매우 큰 머신에서 설정
  • ZGC

GC 설정

  • Heap Size = 운영체제 메모리 - 2GB 정도로 하되 최대 31GB까지만 사용한다.
    • (swappiness=0 or 1이라는 가정하에- 그렇지 않으면 Swap 발생으로 성능저하가 일어날 수 있어보임)
  • 웹 애플리케이션은 운영체제 메모리중 2GB 정도를 남기고 사용한다. (ElasticSearch 제외. 각 솔루션은 솔루션 가이드를 따른다.)
    • 단, 31GB 까지만 사용한다. 32GB가 넘어가게 되면 메모리 포인터의 크기가 64bit가 되면서 메모리 점유율이 크게 늘어난다.
    • 32GB미만은 32bit 포인터 사용.
GC_OPTIONS="-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+DisableExplicitGC"
GC_LOG_OPTIONS="-Xloggc:/var/logs/gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=512K"

운영시 JVM 상태 모니터링하는 명령어

  • $ sudo yum install java-1.8.0-openjdk-devel 를 통해 도구를 설치한다.
    • sudo -u tomcat jstack <pid>
    • sudo -u tomcat jstat -gcutil -h20 <pid> 1000
    • jstat -gccapacity <pid>
    • sudo -u tomcat jmap -histo <pid>
    • jmap -heap <pid>
    • jmap -dump:live,format=b,file=dump.bin <pid> : live 되고 있는 객체만 dump 뜬다. file 위치는 홈디렉토리이다.
  • Thread 별 CPU 도 확인 할수 있음: htop 혹은 /proc/{pid}/task/000/stat 정보로 확인 가능

GC Friendly 하게 작성하기

  • new 를 남발해도 GC 오버헤드는 거의 없다. 중요한건 new 한 객체의 라이프사이클을 짧게 유지해야 한다.
    • 특히 지역변수가 참조하는 객체들
  • LinkedList 는 사용하지 않는게 GC 입장에서는 좋다.
  • 중간데이터를 저장할 때 HashMap 등의 자료구조를 이용해서 데이터가 커지지 안헥 하는 습관이 좋다.
  • 안쓰는 객체는 빨리 참조를 없애라.
  • null out when it is done. if the data-structure is big.

JIT Compiler Friendly

  • branch condition as constant
  • Do not afraid of making smaller functions
    • 가독성이 더 중요하다. JIT Compiler 의 inlining 을 통한 최적화를 믿어라
  • do not abuse native class
    • inlining is impossible

참고 링크