[ODOP:03]Final 키워드
Java 에서 final 의 최적화에 관련된 내용 입니다 개인적으로 봤을 때 떠올리기 위한 내용으로, 주변 지인들의 핍박과 압박속에 힘약한 주인장은 눈물을 머금고 공유 합니다. (주의. 워딩이 정제되지 않았을 수 있습니다)
final 키워드를 각 위치에 사용할 경우의 동작을 설명하시오.
클래스에 사용 할 경우?
다른 클래스에 상속 안됨
변수에 사용 할 경우?
- 참조변수 인 경우? → 참조된 메모리 주소 고정
- primitive 인 경우? → 값 변경 불가
메서드에 사용 할 경우?
- 오버라이딩 불가
final 키워드를 사용하면 성능 향상이 될 수 있는데, 어떤게 있음?
인라인화(Inlining) 가 무엇?
하위 클래스에서 오버라이딩 될 수 없으므로, 컴파일러가 컴파일 시점에 해당 메서드의 실제 구현 코드로 대체 할 수 있음. 그럼 아래 이점이 생김
메서드 호출의 오버헤드 감소
, 실행 시간 단축
상수 폴딩(Constant Folding) 이 무엇?
final 변수는 한 번 초기화 된 후에 값을 변경할 수 없음.
이로인해 컴파일러는 변수가 참조되는 곳에 해당 값 자체를 대체하여 상수 폴딩을 수행 할 수 있음.
이건 최적화 기법중 하나임.
상수 표현식을 컴파일 시간에 미리 계산해서 실행 시간을 단축 시킬 수 있음.
```java
final int a = 5;
int b = a + 10;
```
여기에 상수 폴딩을 적용하면
```java
final int a = 5;
int b = 15;
```
이렇게 됨
메서드 호출, 반복문, 조건문 등에서 사용될 때 특히 유용함
메모리 접근 최적화 (Memory Access Optimization) 는 무엇?
final 변수는 참조되는 메모리 주소가 변경되지 않는것을 보장함.
이를 통해 컴파일러가 변수에 대한 메모리 접근을 간소화 하고 효율적인 레지스터 할당의 최적화를 수행 할 수 있음.
메모리 접근 최적화는 여러가지로 나누어 적용 되는데, 아래의 것들이 있음
- 데이터 정렬 (Data Alignment)
데이터는 정렬 요구사항을 가질 수 있음.
메모리에서 데이터가 위치하는 방식을 조정해서 CPU 캐시 라인을 효율적으로 사용하고 메모리 엑세스 시간을 단축시킴 - 데이터 로컬리티 (Data Locality)
데이터를 연속된 메모리 위치에 저장해서 CPU 캐시의 지역성을 활용하는 것
연속된 메모리 접근은 캐시 블록을 미리 로드해서 데이터 액세스 지역성을 향상시킴
반복문 처럼 데이터를 일정한 패턴으로 액세스 하는 것이 좋은 데이터 로컬리티를 가지는 경우임. - 메모리 쓰기 버퍼링 (Memory Write Buffering)
CPU 쓰기 명령을 임시로 저장하는 메모리 버퍼를 사용해서 성능을 향상 시키는 것
이로인해 CPU 는 쓰기 액세스를 더 효율적으로 수행, 메모리 액세스 지연을 감소시킴 - 레지스터 할당 (Register Allocation)
메모리 접근 대신 레지스터를 사용하여 데이터를 저장하고 처리하는 것
컴파일러는 레지스터 할당 최적화를 통해 변수를 레지스터에 할당, 메모리 액세스를 최소화 하고 성능을 향상시킴. - 캐시 지역성 (Cache Locality)
캐시를 사용하여 메모리 액세스 시간을 줄이고 데이터의 접근 패턴을 최적화 함.
데이터를 캐시에 미리 로드하거나 캐시 라인을 최대한 활용하는 방법을 사용 - 메모리 접근 패턴 최적화
특정 알고리즘이나 애플리케이션에서 특정한 메모리 접근 패턴이 나타나는 경우, 해당 패턴에 맞게 데이터 구조를 조정하거나 액세스 방식을 최적화 함
예를 들자면 행렬 연산에서 데이터를 블록 단위로 액세스 해서 데이터 로컬리티를 향상시킴
가비지 컬렉션 최적화 (Garbage Collection Optimization) 는 무엇?
final 변수는 참조되는 메모리 주소가 변경되지 않는것을 보장함.
가비지 컬렉션 과정에서 대상 객체를 추적하거나 복사하지 않아도 되므로 GC 의 효율성을 높일 수 있음.