가비지 수집 기본 사항Fundamentals of garbage collection

CLR(공용 언어 런타임)에서 GC(가비지 수집기)는 자동 메모리 관리자 역할을 합니다.In the common language runtime (CLR), the garbage collector (GC) serves as an automatic memory manager. 가비지 수집기는 애플리케이션의 메모리 할당 및 해제를 관리합니다.The garbage collector manages the allocation and release of memory for an application. 즉, 관리 코드를 사용하여 작업하는 개발자는 메모리 관리 작업을 수행하기 위해 코드를 작성할 필요가 없습니다.For developers working with managed code, this means that you don't have to write code to perform memory management tasks. 자동 메모리 관리를 사용하면 실수로 개체 비우기를 수행하지 않거나 메모리 누수를 유발하거나 또는 이미 비워진 개체를 찾기 위해 메모리에 액세스하려는 경우 등의 일반적인 문제를 해결할 수 있습니다.Automatic memory management can eliminate common problems, such as forgetting to free an object and causing a memory leak or attempting to access memory for an object that's already been freed.

이 문서에서는 가비지 수집의 핵심 개념에 대해 설명합니다.This article describes the core concepts of garbage collection.

이점Benefits

가비지 수집기는 다음과 같은 이점을 제공합니다.The garbage collector provides the following benefits:

  • 개발자가 수동으로 메모리를 해제할 필요가 없습니다.Frees developers from having to manually release memory.

  • 관리되는 힙에 효율적으로 개체를 할당합니다.Allocates objects on the managed heap efficiently.

  • 더 이상 사용되지 않는 개체를 회수하고 이러한 개체의 메모리를 비워 이후 할당에서 이 메모리를 사용할 수 있도록 합니다.Reclaims objects that are no longer being used, clears their memory, and keeps the memory available for future allocations. 관리되는 개체는 자동으로 시작을 위한 정리된 콘텐츠를 받으므로 개체의 생성자가 모든 데이터 필드를 초기화할 필요가 없습니다.Managed objects automatically get clean content to start with, so their constructors don't have to initialize every data field.

  • 개체에서 다른 개체의 콘텐츠를 사용할 수 없도록 하여 메모리 안전을 제공합니다.Provides memory safety by making sure that an object cannot use the content of another object.

메모리 기본 사항Fundamentals of memory

다음 목록은 중요한 CLR 메모리 개념을 요약한 것입니다.The following list summarizes important CLR memory concepts.

  • 각 프로세스에는 고유한 개별 가상 주소 공간이 있습니다.Each process has its own, separate virtual address space. 동일 컴퓨터의 모든 프로세스는 동일한 실제 메모리와 페이지 파일(있는 경우)을 공유합니다.All processes on the same computer share the same physical memory and the page file, if there is one.

  • 기본적으로 32비트 컴퓨터에서는 각 프로세스에 2GB 사용자 모드 가상 주소 공간이 포함됩니다.By default, on 32-bit computers, each process has a 2-GB user-mode virtual address space.

  • 애플리케이션 개발자는 가상 주소 공간만 사용하고 실제 메모리는 직접적으로 조작하지 않습니다.As an application developer, you work only with virtual address space and never manipulate physical memory directly. 가비지 수집기는 관리되는 힙에서 사용자 대신 가상 메모리를 할당 및 해제합니다.The garbage collector allocates and frees virtual memory for you on the managed heap.

    네이티브 코드를 작성 중인 경우 Windows 함수를 사용하여 가상 주소 공간을 작업합니다.If you're writing native code, you use Windows functions to work with the virtual address space. 이러한 함수는 네이티브 힙에서 사용자 대신 가상 메모리를 할당 및 해제합니다.These functions allocate and free virtual memory for you on native heaps.

  • 가상 메모리는 다음 세 가지 상태일 수 있습니다.Virtual memory can be in three states:

    시스템 상태State 설명Description
    FreeFree 메모리 블록에 가상 메모리에 대한 참조가 없으며, 메모리 블록을 할당에 사용할 수 있습니다.The block of memory has no references to it and is available for allocation.
    예약됨Reserved 메모리 블록을 사용자의 작업에 사용할 수 있으며, 다른 할당 요청에는 메모리 블록을 사용할 수 없습니다.The block of memory is available for your use and cannot be used for any other allocation request. 하지만 커밋되기 전까지는 메모리 블록에 데이터를 저장할 수 없습니다.However, you cannot store data to this memory block until it is committed.
    커밋됨Committed 메모리 블록이 실제 스토리지에 할당되어 있습니다.The block of memory is assigned to physical storage.
  • 가상 주소 공간은 조각화될 수 있습니다.Virtual address space can get fragmented. 즉, 주소 공간에 구멍이라고도 부르는 빈 블록이 존재합니다.This means that there are free blocks, also known as holes, in the address space. 가상 메모리 할당이 요청된 경우 가상 메모리 관리자는 할당 요청을 만족시킬 수 있도록 충분히 큰 단일 빈 블록을 찾아야 합니다.When a virtual memory allocation is requested, the virtual memory manager has to find a single free block that is large enough to satisfy that allocation request. 2GB의 여유 공간이 있는 경우에도 전체 여유 공간이 한 주소 블록에 있는 경우가 아니면 2GB가 필요한 할당이 실패할 수 있습니다.Even if you have 2 GB of free space, an allocation that requires 2 GB will be unsuccessful unless all of that free space is in a single address block.

  • 예약할 가상 주소 공간이나 커밋할 실제 공간이 충분하지 않은 경우 메모리 부족이 발생할 수 있습니다.You can run out of memory if there isn't enough virtual address space to reserve or physical space to commit.

    페이지 파일은 실제 메모리 압력(즉, 실제 메모리에 대한 요구)이 낮더라도 사용됩니다.The page file is used even if physical memory pressure (that is, demand for physical memory) is low. 실제 메모리 압력이 처음으로 높아지면 운영 체제가 데이터를 저장하기 위해 실제 메모리에 공간을 만들어야 하며, 실제 메모리에 있는 데이터 중 일부를 페이지 파일로 백업합니다.The first time that physical memory pressure is high, the operating system must make room in physical memory to store data, and it backs up some of the data that is in physical memory to the page file. 필요할 때까지는 데이터가 페이지 파일로 저장되지 않으므로 실제 메모리 압력이 낮은 상황에서도 페이징이 발생할 수 있습니다.That data is not paged until it's needed, so it's possible to encounter paging in situations where the physical memory pressure is low.

