2019년 11월 15일 금요일

c# - 가비지컬렉터(GarbageCollector)사용시 주의해야 할 점

C# __6.0 가비지컬렉터(GarbageCollector)사용시 주의해야 할 점


이전 내용에서 가비지 컬렉션에 대해 알아보았으니, 이번에는 비지 컬렉터의 성능을 저하시키지 않기 위해 객체를 생성함에 있어서 조심해야할 부분 살펴보겠습니다.

첫번째로 객체를 너무 많이 할당하지 말아야 합니다. 
가장 기본적인 지침인데요, CLR 객체 할당 속도가 빠르긴 하지만 너무 많은 수의 객체는 관리되는 힙의  세대에 메모리 포화를 초래할  있고이는 빈번한 가비지 컬렉션을 부르는 결과를 낳습니다객체 할당 코드를 작성할   필요한 객체인지와 필요 이상으로 많은 객체를 생성하는 코드가 아닌지의 여부를 고려해야합니다.


두번째는 너무  객체 할당을 피해야 합니다. 
CLR 보통 크기의 객체를 할당하는 힙과는 별도로 85KB 이상의  객체를 할당하기 위한 '대형 객체 (LOH:Large Object Heap)' 따로 유지합니다. 우리가 평소에 사용하는 힙은 대형 객체 힙에 대비되는 개념으로 소형 객체 이라고 부르기도 합니다.

커다란 객체를 소형 객체 힙에 할당한다면 0세대가 빠르게 차오르게 되므로 가비지 컬렉션을  자주 촉발하게 되고이는 어플리케이션의 성능 저하를 불러오게 됩니다그래서 대형 객체 힙을 별도로 유지함으로  성능 향상의 효과를 내고 있습니다만단점도 있겠지요.

우선 대형 객체 힙은 동작 방식이 소형 객체 힙과 다릅니다대형 객체 힙은 객체의 크기를 계산한  그만한 여유 공간이 있는지 힙을 탐색하여 할당합니다. GC 수행한  소형 객체 힙은 해제된 메모리 공간에 인접 객체들을 끌어당겨 차곡차곡 정리하지만대형 객체 힙은 해제된 공간을 그대로 둔답니다매우  메모리를 복사하는 비용이 너무 비싸기 때문이지요.
 공간은 나중에 다른 객체들에게 할당 되겠지만메모리를 0바이트의 낭비도 없이 사용하는 소형객체 힙과는 달리  공간을 군데군데 낭비하게 됩니다.

그리고 또하나 CLR 대형 객체 힙을 2세대 힙으로 간주하기 때문에 대형 객체 힙에 있는 쓰레기 객체가 수거되려면 2세대에 대한 가비지 컬렉션이 수행되어야 합니다2세대 가비지 컬렉션은  세대에 대한 가비지 컬렉션을 유발하기 때문에 수거되는 메모리의 양이  수록 어플리케이션이 정지되는 경우가 발생하게 됩니다그래서 너무  객체를 할당하는 코드는 조심스럽게 고려해보아야 한답니다.


세번째는 너무 복잡한 참조 관계는 자제해야 합니다
이러한 지침은 성능 뿐아니라 가독성을 위해서라도 주의하셔야합니다참조 관계가 많은 객체는 가비지 컬렉션 후에 살아남았을 때가 문제입니다가비지 컬렉션에서 살아남았을 경우 다음 세대로 옮기기 위해 메모리 복사를 수행하는데  참조관계가 복잡한 객체의 경우에는 단순히 메모리를 복사하는데서 끝나지 않습니다객체를 구성하고 있는  필드 객체 간의 참조 관계를 일일이 조사해서 참조하고 있는 메모리 주소를 전부 수정한답니다 클래스 구조가 간단했다면 메모리 복사만으로도 끝났을 일을 탐색과 수정까지 거치게 되는것이죠.


네번째는 루트를 너무 많이 만들지 말아야 합니다. 
가비지 컬렉터는 루트 목록을 순회하면서 쓰레기를 찾아냅니다루트 목록이 작아진다면 그만큼 가비지 컬렉터가 검사를 수행하는 횟수가 줄어들므로  빨리 가비지 컬렉션을 끝낼  있습니다따라서 루트를 가급적 많이 많들지 않는 것이 성능에 유리하겠지요 내용은 필요 이상으로 객체를 만들지 말라는 기본적인 지침입니다.

댓글 없음:

댓글 쓰기