generated from Learning-Is-Vital-In-Development/study-template
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2703a67
commit dcf9d42
Showing
3 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# [1장 성능과 최적화] | ||
|
||
### 1.1 자바 성능: 잘못된 방법 | ||
|
||
- 자바 초창기에 메서드 디스패치 성능은 최악이었다. 그래서 메서드를 잘게 나누지 말고 하나의 덩치 큰 메서드로 작성하는 게 좋다고 권고하는 개발자도 존재했다. 물론 시간이 지나면서 가상 디스패치 성능은 엄청나게 좋아졌고 특히 최신 자바 가상 머신에서는 자동 인라이닝 덕분에 가상 디스패치조차 대부분의 호출부에서 사라지게 되었기에 모든 코드를 한 메서드에 넣으라는 코드는 현대 JIT 컴파일러와는 어울리지 않게 되었다. | ||
- 메서드 디스패치 : 메서드 실행 시 실제 호출할 메서드를 결정하는 프로세스 | ||
- 자바 코드가 실행되는 속도는 매우 변화무쌍하며 전적으로 코드를 실행하는 하부(겉으로 드러나지 않는 내부 구현 코드) JVM에 따라 다르다. 따라서 오래 전 작성한 자바 코드도 재컴파일 없이 최신 jvm에서 실행하면 더 빨리 작동될 수 있다. | ||
|
||
### 1.2 자바 성능 개요 | ||
|
||
- 실용성을 추구하는 자바 플랫폼의 성격은 여러 방면에서 드러난다. | ||
- 서브시스템이 그 예이다. | ||
- 개발자가 일일이 용량을 세세하게 관리하는 부담을 덜어주고, 대신 저수준으로 제어 가능한 일부 기능을 포기하자는 발상이다. | ||
- JVM 전반에 걸쳐 등장하는 관리되는 서브시스템은 그 존재 자체로 jvm 애플리케이션의 런타임 동작에 복잡도를 유발한다. | ||
|
||
### 1.3 성능은 실험과학이다. | ||
|
||
- 대부분 최신 sw 시스템이 그렇듯, 자바/JVM SW 스택 역시 아주 복잡하다. | ||
- 이렇게 복잡한 지경까지 이른 건 무어의 법칙과 그로 인한 하드웨어 용량의 전무후무한 발전 때문일 것이다. | ||
- 무어의 법칙 : 반도체 집적 회로의 성능이 24개워람다 2배로 증가한다는 법칙 | ||
|
||
### 1.4 성능 분류 | ||
|
||
- 성능 지표는 성능 분석의 어휘집이자, 튜닝 프로젝트의 목표를 정량적인 단위로 표현한 기준이다. | ||
- 실제로는 어느 한 지표를 최적화하면 다른 지표들이 약화되는 경우도 흔하다. | ||
|
||
1.4.1 처리율 | ||
|
||
- 처리율은 서브시스템이 수행 가능한 작업 비율을 나타낸 지표이다. 보통 일정 시간 동안 완료한 작업 단위 수로 표시한다. (초당 처리 가능한 트랜잭션 수) | ||
|
||
1.4.1 지연 | ||
|
||
- 하나의 트랜잭션을 처리하고 그 결과를 반대편 수도관 끝까지 바라볼 때까지 소요된 시간을 의미한다. | ||
|
||
1.4.1 용량 | ||
|
||
- 시스템이 보유한 작업 병렬성의 총량, 즉 시스템이 동시 처리 가능한 작업(트랜잭션) 단위 개수를 의미한다. | ||
|
||
1.4.1 사용률 | ||
|
||
- 성능 분석 업무 중 가장 흔한 태스크는 시스템 리소스를 효율적으로 관리하는 것이다. | ||
- 사용률은 워크로드에 따라서 리소스별로 차이가 있을 수 있다. | ||
- 예시로 계산 집약적 워크로드(그래픽 처리, 암호화)를 주면 cpu 사용률은 100%에 육박하지만 메모리 사용률은 얼마 안나온다. | ||
|
||
1.4.1 효율 | ||
|
||
- 전체 시스템의 효율은 처리율을 리소스 사용률로 나눈 값으로 측정한다. | ||
- 같은 처리율을 더 많은 리소스를 쏟아부어야 달성할 수 있다면 분명 효율이 낮은 것이다. | ||
|
||
1.4.1 확장성 | ||
|
||
- 처리율이나 시스템 용량은 처리하는 데 끌어 쓸 수 있는 리소스에 달려 있다. | ||
- 리소스 추가에 따른 처리율 변화는 시스템/애플리케이션의 확장성을 가늠하는 척도이다. | ||
|
||
1.4.1 저하 | ||
|
||
- 시스템을 덜 사용하고 있으면 측정 값이 느슨하게 변하지만, 시스템이 풀 가동된 상태면 처리율이 더는 늘어나지 않는, 즉 지연이 증가하는 양상을 띈다. | ||
- 이러한 현상을 부하 증가에 따른 저하라고 한다. | ||
|
||
1.4.1 측정값 사이의 연관 관계 | ||
|
||
- JIT 컴파일 대상이 되는 메서드는 인터프리티드 모드로 실행되어야 한다. 따라서 부하가 적을 경우 핵심 메서드가 인터프리티드 모드의 늪에서 허우적거릴 가능성도 있지만, 부하가 많아 메서드 호출 빈도가 증가하면 jit 컴파일 대상이 될 수도 있다. | ||
- 결국 같은 메서드지만 나중에 호출하는 게 처음보다 훨씬 더 빨리 실행된다. | ||
|
||
### 1.5 성능 그래프 읽기 | ||
|
||
- 부하가 증가하면서 예기치 않게 저하가 발생한 그래프의 형태를 성능 엘보라고 한다. | ||
- 그와 반대로 선형적으로 처리율이 확장되는 결과는 환경이 극단적으로 순조로울 때(서버 하나에 세션 어피니티가 필요벗는 무상태 프로토콜을 확장하는 경우)나 가능하다. | ||
- 진 암달이 발표한 암달의 법칙이 나온다. 암달에 따르면 근본적으로 확장성에는 제약이 따른다. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
# [2장 JVM 이야기] | ||
|
||
### 2.1 인터프리팅과 클래스 로딩 | ||
|
||
- JVM은 스택 기반의 해석 머신으로 물리적 CPU 하드웨어인 레지스터는 없으나, 일부 결과를 실행 스택에 보관하며, 이 스택의 맨 위에 쌓인 값들을 가져와 계산을 합니다. | ||
- 자바 프로세스가 새로 초기화되면 사슬처럼 줄지어 연결된 클래스 로더가 차례차례 작동한다. | ||
- 가장 먼저 부트스트랩 클래스가 기지캐를 켜며 자바 런타임 코어 클래스를 로드한다. | ||
- 부트스트랩 클래스로더의 주 임무는 다른 클래스 로더가 나머지 시스템에 필요한 클래스를 로드할 수 있게 최소한의 필수 클래스(java.lang.Object, Class, ClassLoader)만 로드한다. | ||
- 그 다음 확장 클래스 로더가 생긴다. | ||
- 확장 클래스 로더를 이용하면 특정한 OS나 플랫폼에 네이티브 코드를 제공하고 기본 환경을 재정의 할 수 있다. | ||
- 네이티브 코드란 OS상에서 직접 컴파일하여 바로 기계어로 실행 가능한 코드(c, c++), 반대로 JVM, 닷넷프레임워크처럼 인터프리터가 있어야 실행되는 코드를 관리되는 코드(managed code)라 한다. | ||
- 끝으로 애플리케이션 클래스 로더가 생성되고 지정된 클래스 패스에 위치한 유저 클래스를 로드한다. | ||
|
||
### 2.2 바이트 코드 실행 | ||
|
||
- 자바 소스 코드는 실행되기까지 꽤 많은 변화 과정을 거친다. | ||
- 첫 단계는 자바 컴파일러 javac를 이용해 컴파일 하는 것으로 보통 전체 빌드 프로세스의 한 부분으로 수행한다. | ||
- javac가 하는 일은 자바 소스 코드를 바이트 코드로 가득 찬 .class 파일로 바꾸는 것이다. | ||
- 바이트코드는 특정 컴퓨터 아키텍쳐에 특정하지 않은 중간 표현형이다. 그렇기에 OS에 지배를 받지 않으므로 이식성이 좋아, JVM 지원 플랫폼 어디서건 실행할 수 있다. | ||
- 컴파일러가 생성한 클래스 파일은 VM 명세서에 아주 명확히 잘 정의된 구조를 갖추고 있다. | ||
|
||
```java | ||
매직 넘버 : 0xCAFEBABE | ||
클래스 파일 포맷 버전 : 클래스 파일의 메이저/마이너 버전 | ||
상수 풀 : 클래스 상수들이 모여있는 위치 | ||
엑세스 플래그 : 추상 클래스, 정적 클래스 등 클래스 종류 표시 | ||
this 클래스 : 현재 클래스 명 | ||
수퍼클래스 : 수퍼 클래스 명 | ||
인터페이스 : 클래스가 구현한 모든 인터페이스 | ||
필드 : 클래스에 들어 있는 모든 필드 | ||
메서드 : 클래스에 들어 있는 모든 메서드 | ||
속성 : 클래스가 지닌 모든 속성 | ||
``` | ||
|
||
- 메이저/마이너 버전은 클래스로더의 호환성 보장을 위해 검사하고 호환되지 않는 버전의 클래스 파일을 만나면 런타임에 예외가 발생한다. 런타임 버전이 컴파일된 클래스 파일 버전보다 낮으면 안되기 때문이다. | ||
- 엑세스 플래그는 클래스에 적용한 수정자를 결정한다. 플래스 첫 부분은 일반 프로퍼티로 public 클래스 인지, final 클래스인지를 나타낸다. 플래그의 끝부분은 클래스 파일이 소스 코드에 없는 합성 클래스인지 어노테이션, enum인지를 나타낸다. | ||
|
||
|
||
### 2.3 핫스팟 입문 | ||
|
||
- 자바의 중요한 부분인 핫스팟 가상 머신은 성능 관점에서 자바에 가장 큰 변화를 가져왔다. | ||
|
||
<img width="412" alt="image" src="https://github.com/Learning-Is-Vital-In-Development/23-19-clean-code/assets/56379649/b6849162-18cf-44da-a45b-9528b2f7e90e"> | ||
|
||
- 자바는 핫스팟을 통해서 프로그램의 런타임 동작을 분석하고 성능에 가장 유리한 방향으로 영리한 최적화를 적용하는 가상 머신입니다. 핫스팟 VM의 목표는 개발자가 억지로 VM 틀에 맞게 프로그램을 욱여넣는 대신, 자연스럽게 자바 코드를 작성하고 바람직한 설계 원리를 따르게 한다. | ||
|
||
### 2.3.1 JIT 컴파일이란? | ||
|
||
- 자바 프로그램은 바이트코드 인터프리터가 가상화한 스택 머신에서 명령어를 실행하며 시작된다. | ||
- 이를 위해 핫스팟은 프로그램 단위를 인터프리티드 바이트코드에서 네이티브 코드로 컴파일한다. 이것이 바로 JIT(Just In Time) 컴파일이라고 알려진 기술이다. | ||
- JIT 방식으로 컴파일하면 생기는 장점 | ||
- 무엇보다 컴파일러가 해석 단계에서 수집한 추적 정보를 근거로 최적화를 결정한다는게 가장 큰 장점이다. | ||
- 상황별로 수집한 다양한 정보를 토대로 핫스팟이 더 올바른 방향으로 최적화 할 수 있다. | ||
|
||
- 자바처럼 프로필 기반 최적화(PGO, Profile-guided optimization)을 응용하는 환경에서 대부분의 AOT 컴파일러(Ahead-Of Time Compile) 플랫폼에서 불가능한 방식으로 런타임 정보를 활용할 여지가 있으며, 동적 인라이닝(dynamic inlining) 또는 가상 호출(virtual call) 등으로 성능을 개선할 수 있습니다. 핫스팟 VM은 시동시 CPU 타입을 정확하게 감지해 가능하면 특정 프로세서의 기능에 맞게 최적화를 적용할 수 있습니다. | ||
|
||
### 2.4 JVM 메모리 관리 | ||
|
||
- C, C++ 는 개발자가 메모리 할당/해제 작업을 수행해야합니다. 이에 따라 확정적인 성능과 리소스 관련 작업을 결부시킬 수 있는 장점이 있으나 막대한 책임이 수반됩니다. | ||
- 자바는 `가비지 수집(Garbage Collection)` 이라는 프로세스를 이용해 힙 메모리를 자동 관리하는 방식으로 해결합니다. 즉, 가비지 수집은 JVM이 더 많은 메모리를 할당해야할 때 불필요한 메모리를 회수하거나 재사용하는 불확정적인 프로세스입니다. | ||
|
||
### 2.5 스레딩과 자바 메모리 모델(JMM) | ||
|
||
<aside> | ||
💡 자바는 멀티스레드 프로그래밍을 기본 지원합니다. 그렇기에 자바 프로그램이 작동하는 방식이 복잡하고 성능 분석이 어렵습니다. 주로 JVM 구현체에서 자바 애플리케이션 스레드는 각각 정확히 하나의 전용 OS 스레드에 대응됩니다. | ||
|
||
</aside> | ||
|
||
자바 멀티스레드 방식은 세 가지 설계 원칙에 기반합니다. | ||
|
||
- 자바 프로세스의 모든 스레드는 가비지가 수집되는 하나의 공용 힙을 가집니다. | ||
- 한 스레드가 생성한 객체는 그 객체를 참조하는 다른 스레드가 액세스할 수 있습니다. | ||
- 기본적으로 객체는 변경가능합니다. 즉, 객체 필드에 할당된 값은 프로그래머가 애써 final 키워드로 불변을 표시하지 않는 한 바뀔 수 있습니다. | ||
|
||
### 2.6 JVM 구현체 종류 | ||
|
||
- 오라클이 제작한 **핫스팟** 이외에도 제각기 다른 방법으로 구현한 자바 구현체가 많다. | ||
|
||
- **OpenJDK** | ||
- 오라클이 주관하며, **자바 기준 구현체**(다른 개발자가 참조할 수 있는 샘플 프로그램)를 제공하는 특별한 오픈소스 프로젝트다. | ||
- **GPL 라이선스**(소프트웨어의 실행, 연구, 공유, 수정의 자유를 사용자에게 보장)를 갖고 있다. | ||
- **오라클 자바(Oracle)** | ||
- OpenJDK 기반이지만, 오라클 상용 라이선스로 재라이선스를 받았다. | ||
- 오라클 자바에 변경된 내용은 거의 전부 OpenJDK 공개 저장소에 커밋된다. | ||
- **줄루(Zulu)** | ||
- 아줄 시스템이 제작한, 자바 풀 인증(GPL)을 받은 OpenJDK 구현체다. | ||
- **아이스티(IcedTea)** | ||
- 래드햇이 제작한, 자바 풀 인증을 받은 OpenJDK 구현체다. | ||
- **징(Zing)** | ||
- 아줄 시스템이 제작한, 자바 풀 인증을 받은 고성능 상용 JVM이다. | ||
- **J9** | ||
- IBM이 제작했고, 지금은 이클립스 OMR 프로젝트 기반으로 제작되며, IBM 상용 제품의 근간을 이루고 있다. | ||
- **애비안(Avian)** | ||
- 자바 풀 인증을 받은 구현체가 아니라, 제품으로 쓰기에 완벽한 솔루션은 아니다. | ||
- 그러나 JVM의 세부 작동 원리가 궁금한 개발자에게 훌륭한 학습 도구 역할을 한다. | ||
- **안드로이드(Android)** | ||
- 이 책은 핫스팟에 관한 내용이 대부분이고, 이는 오라클 자바, 아줄 줄루, 래드햇 아이스티 등 OpenJDK에서 파생된 JVM에 똑같이 적용된다. 다만, 안드로이드 기술 스택은 다소 거리가 있으므로 책에서 안드로이드는 고려 대상에서 제외한다. | ||
|
||
|
||
### 2.6.1 JVM 라이선스 | ||
|
||
- **모니터링 :** JVM은 실행 중인 애플리케이션을 인스트루먼테이션(오류 진단이나 성능 개선을 위해 애플리케이션에 특정한 코드를 끼워 넣는 것), 모니터링 등 다양한 기술을 제공한다. | ||
|
||
- **자바 관리 확장(JMX)** | ||
- JVM과 그 위에서 동작하는 애플리케이션을 제어하고 모니터링하는 강력한 범용 툴이다. | ||
- **자바 에이전트** | ||
- 자바 언어로 작성된 툴 컴포넌트로, java.lang.instrument 인터페이스로 바이트코드를 조작한다. | ||
- **JVM 툴 인터페이스(JVMTI)** | ||
- JVM의 네이티브 인터페이스로, 네이티브 컴파일 언어로 작성해야 한다. | ||
- JVM 이벤트를 모니터링하며 알림을 받을 수 있도록 하는 통신 인터페이스다. | ||
- 네이티브이기 때문에 아무래도 자바 에이전트를 사용하는 것이 났다. | ||
- **서비서빌리티 에이전트(SA)>** | ||
- 자바 객체, 핫스팟 자료 구조 모두 표출 가능한 API와 툴을 모아놓은 것. | ||
- JVM 진단, 모니터링 등의 작업을 위해 사용되는 도구. | ||
|
||
- visualVM | ||
- 넷빈즈 플랫폼 기반의 시각화 툴 |
Oops, something went wrong.