Static EnumMap 의 초기화 위치별 메모리 영향
어느 깊은 여름밤 잠에서 깨어난 개발자가 울고 있었다.
(무슨 꿈을 꾸 .. )
코드를 짜면서 메모리 에 걱정이 들기 시작했다
(리펙토링 전) 내가 만든 코드 확인
GitHub - kureung/good-price-good-product
Contribute to kureung/good-price-good-product development by creating an account on GitHub.
github.com
모든 유저가 동일한 Enum 필드 값을 가지고 있고
Enum 클래스 내 EnumMap 초기값을 가질려면 어떻게 만들어야 할까 고민을 하는 와중
그래 그냥 생각나는 데로 다 만들어보자!
자 실험을 시작하지
[entity 생성 부분]
User usera = new User("T", Role.USER, T.init());
< 상속 받는 부분 >
User<T extends ABC> 상속
A,B,C implements ABC
1. enum static init() 만들고 entity객체 생성 시 넣어주기 (기존 방식)
private static void A() {
sequenceA.put(...);
sequenceA.put(... );
}
public static A init() {
A();
return A.ACCEPT;
}
private static final EnumMap<A, A> sequenceA =
new EnumMap<>(A.class);
2. enum EnumMap 초기화 값을 리턴 메소드로 넣어주기
-1 Map to EnumMap 캐스팅 리턴
public static B init() {
return B.ACCEPT;
}
private static EnumMap<B, B> B() {
return (EnumMap<B, B>)
Map.of(... );
}
private static final EnumMap<B, B> sequenceB = B();
-2 EnumMap 객체 생성 후 리턴
public static C init() {
return C.ACCEPT;
}
private static EnumMap<C, C> C() {
EnumMap<C, C> map = new EnumMap<>(C.class);
map.put(...);
map.put(...);
return map;
}
private static final EnumMap<C, C> sequenceC = C();
자 이제 코드들을 실행하면 어떤 결과가 나올까?
그전에 위 코드들을 조금 수정하면서 어떤 리턴 값이 나오는지 확인해보자
(A는 처음에 만들었던 코드라 패턴에 포함 x)
실험 조건은
실험하기 전 서로 객체 하나를 만들어 한 번씩 실행했다.
반복 횟수 2147483647 회(Integer.MAX_VALUE)
측정 함수: System.nanoTime(); -> ((double) nanoTime) / 1000000000
[Pattern -1]
init(){ T(); }
sequence = new EnumMap<>(T.class);
T(){//... 값 넣어주기}
B 결과 - ClassCastException -> map to EnumMap 캐스팅 에러
C 결과 - 실행시간 : 30초 , 리턴 값 null;
[Pattern -2]
sequence = new EnumMap<><T.class>;
B 결과 - 실행시간 : 0.001초 , 리턴값 null;
C 결과 - 실행시간 : 0.001초 , 리턴값 null;
패턴 2는 유일하게 이방식에서 리턴값?을 리턴해줘서 추가함
[Pattern -3]
sequence = T();
B 결과 - ClassCastException -> map to EnumMap 캐스팅 에러
C 결과 - 실행시간 : 0.001초 , 리턴값 존재함
여기서 B는 사용할 수 없는 거라 판단이 들어
A와 B를 비교해 보았다.
A 테스트 코드
public static void testA(int count) {
long time = System.currentTimeMillis();
reportPerformanceFor(" A before", time);
for (int i = 0; i < count; i++) {
User userA = new User("A", Role.USER, A.init());
userA.next();
}
reportPerformanceFor(" A after", time);
}
실행 결과 : 12.8665652초 , 메모리 10.519MB 증가
C 테스트 코드
public static void testB(int count) {
long time = System.currentTimeMillis();
reportPerformanceFor(" C before", time);
for (int i = 0; i < count; i++) {
User userC = new User("C", Role.USER, C.init());
userC.next();
}
reportPerformanceFor(" C after", time);
}
실행 결과: 0.0185339 초 , 메모리 -16.3604049683 MB 감소
시간 차이가 무려 700배 , 메모리 영역은 오히려 감소하는 기이한 형상이 일어났다.
여기서 또 출력도 3가지 패턴이 있다.
ㅋㅋㅋ
[출력문]
A 1번 호출 , C 1번 호출
----------------------------------------------------------------------------------------------------
A before (nanoTime :366446.8587579 , 4.9620513916015625 MB)
A after (nanoTime :366459.5092968 , 18.48230743408203 MB)
C before (nanoTime :366459.5094344 , 18.48230743408203 MB)
C after (nanoTime :366459.527259 , 6.1203765869140625 MB)
----------------------------------------------------------------------------------------------------
? 뭐지
[출력문]
A 1번 호출 , C 6번 호출
----------------------------------------------------------------------------------------------------
A before (nanoTime :362633.3446298 , 4.9621124267578125 MB)
A after (nanoTime :362645.9432127 , 14.482307434082031 MB)
C before (nanoTime :362645.9433499 , 14.482307434082031 MB)
C after (nanoTime :362645.955507 , 20.481971740722656 MB)
C before (nanoTime :362645.9555983 , 20.481971740722656 MB)
C after (nanoTime :362645.9666415 , 3.6124649047851562 MB)
C before (nanoTime :362645.9667442 , 3.6124649047851562 MB)
C after (nanoTime :362645.9667968 , 3.6124649047851562 MB)
C before (nanoTime :362645.9668351 , 3.6124649047851562 MB)
C after (nanoTime :362645.9669407 , 3.6124649047851562 MB)
C before (nanoTime :362645.966973 , 3.6124649047851562 MB)
C after (nanoTime :362645.9670724 , 3.6124649047851562 MB)
C before (nanoTime :362645.9671015 , 3.6124649047851562 MB)
C after (nanoTime :362645.9671953 , 3.6124649047851562 MB)
----------------------------------------------------------------------------------------------------
그래도 그렇지 메모리가 감소가 되나 어... 이게 바로 가비지 컬렉션? (할당 값 주소 재활용 같은 건가?)
[출력문]
C 4번 호출
----------------------------------------------------------------------------------------------------
C before (nanoTime :362148.9913814 , 4.9620513916015625 MB)
C After (nanoTime :362149.0033177 , 9.961990356445312 MB)
C before (nanoTime :362149.0034312 , 9.961990356445312 MB)
C After (nanoTime :362149.0118517 , 14.481971740722656 MB)
C before (nanoTime :362149.0119602 , 14.481971740722656 MB)
C After (nanoTime :362149.0120124 , 14.481971740722656 MB)
C before (nanoTime :362149.0120532 , 14.481971740722656 MB)
C After (nanoTime :362149.0121564 , 14.481971740722656 MB)
----------------------------------------------------------------------------------------------------
2번까지 실행된 후 크게 변화는 없다.
A 코드를 짤 때 서늘함이 느껴져 가지고 실험을 해봤는데
이 정도 실험 결과면 나쁘지 않다.
<테스트 코드>
GitHub - oiNeh/code-test
Contribute to oiNeh/code-test development by creating an account on GitHub.
github.com
이제 안심하고 다시 코드 짜야지