메모리 할당Memory allocation

사용자가 새 프로세스를 시작하면 런타임에서는 인접한 주소 공간 영역을 이 프로세스에 예약합니다.When you initialize a new process, the runtime reserves a contiguous region of address space for the process. 이 예약된 주소 공간을 관리되는 힙이라고 합니다.This reserved address space is called the managed heap. 관리되는 힙에서는 힙에 있는 다음 개체가 할당될 주소의 포인터를 관리합니다.The managed heap maintains a pointer to the address where the next object in the heap will be allocated. 초기에 이 포인터는 관리되는 힙의 기본 주소로 설정됩니다.Initially, this pointer is set to the managed heap's base address. 모든 참조 형식은 관리되는 힙에 할당됩니다.All reference types are allocated on the managed heap. 애플리케이션에서 참조 형식을 처음으로 만드는 경우, 이 참조 형식에 대한 메모리는 관리되는 힙의 기본 주소로 할당됩니다.When an application creates the first reference type, memory is allocated for the type at the base address of the managed heap. 애플리케이션에서 두 번째 개체를 만드는 경우, 가비지 수집기는 첫 번째 개체와 바로 인접한 주소 공간에 두 번째 개체의 메모리를 할당합니다.When the application creates the next object, the garbage collector allocates memory for it in the address space immediately following the first object. 주소 공간을 사용할 수 있다면 가비지 수집기는 이런 방식으로 계속해서 새 개체에 주소 공간을 할당합니다.As long as address space is available, the garbage collector continues to allocate space for new objects in this manner.

관리되는 힙에서 메모리를 할당하면 관리되지 않는 힙에서 메모리를 할당하는 것보다 속도가 더 빠릅니다.Allocating memory from the managed heap is faster than unmanaged memory allocation. 런타임에서는 포인터에 값을 더하여 개체에 메모리를 할당하기 때문에, 스택에서 메모리를 할당하는 속도만큼 빠릅니다.Because the runtime allocates memory for an object by adding a value to a pointer, it's almost as fast as allocating memory from the stack. 또한, 연속으로 할당된 새 개체는 관리되는 힙에 인접하여 저장되므로 애플리케이션에서 개체에 빠른 속도로 액세스할 수 있습니다.In addition, because new objects that are allocated consecutively are stored contiguously in the managed heap, an application can access the objects quickly.

메모리 해제Memory release

