[Effective C# Item 11] .NET 리소스 관리에 대한 이해

[Effective C# Item 11] .NET 리소스 관리에 대한 이해

참조

소개

  • .NET 의 가비지 콜렉터의 동작 방식을 잘 알아야 하고, 비관리 리소스를 어떻게 다룰지에 대해서도 정확히 이해해야 합니다.

가비지 콜렉터

  • 가비지 콜렉터는 관리되는 메모리를 관장하며 네이티브 환경과는 다르게 메모리 누수, 댕글링 포인터, 초기화 되지 않는 포인터, 다른 메모리 관리 문제를 개발자들이 직접 다루지 않도록 자동화 해줍니다.
  • 가비지 콜렉터가 메모리 전반적으로 관리해주기 때문에 개발자는 응용 프로그램의 구조를 단순하게 유지할 수 있습니다.
  • 가비지 콜렉터의 마크/콤팩트(Mark/Compact) 알고리즘은 여러 객체 사이의 연관 관계를 효율적으로 파악하여 더 이상 사용되지 않는 객체를 자동으로 제거합니다.
  • 가비지 콜렉터가 수행되면 관리 힙(Heap) 에 대하여 콤팩트(Compact) 작업을 수행합니다.

콤팩트(Compact) 작업이란, 사용중인 객체들을 한쪽으로 차곡차족 옮겨서 조각난 비어있는 메모리를 단일의 큰 메모리 공간으로 만드는 과정을 말합니다.

1  콤팩트

비관리 리소스

  • 가비지 콜렉터와는 별도로 비관리 리소스는 여전히 개발자가 직접 관리를 해주어야 합니다.
  • .NET 프레임워크는 비관리 리소스의 생명주기에 대해서도 개발자가 쉽게 관리할 수 있도록 finalizerIDisposable 인터페이스라는 두 가지 메커니즘을 제공합니다.
  • finalizer 는 비관리 리소스에 대한 해제 작업이 반드시 수행되도록 하는 방어적인 메커니즘입니다.
  • finalizer 는 단점이 많기 때문에 이보다는 IDisposable 인터페이스를 통해서 적시에 비관리 리소스를 해제 시켜주는 것이 좋습니다.

finalizer 단점

  • finalizer를 사용하면 성능이 나빠집니다.
  • finalizer를 포함하고 있는 객체를 사용하면 가비지 콜렉터 과정이 더 길어지고 finalizer를 포함하고 있는 객체를 가비지로 판단한 경우에 이후에 finzlizer를 호출해야 하기 때문에 객체가 점유하고 있는 메모리 공간을 해제하지 못합니다.
  • 문제는 이 호출되는 시기를 아무도 알 수 없습니다.
  • 따라서, finalizer가 필요한 구조를 회피하고 finalizer가 필요하더라도 부정적인 영향을 최소화하는 방법을 생각해야 합니다. (향후 뒤의 단원에서 다룰 예정입니다.)

가비지 콜럭테 세대(generation)

  • .NET의 가비지 콜렉터는 가비지 수집 과정을 최적화하기 위해 세대(generation) 개념을 사용합니다.
  • 세대(generation) 라는 개념은 가비지가 될 확률이 높은 객체를 더 빠르게 찾아낼 수 있도록 도와줍니다.
  • 가비지 콜렉터의 객체 세대는 다음과 같이 동작합니다.
    1. 우선 가비지 콜렉터가 수행된 이후 임의의 객체가 생성됐다고 가정합니다.
    2. 이 객체를 0세대 객체라고 합니다.
    3. 여기서 가비지 콜렉터가 동작됐다고 가정합니다.
    4. 만약 기존에 생성한 객체가 여전히 쓰인다면 이 객체를 1세대 객체라고 합니다.
    5. 그리고 두 번 이상 가비지 콜렉터가 수행 되었음에도 살아남은 객체가 있다면 그 객체를 2세대 객체라고 합니다.
    6. 대체로 0 세대 객체는 가장 최근에 생성된 객체이고 1세대, 2새대 객체는 멤버 변수나 전역 변수일 것입니다.

0세대 가비지 컬렉션 동작 원리

2  0세대 가비지 컬력센 동작 원리

1,2 세대 가비지 컬렉션 동작 원리

3  1,2 세대 가지비 컬력션 동작 원리

세대에 따른 가비지 콜렉터 동작 방식

  • 가비지 콜렉터는 1세대와 2세대 객체에 대해서는 제한적으로 가비지 콜렉터를 수행합니다.
  • 가비지 콜렉터가 수행되면 우선 0세대 객체에 대해서만 수행되고 대략 10번에 한 번 꼴로 추가적으로 1세대 객체에 대해서 가비지 컬렉션이 수행되고, 약 100번의 한 번 뽈로 2세대 객체를 포함한 모든 세대의 객체를 대상으로 가비지 컬렉션을 수행합니다.

정리

  • 관리 환경에서는 가비지 수집기가 메모리 관리를 전반적으로 담당하기 때문에 메모리 누수나 그 외의 메모리 문제에 대해서는 개발자가 더 이상 신경 쓰지 않아도 됩니다.
  • 하지만 메모리가 아닌 다른 시스템 리소스의 경우, 리소스 정리 작업을 손수 해야 하기 때문에 finalizer 가 반드시 필요하다고 생각할 수 있습니다.
  • finalizer는 응용프로그램의 성능에 심각한 영향을 미치므로 IDisposable 인터페이스를 구현하여 가비지 수집 과정이 지연되는 것을 방지해야 합니다.
728x90

이 글을 공유하기

댓글

Designed by JB FACTORY