취업준비를 하면서 내가 제대로 보지 못했던 자바의 '진짜 모습'을 보고자 노력하고 있다. 그래서 첫번째로, GC에대해서 살펴 볼 것이다.

자바를 공부하면서 흥미로웠던 것은 GC였다. 하지만, 학교내의 프로젝트에서는 GC를 보기 힘들다. 이번기회를 통해 GC를 튜닝하는 방법까지 공부하면서 구현할 예정이다.


가비지 컬렉션(GC)

말그대로 '쓰레기 수집가'이다. 하지만 그냥 수집가가 아니다, GC는 프로그램의 성능과도 연결될 수 있다. 그만큼 GC는 자바의 필수적인 요소이다.


Stop-the-world



이 용어의 뜻은 나는 이렇게 이해했다. 모두 멈추고 어둠의 지배자인 GC의 활동(?).. 이해하기 위해서 이렇게 생각했었다. GC를 진행하는 쓰레드를 제외하고 모든 쓰레드가 멈춘후, GC가 작업을 완료하면 중단한 작업들을 다시 시작한다, 라는 용어이다. 생각해보면 멈춘시간이 짧을 수록 좋은 프로그램이 아닐까 생각든다. 그렇기때문에 GC튜닝과정에서는 이 시간을 줄이는 것이다.


자바는 명시적으로 프로그램을 지정하여 해제 하지 않는다


그렇다. 그러지 않는다, 명시적으로 해제하지 않고 가비지 컬렉터가 필요없는 객체들을 찾아 치우는 작업을 한다. 하고 싶다면 null로 지정하거나, system.gc()를 호출하는데 후자는 절대로 하면 안된다.(성능에 무리)



weak generational hypothesis

가비지 컬렉터는 이 가설을 바탕으로 만들어 졌는데 ,

  • 대부분의 객체는 금방 접근 불가능상태가 된다.
  • 오래된 객체에서 젊은 객체로의 참조는 아주 적다.

이 가설을 전제조건으로 가비지 콜렉터가 만들어졌다.

2개의 공간 Young and Old

스크린샷 2017-11-01 오후 3.54.00

위 가설의 장점을 살리기 위해 2개의 물리적 공간으로 나뉘는데 ,


YoungOld이다.



Young 영역

  • 새롭게 생성한 객체들이 이곳에 저장된다.
  • 객체가 접근 불가능한 상태이므로 생성과 소멸의 과정을 거친다.
  • 소멸의 과정에서 Minor GC가 발생한다.

Order 영역

  • 접근불가 구역이 아니다. 그래서 Young영역에서 살아남은 객체가 이곳으로 복사된다.
  • 위의 사항에 대한 특징상 Young영역보다 크기가 커야된다.
  • Young영역보다는 GC횟수가 비교적 적다.
  • 소멸의 과정에서 Major GC(Full GC)가 발생한다.
추가적으로 perm영역이 있다. java 8에서는 사라졌다고 들었다, 아니 대체되었다는 표현이 정확하겠다. 이 영역에서는 객체or억류된 문자열이 저장된다. Old영역에서 살아남은 객체가 영원히 남아있는 것은 아니다. GC가 발생할 수 있고 Major GC라한다.


Old영역에 있는 객체가 Young 영역의 객체를 참조하는 경우의 처리

카드 테이블을 이용한다. 카드테이블의 크기는 512Byte이다. Old영역에 있는 객체가 Young영역의 객체를 참조할때마다 카드테이블에 표시를 해준다. 따라서 Young의 GC가 실행되면 Old영역이 아닌 카드테이블을 이용하여 처리한다. write barrier를 사용하며 관리하고 minor gc빠르게 해준다. 약간의 오버헤드의 위험이 있지만, 전반적인 GC시간은 줄어든다.



Young generation


제일 먼재 객체가 생성되어 저장되는 곳이다 , 3개의 영역으로 나뉘는데


Eden 과 두개의 Survivor이다.


  • 새로 생성된 객체들은 Eden에 저장된다.
  • Eden에서 GC가 발생하고, 살아남은 객체들은 Survivor로 이동한다.
  • 또 다시 Eden에서 GC가 발생할때, 이미 객체를 가지고 있는 Suvivor로 이동한다.
  • Survivor이 가득차게 되면 그중에 살아남은 객체들을 다른 Survivor로 이동시킨다.
  • 그렇게 되면 기존에 Eden에서 살아남은 객체들이 있던 Survivor은 Empty상태가 된다.
  • 과정을 반복하면서 최종적으로 살아남은 객체들은 Old generation 으로 이동한다.