가비지 수집기의 최적화 엔진은 수행 중인 할당에 따라 수집을 수행하기에 가장 적합한 시간을 결정합니다.The garbage collector's optimizing engine determines the best time to perform a collection based on the allocations being made. 수집을 수행할 때 가비지 수집기는 애플리케이션에서 더 이상 사용되지 않는 개체에 대한 메모리를 해제합니다.When the garbage collector performs a collection, it releases the memory for objects that are no longer being used by the application. 가비지 수집기는 애플리케이션의 루트 를 검사하여 더 이상 사용되지 않는 개체를 결정합니다.It determines which objects are no longer being used by examining the application's roots. 애플리케이션 루트에는 정적 필드, 스레드 스택의 지역 변수, CPU 레지스터, GC 핸들, finalize 큐가 포함됩니다.An application's roots include static fields, local variables on a thread's stack, CPU registers, GC handles, and the finalize queue. 각 루트는 관리되는 힙에 있는 개체를 참조하거나 Null로 설정됩니다.Each root either refers to an object on the managed heap or is set to null. 가비지 수집기는 나머지 런타임에 이러한 루트를 요청할 수 있습니다.The garbage collector can ask the rest of the runtime for these roots. 가비지 수집기는 이 목록을 사용하여 그래프를 만드는데, 이 그래프에는 루트에서 연결할 수 있는 모든 개체가 포함되어 있습니다.Using this list, the garbage collector creates a graph that contains all the objects that are reachable from the roots.

그래프에 없는 개체는 애플리케이션 루트에서 연결할 수 없습니다.Objects that are not in the graph are unreachable from the application's roots. 가비지 수집기는 연결할 수 없는 개체를 가비지로 간주하고 이 개체에 할당된 메모리를 해제할 것입니다.The garbage collector considers unreachable objects garbage and releases the memory allocated for them. 수집을 수행할 때 가비지 수집기는 연결할 수 없는 개체에서 사용되는 주소 공간 블록을 찾기 위해 관리되는 힙을 검사합니다.During a collection, the garbage collector examines the managed heap, looking for the blocks of address space occupied by unreachable objects. 연결할 수 없는 개체가 발견되면 가비지 수집기는 메모리 복사 기능을 사용하여 메모리에서 연결할 수 있는 개체를 압축합니다. 그러면 연결할 수 없는 개체에 할당된 주소 공간 블록이 해제됩니다.As it discovers each unreachable object, it uses a memory-copying function to compact the reachable objects in memory, freeing up the blocks of address spaces allocated to unreachable objects. 연결할 수 있는 개체의 메모리가 압축되면 가비지 수집기는 포인터의 위치를 적절하게 수정합니다. 그러면 애플리케이션 루트는 개체의 새 위치를 가리킬 수 있습니다.Once the memory for the reachable objects has been compacted, the garbage collector makes the necessary pointer corrections so that the application's roots point to the objects in their new locations. 또한 가비지 수집기는 관리되는 힙의 포인터 위치를 연결할 수 있는 마지막 개체 다음에 지정합니다.It also positions the managed heap's pointer after the last reachable object.

컬렉션에서 연결할 수 없는 개체의 수가 엄청나게 발견되는 경우에만 메모리를 압축합니다.Memory is compacted only if a collection discovers a significant number of unreachable objects. 수집을 수행한 후에도 관리되는 힙에서 모든 개체가 그대로 남아 있다면 메모리 압축을 수행할 필요가 없습니다.If all the objects in the managed heap survive a collection, then there is no need for memory compaction.

런타임에서는 성능 향상을 위해 큰 개체의 메모리를 별도의 힙에 할당합니다.To improve performance, the runtime allocates memory for large objects in a separate heap. 그러면 가비지 수집기는 큰 개체에 할당된 메모리를 자동으로 해제합니다.The garbage collector automatically releases the memory for large objects. 하지만 메모리에서 큰 개체가 이동하는 것을 피하기 위해 일반적으로 이 메모리는 압축되지 않습니다.However, to avoid moving large objects in memory, this memory is usually not compacted.

가비지 수집 조건Conditions for a garbage collection

가비지 수집은 다음 조건 중 하나가 충족될 경우 발생합니다.Garbage collection occurs when one of the following conditions is true:

  • 시스템의 실제 메모리가 부족합니다.The system has low physical memory. 이는 OS의 메모리 부족 알림 또는 호스트에서 표시되는 메모리 부족을 통해 감지됩니다.This is detected by either the low memory notification from the OS or low memory as indicated by the host.

  • 관리되는 힙의 할당된 개체에 사용되는 메모리가 허용되는 임계값을 초과합니다.The memory that's used by allocated objects on the managed heap surpasses an acceptable threshold. 이 임계값은 프로세스가 실행됨에 따라 계속 조정됩니다.This threshold is continuously adjusted as the process runs.

  • GC.Collect 메서드가 호출됩니다.The GC.Collect method is called. 가비지 수집기가 지속적으로 실행되므로 이 메서드를 호출해야 하는 경우는 거의 없습니다.In almost all cases, you don't have to call this method, because the garbage collector runs continuously. 이 메서드는 주로 특이한 상황 및 테스트에 사용됩니다.This method is primarily used for unique situations and testing.

