在工作中出现了一个未曾注意的问题:python的内存泄露问题,直接说问题和解决方式:

我遇到的问题出现内存泄露主要是因为:使用c类型申请的变量数组造成的泄露,因为申请(ctype.c_int*len)() 这类的数组的时候,没有手动清除,导致在程序结束的时候,没有自动回收,导致内存不断的增加。

  1. python内存管理机制:
  1. 根据变量的引用计数,引用计数变为0,在结束的时候,垃圾回收机制,会回收;
  2. 标记清除:如果两个对象的引用计数都是1,两个对象是循环引用的,虽然引用计数表现为非0,但是实际上有效的引用计数为0,这两个变量都需要清除;
  3. 分代回收:垃圾回收分为0,1,2代;这个就是有的变量存活时间比较长,这种变量往往不能及时回收;这种就需要手动清楚;
  1. 调优的手段:
  1. 避免循环引用
  2. 手动垃圾回收
  3. 调高垃圾回收阈值(没有试验,前两个都用了。自认为系统的设置一般不动,毕竟不是专业的运维的。)
  1. 内存的问题使用的方式:
  1. heap():在python3中引入guppy3,from guppy import hpy   然后打印出栈中内存的使用情况:print(hpy().heap())
  2. import objgraph,显示内存中变量的增长情况使用objgraph.show_growth()
  3. memory_profiler:在函数的前边添加@profile 显示内存的变化,我这里没有用这个。
  4. 使用tracemalloc,查看没有释放内存的变量和位置,这是我主要使用的方式,
  1. 使用tracker,先查看是否有内存泄露,
  1. from pympler import tracker,summary,muppy
  2. memory_tracer = tracker.SummaryTracker()
  3. 程序流程
  4. 查看是否有内存泄露:memory_tracer.print_diff()
  1. 使用tracemalloc 查看泄露的位置
  1. import tracemalloc  
  2. tracemalloc.start()    运行的程序     
  3. snapshot1 = tracemalloc.take_snapshot()
  4. top_stats = snapshot1.statistics('lineno')   #定位变量的名字和位置
  5. for stat in top_stats[:limit]:   #limit:自己定义个数,要显示的个数
  1. print(stat)
  1. 根据这个可以找到没有释放掉位置,找到变量,在使用完变量后,要手动销毁,del +变量的名字
  2. 在结束后使用gc.collect(),释放掉需要释放的变量。