두 개의 Survivor중 반드시 하나는 비어있어야한다. 둘다 아무것도 없거나, 둘다 있으면 시스템은 정상이 아니다.


빠른 메모리 할당을 위한 기술이 있다.


bump-the-pointer

Eden의 가장 높은(top)부분에는 마지막 객체가 존재한다. bump-the-pointer는 새로운 객체가 생성되면

이 객체가 Eden에 들어가도 되는지 검사를 한다. 그리고 검사를 통과한 객체는 Top위치로 가게 된다.

이러한 이유로 객체를 생성할때 마지막에 추가된 객체만 점검하면된다. 때문에 메모리 할당이 매우 빠르게 된다.


하지만..!


멀티 쓰레드 상황에서는 Thread-safe를 위해 여러 스레드에서 Eden영역을 사용할때에는 롹이 발생한다.

그렇게 되면 성능은 떨어질 가능성이 있다. (..lock contention)


Thread-Local-Allocation-Buffers(TLABs)

각 스레드마다 Eden영역의 작은 덩어리를 나눠준다. 그렇기 때문에 각 스레드는 자신의 TLABs에만 접근하면 된다.

이렇게 롹이 발생할 가능성을 없앨 수 있다.



Old 영역의 GC


Old Generation에 객체가 가득차면 실행하게된다.


Old영역에서 사용하는 알고리즘이다.

Mark : Old영역에 살아있는 객체를 식별한다.

Sweep : 힙의 앞부분부터 확인하여 살아있는것만 남긴다.

Compaction : 앞부분부터 채워서 객체가 존재하는 구역과 존재하지 않는 구역을 나눔

Serial GC

  • 단일스레드
  • 적은 메모리와 cpu 코어 개수가 적을때 사용
  • 잘안쓰임
  • -XX:+UseSerialGC 로 활성화




Parallel GC(=Throughput GC)

  • 쓰렏가 여러개 존재 그래서 Serial GC보다 빠르다.
  • 메모리가 충분할때 사용해야한다.
  • -XX:+UseParallelGC 로 활성화




#Parallel Old GC

  • Parallel GC와 비교하여 Old영역의 GC만 다름

  • mark-summary-Compaction 단계를 거침

  • 별도로 살아있는 객체를 식별한다는 점에서 더 복잡해짐

  • -XX:+UseParallelOldGc 로 활성화




CMS GC(=Low latency GC)

  • 초기 Intial Mask 에서는 가장 가까운 객체를 먼저 찾는다.
  • Concurrent Mask 단계에서는 확인한 객체가 참조 하고 있는 객체들을 따라가면서 확인을 한다.
  • 다른 스레드가 실행되고 있어도 동시 진행이 가능하다.
  • Remark에서는 Concurrent Mask 단계에서 새로 추가되거나 참조가 끊긴 객체를 확인한다.
  • Councurrent sweep에서는 쓰레기(객체)들을 정리한다.
  • Stop-the-world가 매우 짧다는 특징을 가지고 있다.
  • 모든 어플리케이션이 빠른 응답속도를 요구할때 사용된다.
  • 메모리와 CPU사용량이 많이 요구된다.
  • Compaction단계를 제공하지 않는다.
  • 위의 단점으로 인하여 조각난 메모리, 즉 메모리 파편화가 심해진다면 Serial GC와 다를 것이 없다.
  • Compaction작업이 수행에대한 정보가 필요하다.
  • -XX:+UseConcMarkSweepGC 로 활성화




G1 GC

  • CMS GC의 단점을 극복하기 위해
  • 여러 영역(Region)들을 나누어서 활용한다.
  • Young 영역은 멀티쓰레드로 해결
  • Old영역은 백그라운드에 있는 쓰레드가 정리
  • 각 영역에 객체들을 할당하고 GC를 실행한다.
  • 꽉차게 되면 다른영역에 객체를 할당하고 GC를 실행
  • 사용 중인 객체만 다른 영역에 복사 ( 참조 없는 것들은 BYE)
  • CMS에서 발생하는 조각난 메모리의 증가 ( 메모리 파편화)에 대한 문제를 해결 할 수 있다.

'개발이야기 > Java' 카테고리의 다른 글

Linked List (단순 연결 리스트) 소스  (0) 2017.11.10
Java9 발표에 대한 요약  (0) 2017.11.06


벌써 3년이 되어가는 사진이다. 


폴란드에서 -> 영국 -> 아일랜드 넘어가는 비행기에서 틈틈히 원스를 보고,  큰 기대를 가지고 아일랜드를 갔다. 


기대와 달리, 인터넷에 있던 한인 민박은 없어져 있었다. 