관리되는 힙The managed heap

CLR에 의해 가비지 수집기가 초기화되고 나면 가비지 수집기가 개체를 저장 및 관리하기 위해 메모리 세그먼트를 할당합니다.After the garbage collector is initialized by the CLR, it allocates a segment of memory to store and manage objects. 이 메모리를 관리되는 힙이라고 하며, 이는 운영 체제의 네이티브 힙과 대조됩니다.This memory is called the managed heap, as opposed to a native heap in the operating system.

관리되는 각 프로세스마다 관리되는 힙이 있습니다.There is a managed heap for each managed process. 프로세스의 모든 스레드는 같은 힙에 개체 메모리를 할당합니다.All threads in the process allocate memory for objects on the same heap.

메모리를 예약하기 위해 가비지 수집기는 Windows VirtualAlloc 함수를 호출하며 관리되는 애플리케이션을 위해 한 번에 하나의 메모리 세그먼트를 예약합니다.To reserve memory, the garbage collector calls the Windows VirtualAlloc function and reserves one segment of memory at a time for managed applications. 또한 가비지 수집기는 필요할 때 세그먼트를 예약하고 Windows VirtualFree 함수를 호출하여 (세그먼트에서 개체를 지운 후) 세그먼트를 운영 체제로 돌려보냅니다.The garbage collector also reserves segments, as needed, and releases segments back to the operating system (after clearing them of any objects) by calling the Windows VirtualFree function.

중요

가비지 수집기에서 할당되는 세그먼트 크기는 구현에 따라 다르며 정기적인 업데이트를 포함하여 언제든지 변경될 수 있습니다.The size of segments allocated by the garbage collector is implementation-specific and is subject to change at any time, including in periodic updates. 앱에서 특정 세그먼트 크기를 가정하거나 의존해서는 안 되며, 세그먼트 할당에 사용할 수 있는 메모리 크기를 구성하려고 해서도 안 됩니다.Your app should never make assumptions about or depend on a particular segment size, nor should it attempt to configure the amount of memory available for segment allocations.

힙에 할당되는 개체의 수가 적을수록 가비지 수집기가 할 일도 줄어듭니다.The fewer objects allocated on the heap, the less work the garbage collector has to do. 개체를 할당할 때는 15바이트만 필요한 상황에서 32바이트 배열을 할당하는 것처럼 필요 이상의 값을 사용하지 마세요.When you allocate objects, don't use rounded-up values that exceed your needs, such as allocating an array of 32 bytes when you need only 15 bytes.

가비지 수집이 트리거되면 가비지 수집기는 비활성 개체에 의해 점유된 메모리를 회수합니다.When a garbage collection is triggered, the garbage collector reclaims the memory that's occupied by dead objects. 회수 프로세스는 활성 개체를 압축하여 함께 이동하도록 하며, 비활성 공간이 제거되어 힙의 크기가 더 작아집니다.The reclaiming process compacts live objects so that they are moved together, and the dead space is removed, thereby making the heap smaller. 이로써 함께 할당된 개체가 관리되는 힙에서 함께 유지되어 집약성을 계속 유지합니다.This ensures that objects that are allocated together stay together on the managed heap to preserve their locality.

가비지 수집의 개입 수준(빈도와 지속 시간)은 할당 규모 및 관리되는 힙에서 남은 메모리의 크기에 따라 결정됩니다.The intrusiveness (frequency and duration) of garbage collections is the result of the volume of allocations and the amount of survived memory on the managed heap.

힙은 두 힙(대형 개체 힙과 소형 개체 힙)의 누적으로 간주할 수 있습니다.The heap can be considered as the accumulation of two heaps: the large object heap and the small object heap. 대형 개체 힙에는 일반적으로 배열인 85,000바이트 이상의 개체가 포함됩니다.The large object heap contains objects that are 85,000 bytes and larger, which are usually arrays. 인스턴스 개체의 크기가 상당히 커지는 경우는 거의 없습니다.It's rare for an instance object to be extremely large.

