>  기사  >  백엔드 개발  >  한 기사에서 CPython의 가비지 수집기에 대해 알아보세요.

한 기사에서 CPython의 가비지 수집기에 대해 알아보세요.

WBOY
WBOY앞으로
2022-10-12 15:32:351569검색

이 기사에서는 CPython과 관련된 문제를 주로 소개하는 Python에 대한 관련 지식을 제공합니다. CPython의 가비지 수집기는 순환 참조 문제를 해결하기 위해 Python에 내장된 방법입니다. 모두에게 도움이 되기를 바랍니다.

한 기사에서 CPython의 가비지 수집기에 대해 알아보세요.

【관련 추천: Python3 동영상 튜토리얼

CPython의 가비지 수집기

CPython의 가비지 수집기(GC라고도 함)는 순환 참조 문제를 해결하기 위한 Python의 내장 방법입니다. 기본적으로 항상 백그라운드에서 실행되고 가끔씩 마법이 작동하므로 메모리가 막히는 순환 참조에 대해 걱정할 필요가 없습니다.

가비지 수집기는 CPython의 작업 메모리에서 순환 참조 객체를 찾아 제거하도록 설계되었습니다. 이는 다음과 같은 방법으로 수행됩니다.

  • 순환 참조 개체 감지

  • 루프 문제를 해결하기 위해 각 개체에서 포인터를 제거하는 최종 __del__ 메서드

  • 를 호출합니다. 단, 2단계 이후에도 루프가 여전히 고아인 경우에만 해당

이 프로세스가 완료되면 이전에 루프에 있던 모든 개체의 참조 횟수가 0이 되므로 이 개체는 메모리에서 삭제됩니다.

자동으로 작동하지만 실제로는 표준 라이브러리에서 모듈로 가져올 수 있습니다. 예는 다음과 같습니다:

import gc

순환 참조 감지

CPython의 가비지 수집기는 메모리에 존재하는 다양한 개체를 추적하지만 모든 개체는 아닙니다. 일부 개체를 인스턴스화하고 가비지 수집기가 해당 개체를 수집하는지 확인할 수 있습니다.

>>> gc.is_tracked("a string")
False
>>> gc.is_tracked(["a", "list"])
True

객체가 포인터를 포함할 수 있는 경우 순환 참조 구조의 일부를 형성할 수 있는 기능을 제공합니다. 이것이 바로 가비지 감지기가 존재하는 이유이며 이를 감지하고 파괴하는 것입니다. Python에서는 이러한 객체를 종종 "컨테이너 객체"라고 부릅니다.

따라서 가비지 수집기는 순환 참조의 일부로 존재할 수 있는 모든 개체에 대해 알아야 합니다. 문자열은 추적할 수 없으므로 "문자열"은 가비지 수집기에 의해 추적되지 않습니다. 목록(우리가 본 것처럼)에는 포인터가 포함될 수 있으므로 ['a', 'list']가 추적됩니다.

사용자 정의 클래스의 모든 인스턴스는 언제든지 임의의 속성(포인터)을 설정할 수 있으므로 가비지 수집기에 의해 추적됩니다.

>>> Wade = MyNameClass("Wade")
>>> gc.is_tracked(Wade)
True

그래서 가비지 수집기는 순환 참조를 형성할 수 있는 모든 개체를 알고 있습니다. 순환 참조가 형성되었는지 어떻게 알 수 있나요?

또한 각 객체의 모든 포인터와 그것이 가리키는 위치를 알고 있습니다. 우리는 이 행동을 볼 수 있습니다.

>>> my_list = ["a", "list"]
>>> gc.get_referents(my_list)
['list', 'a']

get_referents 메소드(순회 메소드라고도 함)는 객체를 수신하고 객체에 포함된 객체 포인터(해당 참조) 목록을 반환합니다. 따라서 위 목록에는 문자열인 각 요소에 대한 포인터가 포함되어 있습니다.

객체 루프에서 get_referents 메서드를 살펴보겠습니다(아직 순환 참조는 아니지만 객체는 여전히 네임스페이스에서 액세스할 수 있으므로).

>>> jane = MyNamedClass("Jane")
>>> bob = MyNamedClass("Bob")
>>> jane.friend = bob
>>> bob.friend = jane
>>> gc.get_referents(bob)
[{&#39;name&#39;: &#39;bob&#39;, &#39;friend&#39;: <__main__.MyNamedClass object at 0x7ff29a095d60>}, <class &#39;__main__

이 루프에서 bob이 가리키는 객체에는 bob의 이름(bob)과 그 친구(jane이 가리키는 MyNamedClass 인스턴스)가 포함된 속성 사전에 대한 포인터가 포함되어 있음을 알 수 있습니다. bob 객체에는 클래스 객체 자체에 대한 포인터도 있습니다. bob.class가 해당 클래스 객체를 반환하기 때문입니다.

가비지 수집기가 실행되면 알고 있는 모든 개체(즉, gc.is_tracked를 호출할 때 True를 반환하는 모든 개체)가 네임스페이스에서 연결할 수 있는지 확인합니다. 이는 코드에서 액세스할 수 있는 모든 항목에 대한 전체 보기가 구축될 때까지 네임스페이스의 모든 포인터, 해당 포인터가 가리키는 개체의 포인터 등을 추적함으로써 이를 수행합니다.

이 작업을 수행한 후 GC가 네임스페이스에서 접근할 수 없는 일부 개체가 있음을 발견하면 이러한 개체를 지울 수 있습니다.

아직 메모리에 있는 모든 객체는 참조 횟수가 0이 아니어야 한다는 점을 기억하세요. 그렇지 않으면 참조 횟수로 인해 삭제됩니다. 연결할 수 없지만 여전히 참조 횟수가 0이 아닌 개체의 경우 순환 참조의 일부여야 합니다. 이것이 바로 우리가 이러한 일이 발생할 가능성에 대해 많은 관심을 기울이는 이유입니다.

참조 루프인 jane과 bob으로 돌아가서 네임스페이스에서 포인터를 제거하여 이 루프를 루프 분리 루프로 바꿔 보겠습니다.

>>> del jane
>>> del bob

이제 우리는 가비지 컬렉터가 해결해야 할 정확한 상황을 이해했습니다. gc.collect()를 호출하여 수동 가비지 수집을 실행할 수 있습니다.

>>> gc.collect()
Deleting Bob!
Deleting Jane!
4

기본적으로 가비지 수집기는 가끔씩 자동으로 이 작업을 수행합니다(CPython 런타임 중에 점점 더 많은 객체가 생성되고 파괴되기 때문입니다).

위 코드 조각에서 우리가 보는 출력에는 MyNamClass의 __del__ 메서드의 print 문이 포함되어 있으며 끝에 숫자가 있습니다(이 경우 4). 이 숫자는 가비지 수집기 자체에 의해 출력되며 제거된 개체 수를 알려줍니다.

【관련 추천: Python3 비디오 튜토리얼

위 내용은 한 기사에서 CPython의 가비지 수집기에 대해 알아보세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.im에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제