휴업을 한거지, 폐업을 한건지..결국 그 날 비슷한 숙소이름으로 해 


6시간정도를 걸어다녔다..


다음날 일어나자마자, 더블린을 돌아다녔는데, 

아! 그날 오전에도 실수를 했다. 더블린도.. 주말에는 버스 배차간격이 길다..두배였나..ㅜㅜ 엄청 기다렸다 버스..



이 사진을 보고 블로깅 하고자 생각했다. 

나도 몇년동안 버스킹을 했지만, 이때는 버스킹에 대한 경험이 없었다. 

보면서 원스만큼의 감동은 아니더라도, 모여있는 사람들과 공감할 수 있었다. 

더군다나 크리스마스라, 다같이 때창하고 그랬다. 정말 좋은 추억이었다. 


유럽에서 살면서 좋았던 것은 음악하나로 정말 하나가 될 수 있다는 것을 경험한 것이다.


아일랜드는 여기뿐만 아니라, 거리 곳곳에서 버스킹을 한다.  

특히 템블바가 있는 골목에서는 쭈루루룩 있었다. 

그리고 그것을 즐기는 사람들 또한 많았다. 

한국에서와 달리 버스킹에 대한 시스템이 자유로운게 부러웠다. 


<비긴어스>가 그러했듯, 날씨가 안좋으면 보기 힘들다, 나는 운이 좋게도 아일랜드에 있던날들 동안 

날씨가 무척 좋았다. 

또한 축제 분위기라 너무 좋았다. 


아일랜드, 더블린에 갔다면 많은 그래프톤 거리를 포함하여 많은 거리 골목골목 다니길 추천한다.

날씨가 좋다면, 잠을 덜 자더라도 나가라! 


다른 사진들과 함께 다른 것들도 같이 올려 설명하고 싶지만.. 

지금 이력서 마감 관계로.. ㅜ ㅜ 


* 아일랜드 가기전에 아일랜드 역사를 알고 가면 좋다.  

아일랜드는 우리와 비슷한 아픈 상처를 지니고 있다. 그래서 영국과 비슷하지만 다른 느낌을 받을 수 있다. 


* 추천영화 : 보리밭이 흔드는 바람

2017.11.02 ** 목요일 ** Solution - 1238(파티)
백준 1238 파티

풀이방법: 다익스트라

특정한 장소에 최단시간으로 모두 갔다오고, 그 중 가장 오랜시간 걸린 사람을 찾는 문제이다.

풀이방식

문제를 읽고 두 가지 풀이가 생각났다.

1.플로이드
2.다익스트라

처음에는 플로이드로 하면 금방할 것 같아 했는데 , 뭔가 오류가난다. 시간이 초과되고 그러는것 같다.

그래서 플로이드의 조건을 바꾸느냐? 아니면 다익스트라로 다시푸느냐...

다시하는게 빠를것 같아 다익스트라로 풀었다.

그냥 다익스타로 하기전에 고민을 좀 더 해봤다.

다시 생각해보면 우리는 X의 지점만 왓다리 갓다리 하면된다.

문제에서 보면 1 -> 2 가 4인데 이것을 뒤집으면 2 -> 1이된다. 보기에는 다르겠지만 의미는 같다.

따라서 두 가지의 방식을 사용하면된다.

일반적인 거리배열을 이용한것과 위처럼 뒤집은 배열을 사용한것 이 결과 두개를 더하면된다.

또한 우리는 기준이 되는 점을 알고 있기 때문에 기준점을 활용한다.

dist[i] = map{x}{i} + d[x]를 점화식으로 세운다.

나머지는 다른 다익스트라와 같다. (우선순위 큐쓰고,, 넣고 와일문 돌리고등.)

함수의 매개변수를 (int x, int{}{}map, int{} dist) 이렇게 받아주고 계산하면된다.(쓴 이유는 아래에 있다)

그리고 우리는 함수를 2번 호출한다. 왜냐하면 우리는 2개씩 배열을 만들것이기 떄문!

안뒤집은 배열, 뒤집은 배열, 안뒤집은 거리, 뒤집은 거리 이렇게 4개를 활용한ㄷ.

뒤집은 것을 넣게되면 아까 말한것처럼 1->2 를 2->1로 계산할 수 있다.

출력할때는

제일 큰 dist[i] + redist[i] 하면된다. 모두 x까지 왕복한 거리들이기 떄문이다.
코드 전체 보기

: 풀다가 잣다.. 어려웡.

'알고리즘(추가예정) > 다익스트라' 카테고리의 다른 글

백준 2665 미로만들기  (0) 2017.10.30

+ Recent posts