대형 개체 힙에서 사용할 수 있도록 개체의 임계값 크기를 구성할 수 있습니다.You can configure the threshold size for objects to go on the large object heap.

세대Generations

GC 알고리즘은 몇 가지 고려 사항을 기반으로 합니다.The GC algorithm is based on several considerations:

  • 가비지 수집기는 관리되는 전체 힙보다 관리되는 일부 힙에서 더 빠르게 메모리를 압축할 수 있습니다.It's faster to compact the memory for a portion of the managed heap than for the entire managed heap.
  • 개체가 새로울수록 수명은 더 짧아지고 개체가 오래될수록 수명은 더 길어집니다.Newer objects have shorter lifetimes and older objects have longer lifetimes.
  • 새로운 개체일수록 서로 연결되는 경향이 있어서 애플리케이션에서 거의 동시에 액세스됩니다.Newer objects tend to be related to each other and accessed by the application around the same time.

가비지 수집은 주로 수명이 짧은 개체의 회수와 함께 발생합니다.Garbage collection primarily occurs with the reclamation of short-lived objects. 가비지 수집기의 성능을 최적화하기 위해 관리되는 힙은 0세대, 1세대 및 2세대의 3개 세대로 나뉘어 있으므로 수명이 길고 수명이 짧은 개체를 별도로 처리할 수 있습니다.To optimize the performance of the garbage collector, the managed heap is divided into three generations, 0, 1, and 2, so it can handle long-lived and short-lived objects separately. 가비지 수집기는 새 개체를 0세대에 저장합니다.The garbage collector stores new objects in generation 0. 애플리케이션 수명의 초기에 만들어져 수집 후에도 남아 있는 개체는 수준이 올라가 1세대와 2세대에 저장됩니다.Objects created early in the application's lifetime that survive collections are promoted and stored in generations 1 and 2. 전체 힙보다 일부 관리되는 힙을 압축하는 것이 더 빠르기 때문에 가비지 수집기는 수집을 수행할 때마다 이 체계를 사용하여 전체 관리되는 힙에서 메모리를 해제하는 대신 특정 세대에서 메모리를 해제할 수 있습니다.Because it's faster to compact a portion of the managed heap than the entire heap, this scheme allows the garbage collector to release the memory in a specific generation rather than release the memory for the entire managed heap each time it performs a collection.

  • 0세대.Generation 0. 가장 젊은 세대이며 수명이 짧은 개체를 포함합니다.This is the youngest generation and contains short-lived objects. 수명이 짧은 개체의 예로는 임시 변수가 있습니다.An example of a short-lived object is a temporary variable. 가비지 수집은 이 세대에서 가장 자주 발생합니다.Garbage collection occurs most frequently in this generation.

    새로 할당된 개체는 새로운 개체 세대를 구성하며 암시적으로 0세대 수집입니다.Newly allocated objects form a new generation of objects and are implicitly generation 0 collections. 그러나 대형 개체인 경우 ‘3세대’라고도 하는 LOH(대형 개체 힙)에서 사용됩니다.However, if they are large objects, they go on the large object heap (LOH), which is sometimes referred to as generation 3. 3세대는 물리적 세대로, 논리적으로는 2세대의 일부로 수집됩니다.Generation 3 is a physical generation that's logically collected as part of generation 2.

    대부분의 개체는 0세대 가비지 수집에서 회수되며 다음 세대까지 남아 있지 않습니다.Most objects are reclaimed for garbage collection in generation 0 and don't survive to the next generation.

    애플리케이션에서 새 개체를 만들려고 할 때 0세대가 가득 찬 경우, 가비지 수집기에서는 개체에 대한 주소 공간을 확보하려고 시도하는 컬렉션을 수행합니다.If an application attempts to create a new object when generation 0 is full, the garbage collector performs a collection in an attempt to free address space for the object. 가비지 수집기는 관리되는 힙에서 모든 개체를 검사하는 대신 먼저 세대 0에서 개체를 검사합니다.The garbage collector starts by examining the objects in generation 0 rather than all objects in the managed heap. 0세대에만 컬렉션을 수행하더라도 애플리케이션에서 새 개체를 계속 만들 수 있는 충분한 메모리를 확보하기도 합니다.A collection of generation 0 alone often reclaims enough memory to enable the application to continue creating new objects.

  • 1세대.Generation 1. 이 세대는 수명이 짧은 개체를 포함하며 수명이 짧은 개체와 수명이 긴 개체 사이에서 버퍼 역할을 합니다.This generation contains short-lived objects and serves as a buffer between short-lived objects and long-lived objects.

    가비지 수집기에서는 0세대 컬렉션을 수행한 후 연결할 수 있는 개체의 메모리를 압축하고 1세대로 승격시킵니다.After the garbage collector performs a collection of generation 0, it compacts the memory for the reachable objects and promotes them to generation 1. 수집 후에도 존재하는 개체는 수명이 긴 성향이 있기 때문에, 이런 개체를 상위 세대로 승격시키는 것이 당연합니다.Because objects that survive collections tend to have longer lifetimes, it makes sense to promote them to a higher generation. 가비지 수집기에서 0세대 수집을 수행할 때마다 1세대와 2세대에서 개체를 다시 검사할 필요가 없습니다.The garbage collector doesn't have to reexamine the objects in generations 1 and 2 each time it performs a collection of generation 0.

    예를 들어, 0세대에서 수집을 수행했음에도 불구하고 애플리케이션에서 새 개체를 성공적으로 만드는 데 필요한 충분한 메모리를 확보할 수 없는 경우, 가비지 수집기는 1세대에서 2세대의 순서로 수집을 수행할 수 있습니다.If a collection of generation 0 does not reclaim enough memory for the application to create a new object, the garbage collector can perform a collection of generation 1, then generation 2. 또한, 수집이 완료된 후에 세대 1에 존재하는 개체를 세대 2로 승격시킵니다.Objects in generation 1 that survive collections are promoted to generation 2.

  • 2세대.Generation 2. 이 세대는 수명이 긴 개체를 포함합니다.This generation contains long-lived objects. 수명이 긴 개체의 예로는 프로세스의 기간 동안 유지되는 정적 데이터가 포함된 서버 애플리케이션의 개체가 있습니다.An example of a long-lived object is an object in a server application that contains static data that's live for the duration of the process.

    수집이 완료된 후에 2세대에 존재하는 개체는 다음 수집에서 연결할 수 없는 개체로 결정될 때까지 2세대에 보관됩니다.Objects in generation 2 that survive a collection remain in generation 2 until they are determined to be unreachable in a future collection.

    대량 개체 힙(‘3세대’라고도 함)의 개체는 2세대에서도 수집됩니다.Objects on the large object heap (which is sometimes referred to as generation 3) are also collected in generation 2.

