2023-10-31 TIL(가비지 컬렉터)

SeongH·2023년 10월 31일

1.가비지 컬렉션은 시스템에서 더 이상 사용하지 않는 동적 메모리 블럭을 찾아 자동으로 해제해 주는
메모리 관리 방법 입니다.

2.가비지 컬렉터(garbage collector)는 자동 메모리 관리 시스템으로
프로그램에 의해 할당된 메모리가 더이상 인스턴스를 참조하지 않아
가비지(garbage) 상태가 되면 자동으로 메모리를 초기화해주는 프로그램입니다.


프로그램을 실항 할 떄 메모리를 관리하는 os프로그램 실해에 필요한 메모리를 요청하게 되고, 이때 메모리를
어디에 저장할지 그 주소를 할당하는데 이 주소를 offset 주소라고 부른다.
이 할당된 메모리들은 프로그램이 돌아가면 필연적으로 가비지가 발생하게 된다. 기존에 가리키고 있던 메모리를 새롭게
선언되거나 형변환이 되면서 다른 곳을 가리키게 되면서 주소를 잃어 버리게 되고 다시 찾을 수 없게 되면서 정리
되지 않은 메모리가 생겨 버리기 때문이다.

보통 게임개발을 하다보면 로비에서 인게임으로 진입하거나, 인게임에서 로비로 되돌아올 때
강제로 GC.Collect()를 호출하는 사람들이 종종 있는데 이는 좋지 못한 방법이다.
(기본적으로 0세대에 집중적 처리하는데 강제 호출하게되면 다른 객체들이 다 1세대씩 올라감)

그리고 클래스의 정적 필드(Static)으로 기록된 객체들은 명시적으로 해당 객체를 null로 할당해주어야 한다.
그렇지 않는 한 절대 해제되지 않는다.


<최적화 팁>

  1. String을 사용할 때 +연산자는 되도록 사용하지 말자
  • String은 불변객체이기 때문에 +연산자를 하면 내부적으로 새로운 객체가 생성되고
    기존 객체는 참조 없이 쌓이기만 한다. 변화가 자주 일어나는 경우 String 대신에 StringBuilder를 사용하자
  1. 웬만하면 박싱/언박싱이 일어나지 않도록 하자
  • 값 타입에서 참조 타입으로, 참조 타입에서 값 타입으로 변환하는 작업은 굉장히 느리고 좋지 못한 방법이다.
    값 타입이 참조 타입으로 변환될 때 힙 메모리에 쌓이고 값이 복사된다.
  1. 자원을 다룰 때 using 키워들 이용하자
  • using 키워드를 이용하면 괄호( {} )를 빠져나올 때 자동으로 Dispose를 해준다.
    여기서 자원이란 파일, 폰트 등과 같은 Resource를 말한다.
  1. C#에서 System.Collections.Generic.List를 쓸 필요 없는때에는 쓰지마라
  • List의 내부 구조를 열어보면 Linked List처처럼 만들어 놓은 List가 아니라 ArrayList처럼 만들어놨다.
    즉, 편하게 Add, Remove를 하지만 내부적으로는 새로운 배열에 복사해주는 형식이다.
  1. 단일 원칙을 지켜라
  • 객체지향에서 단일 원칙을 지켜야하는것은 너무나도 당연하지만 그렇지 않고 사용하는 사람들이 많다.
    간단하게 말하자면 하나의 CS파일에 하나의 Class만을 사용하고, 하나의 Class에는 Class 이름에 맞는
    단일 책임을 갖는 구조를 구현해야한다는 것이다.
    '연필'이라는 Class가 있으면 그 Class는 딱 '연필'에 대해서만 구현해야한다.
    단일 원칙만 지켜줘도 내가 모르는 곳에서 참조가 끊어지지 않고 메모리에 계속 남아돌게 되는 상황을 최대한 피할 수 있다.
  1. string 대소문자 구분 없이 비교할 때 Compare 함수를 사용해라
  • 흔히들 대소문자 구분 없이 비교하기 위해 ToUpper()나 ToLower()를 사용하곤 한다.
    string은 불변 객체이기 때문에 ToUpper()나 ToLower()를 사용하면 내부적으로 불필요한 객체 2개를 만들게 되고
    이는 곧 GC의 대상이 된다.
    string.Compare(string, string, bool) 함수를 사용하면 불필요한 객체를 만들지 않고 비교가 가능하다.
    파라미터는 (비교1, 비교2, 대소문자구분(true : 구분 안함, false : 구분함))이다

<기술면접>

  1. 가비지 컬렉터를 회피 할 수 있는 전략은 무엇이 있나요?

가비지 컬렉션으로 실제 성능 문제가 발생 했을 때 사용 할 수 있는 가비지 컬렉션 회피 전략에는
값타입 사용, 메모리 할당 최소화, GC 호출 최소화, Finzlizer 사용제한, IDisposable 활용 전략이 있습니다.

각 방법에 대해서 좀 구체적으로 설명해 주실수 있나요?

음.. 일단 당연히 구조체같이 힙 메모리 사용을 하지 않는 값타입을 사용한다면 가비지 컬렉션을 회피 할 수 있고
재사용 객체는 미리 생성하고 재사용하면서 임시객체의 생성을 줄여서 메모리 할당을 최소화 하는 방법이 있습니다.
또한 가비지 콜렉션을 직접 호출하는 것은 가급적 피하고, 가비지 컬렉션에 수거되기 전에 호출되는 특수 메서드인
FInalizer 사용을 최소화 합니다.


C#에서 GC는 메모리 관리를 자동화해주는 역할을 하지만, 때때로 GC가 동작할 때 성능 저하가 발생할 수 있다.
C#에서 가비지 컬렉션에 의한 성능 저하를 최소화하려면 다음과 같은 전략을 사용할 수 있다.

1.메모리 할당 최소화: 재사용 가능한 객체는 미리 생성하고 재사용하며, 임시 객체의 생성을 최소화한다.
(가비지 컬렉터의 역할이 메모리를 할당하고 해제하는 작업임으로)
(대표적으로 오브젝트 풀링)

  1. GC 직접 호출 최소화: GC.Collect()를 필요할 때만 호출하여 가비지 컬렉션 빈도를 줄인다.

  2. IDisposable 활용: 리소스를 직접 관리하는 클래스에서는 IDisposable 인터페이스를 구현하여 리소스를 적시에 해제한다.
    (가비지 컬렉터의 처리 작업을 줄여줌)

  3. Finalizer 사용 제한: 가비지 컬렉션이 느려지는 원인인 Finalizer 사용을 최소화한다.

  4. 값 타입 활용: 가능한 경우 참조 타입 대신 구조체와 같은 값 타입을 사용하여 가비지 컬렉션의 대상을 줄인다.

위 전략들은 성능 최적화를 위한 것이지만, 코드의 가독성이나 유지 관리성을 저해할 수 있으므로 실제 성능 문제가 발생했을 때만 적용하는 것이 좋다.

profile
개발자 꿈나무

0개의 댓글