In a development environment, we usually write python When the program is running, it pays little attention to the memory problem , Maybe write c and c++ My friends will think more about it , But once our python There is a memory leak in the program , It will also be a very troublesome thing , So how can we avoid this kind of problem , If something happens, how can we solve it? Let's take a look !

cause

A memory leak is a situation in which a program fails to release memory that is no longer in use due to negligence or error . Memory leaks are not physical disappearances , But after the application allocates some memory , Because of a design mistake , Lost control of this segment of memory , So it's a waste of memory . Causes the procedure to run the speed to slow down even the system crashes and so on the serious consequence . Yes del() The main culprit of memory leak is the circular reference between objects of function

programme

Use... When not using an object :delobject To delete the reference count of an object can effectively prevent memory leakage . adopt Python Extension module gc To see the details of objects that cannot be recycled . Can pass sys.getrefcount(obj) To get the reference count of the object , And according to whether the return value is 0 To determine if there is a memory leak .

But because of gc Garbage collection mechanism , To traverse all of the python object ( Including garbage and non garbage objects ), This process is time-consuming and may cause the program to jam , It's going to do something about memory 、cpu Demanding scenarios have a performance impact . So how to avoid memory leaks gracefully ?

Write secure code

For example, for the following memory leaks cycle_ref function , Dereference the loop before the end of the function , Can solve the memory leak problem .

def cycle_ref():

a1 = A()
a2 = A()
a1.child = a2
a2.child = a1
#  Dereference , Avoid memory leaks
a1.child  = None
a2.child  = None

But for the above method , We may forget one or two unimportant lines of code and have disastrous consequences , After all, tigers sometimes nap . What to do with that ? Don't worry ,Python That has been taken into account for us : Weak reference .

Weak reference

Python The standard library provides weakref modular , Weak references are not counted in the reference count , Its main purpose is to solve the problem of circular reference . Not all objects support weakref, for example list and dict I don't support . Here is weakref The more common method :

“”"

  1. class weakref.ref(object[, callback]) : Create a weak reference object ,object Is the referenced object ,callback It's a callback function ( When the referenced object is deleted , Call the callback function )

2.weakref.proxy(object[, callback]): Create a proxy object implemented with a weak reference , The parameters are the same as above

3.weakref.getweakrefcount(object) : Get objects object The number of weakly referenced objects associated

4.weakref.getweakrefs(object): obtain object List of associated weakly referenced objects

5.class weakref.WeakKeyDictionary([dict]): establish key Dictionary for weakly referenced objects

6.class weakref.WeakValueDictionary([dict]): establish value Dictionary for weakly referenced objects

7.class weakref.WeakSet([elements]): Create a collection object whose members are weakly referenced objects

“”"

Also for the memory leak above cycle_ref function , Use weakref Slightly improved , Can be more secure to solve the problem of memory leakage :

import weakref

class A(object):

def __init__(self):
    self.data = [x for x in range(100000)]
    self.child = None
def __del__(self):
    pass

def cycle_ref():

a1 = A()
a2 = A()
a1.child = weakref.proxy(a2)
a2.child = weakref.proxy(a1)

if name == ‘main’:

import time
while True:
    time.sleep(0.5)
    cycle_ref()