가비지 수집은 조건이 충족될 때 특정 세대에서 발생합니다.Garbage collections occur on specific generations as conditions warrant. 하나의 세대를 수집한다는 것은 해당 세대와 그보다 더 젊은 모든 세대의 개체를 수집한다는 것을 의미합니다.Collecting a generation means collecting objects in that generation and all its younger generations. 2세대 가비지 수집은 모든 세대의 개체(즉, 관리되는 힙의 모든 개체)를 회수하므로 전체 가비지 수집이라고도 합니다.A generation 2 garbage collection is also known as a full garbage collection, because it reclaims objects in all generations (that is, all objects in the managed heap).

유지 및 승격Survival and promotions

가비지 수집에서 회수되지 않는 개체는 남은 개체라고 하며 다음 세대로 승격됩니다.Objects that are not reclaimed in a garbage collection are known as survivors and are promoted to the next generation:

  • 0세대 가비지 수집에서 남은 개체는 1세대로 승격됩니다.Objects that survive a generation 0 garbage collection are promoted to generation 1.
  • 1세대 가비지 수집에서 남은 개체는 2세대로 승격됩니다.Objects that survive a generation 1 garbage collection are promoted to generation 2.
  • 2세대 가비지 수집에서 남은 개체는 2세대에 남아 있습니다.Objects that survive a generation 2 garbage collection remain in generation 2.

가비지 수집기는 한 세대의 잔존율이 높음을 탐지하면 해당 세대의 할당 임계값을 늘립니다.When the garbage collector detects that the survival rate is high in a generation, it increases the threshold of allocations for that generation. 다음 수집으로 상당한 크기의 회수된 메모리가 발생합니다.The next collection gets a substantial size of reclaimed memory. CLR은 가비지 수집을 지연하여 애플리케이션의 작업 집합이 너무 커지지 않도록 하는 것과 가비지 수집이 너무 자주 실행되지 않도록 하는 두 가지 우선 순위 사이에서 지속적으로 균형을 유지합니다.The CLR continually balances two priorities: not letting an application's working set get too large by delaying garbage collection and not letting the garbage collection run too frequently.

임시 세대 및 세그먼트Ephemeral generations and segments

