Python_쓰레기 수거 메커니즘의 GC 모듈 ③

6078 단어 Python

하나.쓰레기 회수 메커니즘


파이톤의 쓰레기 회수는 인용 계수를 위주로 하고 세대별 수집을 보조로 한다.

1. 인용 계수 +1을 초래하는 경우

  • , a=23
  • , b=a
  • , , func(a)
  • , , list1=[a,a]

  • 2. 인용 계수 -1을 초래하는 경우

  • , del a
  • , a=24
  • , f ,func ( )

  • 3. 한 대상의 인용 수를 보기

    import sys
    a = "hello world"
    sys.getrefcount(a)

    a 대상의 인용 계수를 볼 수 있지만 정상 계수보다 1이 큽니다. 함수를 호출할 때 a를 전송하면 a의 인용 계수가 +1이 되기 때문입니다.

    둘.순환 인용으로 메모리 유출


    인용 계수의 결함은 순환 인용의 문제이다
    # -*- coding: utf-8 -*-
    # @Author  : G_SANGSK
    
    import gc
    
    class ClassA():
        def __init__(self):
            print('object born,id:%s'%str(hex(id(self))))
    
    def f2():
        while True:
            c1 = ClassA()
            c2 = ClassA()
            c1.t = c2
            c2.t = c1
            del c1
            del c2
    
    # python gc 
    gc.disable()
    
    f2()

    f2 () 를 실행하면 프로세스가 차지하는 메모리가 계속 증가합니다.
  • c1, c2를 만든 후 이 두 메모리의 인용 계수는 모두 1이고 실행c1.t=c2c2.t=c1을 실행한 후 이 두 메모리의 인용 계수는 2가 된다.
  • del c1 이후 메모리 1의 대상의 인용 계수는 1이 되고 0이 아니기 때문에 메모리 1의 대상은 소각되지 않기 때문에 메모리 2의 대상의 인용 수는 여전히 2이다.del c2 이후에도 마찬가지로 메모리 1의 대상, 메모리 2의 대상의 인용 수는 모두 1이다.
  • 두 대상은 모두 폐기될 수 있지만 순환 인용으로 쓰레기 수거기가 회수되지 않아 메모리 유출이 발생한다.

  • 셋.쓰레기 수거

    # -*- coding: utf-8 -*-
    # @Author  : G_SANGSK
    
    import gc
    
    class ClassA():
        def __init__(self):
            print('object born,id:%s'%str(hex(id(self))))
        # def __del__(self):
        #     print('object del,id:%s'%str(hex(id(self))))
    
    def f3():
        print("-----0------")
        # print(gc.collect())
        c1 = ClassA()
        c2 = ClassA()
        c1.t = c2
        c2.t = c1
        print("-----1------")
        del c1
        del c2
        print("-----2------")
        print(gc.garbage)
        print("-----3------")
        print(gc.collect()) # 
        print("-----4------")
        print(gc.garbage)
        print("-----5------")
    
    if __name__ == '__main__':
        gc.set_debug(gc.DEBUG_LEAK) # gc 
        f3()

    python2 실행 결과:
    -----0------
    object born,id:0x724b20
    object born,id:0x724b48
    -----1------
    -----2------
    []
    -----3------
    gc: collectable 
    gc: collectable 
    gc: collectable 
    gc: collectable 
    4
    -----4------
    [<__main__.classa instance="" at="">, <__main__.classa instance="" at="">, {'t': <__main__.classa instance="" at="">}, {'t': <__main__.classa instance="" at="">}]
    -----5------

    설명:
  • 쓰레기 회수 후 대상은 gc.garbage 목록 안
  • gc.collect () 는 도달할 수 없는 대상의 수를 되돌려줍니다. 4는 두 대상과 대응하는dict
  • 쓰레기 수거를 촉발하는 세 가지 상황이 있다.

  • gc를 호출합니다.collect(),
  • gc모듈의 계수기가 밸브값에 도달했을 때.
  • 프로그램이 종료되었을 때
  • 넷.gc 모듈 상용 기능 분석

    gc .위에서 말한 바와 같이 인용 계수의 방법으로 메모리를 관리하는 결함의 하나는 순환 인용이고 gc모듈의 주요 기능은 순환 인용 문제를 해결하는 것이다.
    공통 함수:
    1、gc.set_debug(flags) gc의 debug 로그를 설정합니다. 일반적으로 gc로 설정합니다.DEBUG_LEAK
    2、gc.collect([generation])현식으로 쓰레기 수거를 진행하면 파라미터를 입력할 수 있습니다. 0은 1세대만 검사하는 대상이고, 1은 1세대, 2세대만 검사하는 대상이며, 2는 1, 2, 3세대를 검사하는 대상입니다. 파라미터를 전달하지 않으면 full collection을 실행합니다. 즉 2세대와 같습니다.도달할 수 없는 객체 수를 반환합니다.
    3、gc.get_threshold () 에서 가져온 gc 모듈에서 쓰레기 회수 주파수를 자동으로 실행합니다.
    4、gc.set_threshold(threshold0[,threshold1[,threshold2])는 쓰레기 회수를 자동으로 실행하는 주파수를 설정합니다.
    5、gc.get_count () 현재 쓰레기 수거를 자동으로 실행하는 계수기를 가져와 길이 3의 목록을 되돌려줍니다
    gc 모듈의 자동 쓰레기 회수 메커니즘
    import gc 모듈이 필요하고is_enable()=True 자동 쓰레기 회수가 시작됩니다.
    이 메커니즘의 . = +
    파이톤에서는 세대별로 수집하는 방법을 사용한다.대상을 3세대로 나눠 처음에는 대상자가 창설될 때 세대에 두고, 한 세대 한 세대 쓰레기 검사에서 개대상이 살아남으면 2세대에 넣고, 같은 이치로 한 세대 두 세대 쓰레기 검사에서 이 대상이 살아남으면 3세대에 넣는다.
    gc 모듈 안에는 길이가 3인 목록의 계수기가 있는데 gc를 통과할 수 있다.get_count()를 가져옵니다.
    예를 들어(488,3,0)에서 488은 지난번 쓰레기 검사에서 Python의 메모리 분배 수량에서 메모리를 방출한 수량을 빼고 인용 계수의 증가가 아니라 메모리 분배에 주의하는 것을 말한다.예를 들면 다음과 같습니다.
    print gc.get_count() # (590, 8, 0)
    a = ClassA()
    print gc.get_count() # (591, 8, 0)
    del a
    print gc.get_count() # (590, 8, 0)

    3은 지난번 2세대 쓰레기 검사, 1세대 쓰레기 검사 횟수, 같은 이치, 0은 지난번 3세대 쓰레기 검사, 2세대 쓰레기 검사 횟수를 가리킨다.
    gc모드는 자동 쓰레기 회수 , 즉 gc를 통과한다.get_threshold 함수에서 얻은 길이가 3인 모듈, 예를 들어 (700,10,10) 매번 계수기의 증가에 따라 gc모듈은 증가한 계수가 밸브값에 도달했는지 검사하고, 만약 그렇다면 대응하는 대수의 쓰레기 검사를 실시하고 계수기를 리셋합니다.
    예를 들어, 밸브 값이 (700,10,10)인 경우를 가정합니다.
    ‘’‘
     (699,3,0) (700,3,0),gc gc.collect(0), , (0,4,0)
     (699,9,0) (700,9,0),gc gc.collect(1), 、 , (0,0,1)
     (699,9,9) (700,9,9),gc gc.collect(2), 、 、 , (0,0,0)
    ’‘’

    주의점


    gc 모듈에서 유일하게 처리할 수 없는 것은 순환 인용 클래스가 모두 있다는 것이다del__방법. 따라서 프로젝트에서 정의를 피해야 한다.del__메서드
    import gc
    
    class ClassA():
        pass
        # def __del__(self):
        #     print('object born,id:%s'%str(hex(id(self))))
    
    gc.set_debug(gc.DEBUG_LEAK)
    a = ClassA()
    b = ClassA()
    
    a.next = b
    b.prev = a
    
    print "--1--"
    print gc.collect()
    print "--2--"
    del a
    print "--3--"
    del b
    print "--3-1--"
    print gc.collect()
    print "--4--"

    실행 결과:
    --1--
    0
    --2--
    --3--
    --3-1--
    gc: collectable 
    gc: collectable 
    gc: collectable 
    gc: collectable 
    4
    --4--

    del을 열면 다음 결과가 실행됩니다.
    --1--
    0
    --2--
    --3--
    --3-1--
    gc: uncollectable 
    gc: uncollectable 
    gc: uncollectable 
    gc: uncollectable 
    4
    --4--

    좋은 웹페이지 즐겨찾기