문제

소멸자는 객체가 보유하고있는 관리되지 않은 자원 만 출시해야하며 다른 객체를 참조해서는 안됩니다. 참조 만 관리 한 경우 소멸자를 구현할 필요가없고 안됩니다. 당신은 관리되지 않는 리소스를 처리하기 위해서만 이것을 원합니다. 소멸자를 갖는 데 약간의 비용이 있기 때문입니다, 당신은 귀중하고 관리되지 않는 리소스를 소비하는 방법에 대해서만 이것을 구현해야합니다.

-- C ++ 프로그래머의 경우 C#의 10 대 트랩

이 기사는 이것에 대해 더 깊이 들어 가지 않지만 C#의 소멸자 사용과 관련된 비용은 어떤 종류의 비용입니까?

메모: 나는 GC와 파괴자가 신뢰할 수있는시기에 불려지지 않았다는 사실에 대해 알고 있습니다.

도움이 되었습니까?

해결책

Finalizer가있는 모든 객체 (C ++ 소멸자와의 차이를 강조하기 위해 파괴자보다 용어를 선호합니다)가 Finalizer 대기열에 추가됩니다. 이것은 제거되기 전에 호출 해야하는 최종화기가있는 객체에 대한 참조 목록입니다.

객체가 쓰레기 수집을위한 개체가 올라 오면 GC는 최종 조정 대기열에 있음을 발견하고 변속기 (F-reachable) 대기열에 대한 참조를 이동합니다. 이것은 Finalizer Background 스레드가 각 객체의 Finalizer 메소드를 차례로 호출하는 목록입니다.

객체의 최종화기가 호출되면 객체는 더 이상 Finalizer 큐에 있지 않으므로 GC가 제거 할 수있는 일반 관리 객체 일뿐입니다.

이것은 객체에 최종화기가있는 경우 제거되기 전에 적어도 하나의 쓰레기 수집에서 살아남을 것임을 의미합니다. 이는 일반적으로 물체가 다음 힙 생성으로 이동하여 실제로 메모리의 데이터를 한 힙에서 다른 힙으로 이동하는 것을 포함합니다.

다른 팁

Joe Duffy 가이 모든 작품을 어떻게 수행했는지에 대해 내가 본 가장 광범위한 토론. 그것은 당신이 상상할 수있는 것보다 더 세부적인 것을 가지고 있습니다.

그 후, 나는 함께 모았다 실용적인 접근법 이 작업을 매일 - 비용에 대해서는 적은 비용이 아니라 구현에 대한 더 많은 것입니다.

Guffa와 Jaredpar는 세부 사항을 꽤 잘 커버하므로 C# 언어 사양이 불행히도 호출 할 때 Finalizers 또는 Destructors에 다소 난해한 메모를 추가하겠습니다.

명심해야 할 한 가지는 Finalizer 스레드가 모든 최종화기를 순서대로 실행하므로 Finalizer의 교착 상태가 남아있는 모든 (및 미래) 최종화기가 실행되는 것을 방지한다는 것입니다. 이러한 인스턴스는 최종화 업체가 완성 될 때까지 수집되지 않기 때문에 교착 상태를 완성하면 메모리 누출이 발생합니다.

이 기사는 문제를 자세히 다룹니다. 간단한 게시물로 요약하기가 정말 어렵습니다. http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

guffa Finalizer 비용의 요인을 상당히 잘 요약했습니다. 최근이있었습니다 기사 Java의 최종화기 비용에 대해서도 통찰력을 제공합니다.

.NET의 비용의 일부는 GC.SuppressFinalize를 사용하여 Finalizer 큐에서 객체를 제거하여 피할 수 있습니다. 기사를 기반으로 .NET에서 빠른 테스트를 실행하여 게시했습니다. 여기 (초점은 Java 측에 훨씬 더 중요합니다).


아래는 결과의 그래프입니다. 실제로 최상의 레이블이 없습니다 ;-). "Debug = true/false"는 빈 vs 간단한 파이널 라이저를 나타냅니다.

~ConditionalFinalizer()  
{  
    if (DEBUG)  
    {  
        if (!resourceClosed)  
        {  
            Console.Error.WriteLine("Object not disposed");  
        }  
        resourceClosed = true;  
    }  
} 

"suppress = true"는 GC.Suppressfinalize가 쌍극자 방법에서 호출되었는지 여부를 나타냅니다.

요약

.NET의 경우 gc.suppressfinalize를 호출하여 Finalizer 큐에서 객체를 제거하는 것은 큐에 객체를 남겨 두는 비용의 절반입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top