0세대와 1세대의 개체는 수명이 짧으므로 이러한 세대를 임시 세대 라고 합니다.Because objects in generations 0 and 1 are short-lived, these generations are known as the ephemeral generations.

임시 세대는 임시 세그먼트라는 메모리 세그먼트에 할당됩니다.Ephemeral generations are allocated in the memory segment that's known as the ephemeral segment. 가비지 수집기에서 획득하는 새로운 각 세그먼트는 새로운 임시 세그먼트가 되며 0세대 가비지 수집에서 남은 개체를 포함합니다.Each new segment acquired by the garbage collector becomes the new ephemeral segment and contains the objects that survived a generation 0 garbage collection. 이전의 임시 세그먼트는 새로운 2세대 세그먼트가 됩니다.The old ephemeral segment becomes the new generation 2 segment.

임시 세그먼트의 크기는 시스템이 32비트 또는 64비트인지, 그리고 실행 중인 가비지 수집기 형식(워크스테이션 또는 서버 GC)에 따라 달라집니다.The size of the ephemeral segment varies depending on whether a system is 32-bit or 64-bit and on the type of garbage collector it is running (workstation or server GC). 다음 표에서는 임시 세그먼트의 기본 크기를 보여 줍니다.The following table shows the default sizes of the ephemeral segment.

워크스테이션/서버 GCWorkstation/server GC 32비트32-bit 64비트64-bit
워크스테이션 GCWorkstation GC 16MB16 MB 256 MB256 MB
서버 GCServer GC 64MB64 MB 4 GB4 GB
논리적 CPU 수가 4개를 초과하는 서버 GCServer GC with > 4 logical CPUs 32MB32 MB 2GB2 GB
논리적 CPU 수가 8개를 초과하는 서버 GCServer GC with > 8 logical CPUs 16MB16 MB 1GB1 GB

임시 세그먼트에는 2세대 개체가 포함될 수 있습니다.The ephemeral segment can include generation 2 objects. 2세대 개체는 여러 세그먼트를 사용할 수 있습니다(프로세스에 필요하고 메모리가 허용하는 한도만큼).Generation 2 objects can use multiple segments (as many as your process requires and memory allows for).

임시 가비지 수집에서 해제된 메모리의 크기는 임시 세그먼트의 크기로 제한됩니다.The amount of freed memory from an ephemeral garbage collection is limited to the size of the ephemeral segment. 해제되는 메모리의 크기는 비활성 개체가 점유했던 공간에 비례합니다.The amount of memory that is freed is proportional to the space that was occupied by the dead objects.

가비지 컬렉션 중 수행되는 작업What happens during a garbage collection

가비지 수집은 다음 단계로 구성됩니다.A garbage collection has the following phases:

  • 모든 활성 개체를 찾아 목록을 만드는 표시 단계A marking phase that finds and creates a list of all live objects.

  • 압축될 개체에 대한 참조를 업데이트하는 재배치 단계A relocating phase that updates the references to the objects that will be compacted.

  • 비활성 개체에 의해 점유된 공간을 회수하고 남은 개체를 압축하는 압축 단계.A compacting phase that reclaims the space occupied by the dead objects and compacts the surviving objects. 압축 단계에서는 가비지 수집에서 남은 개체가 세그먼트의 오래된 쪽으로 이동됩니다.The compacting phase moves objects that have survived a garbage collection toward the older end of the segment.

    2세대 수집은 여러 세그먼트를 점유할 수 있으므로 2세대로 승격된 개체는 오래된 세그먼트로 이동될 수 있습니다.Because generation 2 collections can occupy multiple segments, objects that are promoted into generation 2 can be moved into an older segment. 1세대 및 2세대 남은 개체는 2세대로 승격되므로 모두 다른 세그먼트로 이동될 수 있습니다.Both generation 1 and generation 2 survivors can be moved to a different segment, because they are promoted to generation 2.

    일반적으로 대형 개체를 복사하면 성능 저하가 발생하기 때문에 LOH(대형 개체 힙)는 압축되지 않습니다.Ordinarily, the large object heap (LOH) is not compacted, because copying large objects imposes a performance penalty. 하지만 .NET Core 및 .NET Framework 4.5.1 이상에서, GCSettings.LargeObjectHeapCompactionMode 속성을 사용하면 필요 시 대형 개체 힙을 압축시킬 수 있습니다.However, in .NET Core and in .NET Framework 4.5.1 and later, you can use the GCSettings.LargeObjectHeapCompactionMode property to compact the large object heap on demand. 또한 다음 중 하나를 지정하여 하드 한도가 설정된 경우 LOH가 자동으로 압축됩니다.In addition, the LOH is automatically compacted when a hard limit is set by specifying either:

