python의 세 가지 흔히 볼 수 있는 메모리 유출 장면을 총괄하다

5933 단어 python메모리누설
개요
Python이 자동 쓰레기 회수가 있으면 메모리 누출이 없다고 생각하지 마라. 쓰레기 회수가 있기 때문에 나는'스팸 코드'의 정신을 가지고 있다. 지금 세 가지 흔히 볼 수 있는 메모리 누출 장면을 총괄해 보자.
무궁무진하게 메모리 유출을 초래하다
만약 메모리 유출을 신청만 하고 방출하지 않는다고 정의한다면,Python의 정수를 빌려 무한대의 이 특징을 빌려 우리 코드는 메모리 유출을 완성할 수 있다.

i = 1024 ** 1024 ** 1024
순환 인용으로 메모리 유출
인용 기수기는 Python 쓰레기 회수 메커니즘의 기초이다. 만약에 대상의 인용 수량이 0이 되지 않으면 쓰레기가 회수되지 않는다. 우리는sys를 통해getrefcount는 주어진 대상의 인용 수량을 얻습니다.

In [1]: import sys                               

In [2]: a = {'name':'tom','age':16}                       

In [3]: sys.getrefcount(a)  #   getrefcount   a  ,  2 。               
Out[3]: 2

In [4]: b = a                                  

In [5]: sys.getrefcount(a)                           
Out[5]: 3
먼저 순환 인용 장면을 보십시오.

#!/usr/bin/evn python3

import sys
import time
import threading


class Person(object):
  free_lock = threading.Condition()

  def __init__(self, name: str = ""):
    """
    Parameters
    ----------
    name: str
       

    best_friend: str
       
    """
    self._name = name
    self._best_friend = None

  @property
  def best_friend(self, person: "Person"):
    return self._best_friend

  @best_friend.setter
  def best_friend(self, friend: "Person"):
    self._best_friend = friend

  def __str__(self):
    """
    """
    return self._name

  def __del__(self):
    """
    """
    self.free_lock.acquire()
    print(f"{self._name}   GG  , 。")
    sys.stderr.flush()
    self.free_lock.release()


def mem_leak():
  """
   
  """
  zhang_san = Person(name=' ')
  li_si = Person(" ")

  #  
  #  
  li_si.best_friend = zhang_san
  #  
  zhang_san.best_friend = li_si


if __name__ == "__main__":
  for i in range(3):
    time.sleep(0.01)
    print(f"{i}")
    mem_leak()

  print("mem_leak  .")
  time.sleep(5)
실행 효과.
python3 main.py
0


mem_leak 실행이 완료되었습니다.
장삼은 GG를 원하는데, 지금 그것의 메모리 공간을 방출한다.
이사는 GG를 원한다. 이제 메모리 공간을 방출한다.
장삼은 GG를 원하는데, 지금 그것의 메모리 공간을 방출한다.
이사는 GG를 원한다. 이제 메모리 공간을 방출한다.
장삼은 GG를 원하는데, 지금 그것의 메모리 공간을 방출한다.
이사는 GG를 원한다. 이제 메모리 공간을 방출한다
순환 인용의 존재로 인해mem_leak 함수만 실행하면 그 내부의 국부 변수 인용 계수기도 0이 아니기 때문에 메모리가 제때에 방출되지 않습니다.이 부분의 메모리를 방출하는 데는 두 가지 경로가 있다. 1,Python 내부의 순환 검출 메커니즘에 의해 발견되었다.2. 프로세스가 종료되기 전의 집중 방출.
tracemalloc 일정한 절차에서 우리가 문제를 발견하는 것을 도울 수 있다. 여기서 어떻게 사용하는지 말하지 않고 우리는 직접 해결 방안을 제시한다.Python은 프로그래머에게 약한 인용을 제공합니다. 이런 방식을 통해 대상 인용 계수기의 수치를 증가하지 않을 수 있습니다. 이것은 우리가 순환 인용을 깨뜨리는 수단이 되었습니다.

In [1]: import sys                               

In [2]: import weakref                             

In [3]: from main import Person                         

In [4]: tom = Person('tom')                           

In [5]: sys.getrefcount(tom)                          
Out[5]: 2

In [6]: p = weakref.ref(tom)                          

In [7]: sys.getrefcount(tom)  #                          
Out[7]: 2
현재 weakref 기술을 사용하여 우리의 코드를 개조합니다.

#!/usr/bin/evn python3


import sys
import time
import weakref
import threading


class Person(object):
  free_lock = threading.Condition()

  def __init__(self, name: str = ""):
    """
    Parameters
    ----------
    name: str
       

    best_friend: str
       
    """
    self._name = name
    self._best_friend = None

  @property
  def best_friend(self, person: "Person"):
    return self._best_friend

  @best_friend.setter
  def best_friend(self, friend: "Person"):
    self._best_friend = weakref.ref(friend)

  def __str__(self):
    """
    """
    return self._name

  def __del__(self):
    """
    """
    self.free_lock.acquire()
    print(f"{self._name}   GG  , 。")
    sys.stderr.flush()
    self.free_lock.release()


def mem_leak():
  """
   
  """
  zhang_san = Person(name=' ')
  li_si = Person(" ")

  #  
  #  
  li_si.best_friend = zhang_san
  #  
  zhang_san.best_friend = li_si


if __name__ == "__main__":
  for i in range(3):
    time.sleep(0.01)
    print(f"{i}")
    mem_leak()

  print("mem_leak  .")
  time.sleep(5)
실행 효과.
python3 main.py
0
장삼은 GG를 원하는데, 지금 그것의 메모리 공간을 방출한다.
이사는 GG를 원한다. 이제 메모리 공간을 방출한다.

장삼은 GG를 원하는데, 지금 그것의 메모리 공간을 방출한다.
이사는 GG를 원한다. 이제 메모리 공간을 방출한다.

장삼은 GG를 원하는데, 지금 그것의 메모리 공간을 방출한다.
이사는 GG를 원한다. 이제 메모리 공간을 방출한다.
mem_leak 실행이 완료되었습니다.
현재 함수 실행이 완료되면 그 내부의 국부 변수의 메모리가 방출되고 매우 신속하다는 것을 볼 수 있다.
외부 라이브러리가 메모리 유출을 초래하다
이런 상황은 나도 단지 한 번 만난 적이 있다. 이전에 mysql-connector-python의 메모리 유출로 인해 나의 프로그램이 달리면서 차지하는 메모리가 점점 커진다.마지막으로 우리가 되돌아온 C 언어의 확장이 비활성화되면 문제가 없다.
이상은python의 세 가지 흔히 볼 수 있는 메모리 유출 장면의 상세한 내용을 총괄하고python 메모리 유출에 관한 더 많은 자료는 저희 다른 관련 글에 주목하세요!

좋은 웹페이지 즐겨찾기