-
Notifications
You must be signed in to change notification settings - Fork 1
자바 애플리케이션 성능 및 메모리 관리(JVM)
rnjstjdgh edited this page May 19, 2021
·
49 revisions
- 강좌 링크: https://www.udemy.com/course/java-application-performance-and-memory-management/learn/lecture/13816100?
- the java 코드를 조작하는 다양한 방법: https://docs.google.com/document/d/11zgALhqn3igwfs4xc9cYdRPlyS84M6ba_6xz0I2M-Ik/edit
-
두 가지 관점에서 생각
- Memory constraints(메모리 제약)
- application speed(속도)
-
java 언어적인 측면이 아니라 JVM 실행 환경적인 측면에 대한 내용이 주를 이룰 것임
- JIT 컴파일러
-
기본적으로 JVM은 바이트코드를 인터프리팅 방식으로 실행
- 바이트코드를 직접 실행하기 때문에 native보다 느림
- 인터프리팅 방식은 컴파일 방식보다 느릴 수 밖에 없음(한줄 한줄 실행하기 때문에 전체를 보며 최적화가 어려움)
-
JVM은 실행 환경을 프로파일링 하면서 [자주 실행되는 | 복잡한 | 시간이 많이 걸리는] 블록을 [bytecode => native code]로 컴파일 하며 최적화를 한다.
-
프로파일링 및 컴파일 과정은 JVM내의 별도의 스레드를 통해 수행된다.
- 따라서, 코드 실행 스레드에는 영향을 주지 않음
-
JIT 컴파일러가 어떻게 동작하느냐에 따라 성능이 달라질 수 있다.
- 어떤 부분을 언제, 어느 수준으로 컴파일 하고 언제 caching할지??
- 컴파일 할 때에도 0(컴파일 안함)~4까지의 수준이 있다.(jvm은 프로파일링을 통해 얻은 데이터를 기반으로 이 수준을 결정)
- 이러한 요소 중에 개발자 수준 커스텀 가능한 요소가 있을까?!
-
Tuning the code cache size
- level 4로 컴파일 되어 케싱이 될 수 있는 요소가 많은 프로그램의 경우 caching되어 있는 code block이 가득 차 있으며 실행중 일 수 있다. 이러면 더는 새로운 caching 후보가 있어도 cache하지 못하는 경우가 발생한다.
- cache의 max size와 지금 사용되고 있는 size를 알 수 있으며, 지금 사용 되고 있는 size가 max에 근접하다면 cache size 증가를 고려해 볼 만 하다.
-
cache size, 컴파일이 어떻게 일어나는지 등은 application 실행 시 특정 flag 전달을 통해 확인할 수 있고 필요 시 외부 모니터링 툴과 연동할 수도 있음(그때그때 필요 시 찾아보면 되는 요소)
-
-
실행 시 여러 flag를 통해 컴파일 옵션을 줄 수 있다. => 튜닝 가능한 지점
-
java -XX:+PrintFlagsFinal : java 실행 시 지정할 수 있는 flag들을 보여준다.
-
성능에 영향을 줄 수 있는 요소(컴파일러 튜닝)
-
컴파일 프로세스를 실행하는 데 사용할 수 있는 스레드 수
- CICompilerCount flag
- jinfo -flag CICompilerCount [pid] 명령어를 통해 CICompilerCount의 기본 값을 알 수 있음
- 기본값은 3개
- [-XXLCICompilerCount=n] flag를 통해 실행되는 application의 컴파일 용 스레드 수를 지정할 수 있음
-
네이티브 컴파일의 임계값(동일한 메소드가 몇번 수행 될 때, 컴파일하는 것으로 판단 할 것인가?)
- [-XX:CompileThreshold=n] flag를 통해 실행되는 application의 임계 값을 지정 가능
- 기본값은 10000
-
- jvm은 바이트코드를 실행하는 표준
- 바이트코드는 기본적으로 인터프리팅 방식으로 실행 => 느림
- 자주 실행되는 코드 블락을 컴파일 방식으로 실행해서 성능 개선을 도모
- 튜님 요소
- 자주 실행되는 기준을(임계 값을) 튜닝
- 컴파일에 사용되는 스레드 수를 튜닝
- code cache를 위한 cache size를 튜닝
- 성능에 가장 영향을 미치는 메모리 요소는 GC
- GC를 이해하기 위해 JVM 메모리 동작 방식을 이해해야 한다.
- 또한, JVM 메모리 동작 방식은 프로그래밍을 통해 얼마든지 커스터마이징 할 수 있는 요소가 많다!
- (stack과 heap의 개념은 복습 측면이 강함)
- call by value(primitive) vs call by reference(object) 복습
- final 키워드 학습
- 참고자료: https://djkeh.github.io/articles/Why-should-final-member-variables-be-conventionally-static-in-Java-kor/
-
기본 개념: final의 의미는 최종적이란 뜻을 가지고 있습니다. final 필드는 초기값이 저장되면 최종적인 값이 되어 프로그램 실행 도중에 수정을 할 수 없습니다.
- final 필드:
- 값 초기화 후 변경 불가
- final 객체:
- 객체 변수에 final로 선언하면 그 변수에 다른 참조 값을 지정할 수 없습니다. 즉 한번 생성된 final 객체는 같은 타입으로 재생성이 불가능합니다. 객체자체는 변경이 불가능하지만 객체 내부 변수는 변경 가능합니다.
- final 클래스:
- 최종상태가 되어 더이상 상속이 불가
- final 클래스여도 필드는 Setter함수를 통하여 변경은 가능합니다.
- final 메서드:
- 메서드에 final을 사용하게되면 상속받은 클래스에서 부모의 final 메서드를 재정의 할 수 없습니다. 자신이 만든 메서드를 변경할 수 없게끔 하고싶을때 사용되며 시스템의 코어부분에서 변경을 원치 않는 메서드에 많이 구현되어 있습니다.
- 메서드 인자 값에 final 사용:
- final 필드와 마찬가지로 인자값에 final을 사용하는 경우 final 인자값의 변경이 불가능합니다.
- final 필드:
-
사용 이유:
- 코드에 의도를 명확하게 하기 위해
- final 키워드를 사용하면 자바 컴파일러가 최적화 할 수 있는 여지가 생김(final 키워드를 쓰면 변경 불가하기 때문에 인라이닝을 할 수 있다)
-
const vs final
- 둘은 정확히 같은 개념? => 답은 아니다!
-
제목 | c++ const |
java final |
---|---|---|
선언과 동시에 초기화? | 초기화 해야 함 | 초기화 안해도 됨 |
객체의 참조의 경우 참조되는 객체의 상태를 변경하는 것이 가능? | 불가 | 가능 |
객체의 참조의 경우 참조되는 객체 자체를 바꾸는 것이 가능? | 가능 | 불가능 |
- 정리
- final변수의 의미는 한번만 참조를 지정할 수 있다는 것
- 즉, final변수가 참조하고 있는 객체의 상태는 언제든 바뀔 수 있다.
- final을 쓰면 컴파일러에 의해 선택적으로 인라인 처리가 될 수 있기 때문에 성능상의 이익을 얻을 수 있다(최적화 요소)