가비지 수집기는 다음 정보를 사용하여 개체가 활성 개체인지 여부를 판단합니다.The garbage collector uses the following information to determine whether objects are live:

  • 스택 루트.Stack roots. JIT(Just-In-Time) 컴파일러 및 스택 워크에서 제공한 스택 변수Stack variables provided by the just-in-time (JIT) compiler and stack walker. JIT 최적화는 가비지 수집기로 보고되는 스택 변수 내에서 코드 영역을 늘리거나 줄일 수 있습니다.JIT optimizations can lengthen or shorten regions of code within which stack variables are reported to the garbage collector.

  • 가비지 수집 핸들.Garbage collection handles. 관리되는 개체를 가리키며 사용자 코드 또는 공용 언어 런타임에 의해 할당될 수 있는 핸들입니다.Handles that point to managed objects and that can be allocated by user code or by the common language runtime.

  • 정적 데이터.Static data. 다른 개체를 참조할 수 있는 애플리케이션 도메인의 정적 개체입니다.Static objects in application domains that could be referencing other objects. 각 애플리케이션 도메인은 해당 정적 개체를 추적합니다.Each application domain keeps track of its static objects.

가비지 수집이 시작되기 전에 가비지 수집을 트리거한 스레드를 제외한 모든 관리되는 스레드가 일시 중단됩니다.Before a garbage collection starts, all managed threads are suspended except for the thread that triggered the garbage collection.

다음 그림에서는 가비지 수집을 트리거하여 다른 스레드가 일시 중단되도록 하는 스레드를 보여 줍니다.The following illustration shows a thread that triggers a garbage collection and causes the other threads to be suspended.

스레드에서 가비지 수집을 트리거하는 시기

관리되지 않는 리소스Unmanaged resources

가비지 수집기는 사용자 애플리케이션에서 만들어지는 대부분의 개체에 대해 메모리 관리 작업을 자동으로 수행할 수 있습니다.For most of the objects that your application creates, you can rely on garbage collection to automatically perform the necessary memory management tasks. 하지만 관리되지 않는 리소스의 경우는 명시적으로 정리할 필요가 있습니다.However, unmanaged resources require explicit cleanup. 가장 일반적인 형태의 관리되지 않는 리소스로는 파일 핸들, 창 핸들 또는 네트워크 연결 등의 운영 체제 리소스를 래핑하는 개체를 들 수 있습니다.The most common type of unmanaged resource is an object that wraps an operating system resource, such as a file handle, window handle, or network connection. 가비지 수집기에서는 관리되지 않는 리소스를 캡슐화하는 데 사용되는 관리되는 개체의 수명을 추적할 수 있지만, 리소스 정리 방법에 대한 구체적인 정보는 알 수 없습니다.Although the garbage collector is able to track the lifetime of a managed object that encapsulates an unmanaged resource, it doesn't have specific knowledge about how to clean up the resource.

관리되지 않는 리소스를 캡슐화하는 개체를 만드는 경우 관리되지 않는 리소스를 정리하는 데 필요한 코드를 공용 Dispose 메서드에 제공하는 것이 좋습니다.When you create an object that encapsulates an unmanaged resource, it's recommended that you provide the necessary code to clean up the unmanaged resource in a public Dispose method. Dispose 메서드를 사용하면 개체 사용자가 개체 사용을 마칠 때 할당된 메모리를 명시적으로 해제할 수 있습니다.By providing a Dispose method, you enable users of your object to explicitly free its memory when they are finished with the object. 관리되지 않는 리소스를 캡슐화하는 개체를 사용하는 경우 필요에 따라 Dispose를 호출해야 합니다.When you use an object that encapsulates an unmanaged resource, make sure to call Dispose as necessary.

형식의 소비자가 실수로 Dispose를 호출하지 않은 경우 관리되지 않는 리소스를 해제하는 방법도 제공해야 합니다.You must also provide a way for your unmanaged resources to be released in case a consumer of your type forgets to call Dispose. 안전한 핸들을 사용하여 관리되지 않는 리소스를 래핑하거나 Object.Finalize() 메서드를 재정의할 수 있습니다.You can either use a safe handle to wrap the unmanaged resource, or override the Object.Finalize() method.

관리되지 않는 리소스 정리에 대한 자세한 내용은 관리되지 않는 리소스 정리를 참조하세요.For more information about cleaning up unmanaged resources, see Clean up unmanaged resources.

참조See also