• python 垃圾回收机制(转)


    起因

    前段时间,在做文本处理的实验时,需要预加载大量的原始数据(100W),在Python中使用的字典(dict)类型负责保存这些数据,很快就开发完成了一个Demo版,然而程序执行的效率不是那么令人满意,通过使用Python中的profile发现,影响程序执行性能的关键语句就那么几条(用 dict保存加载后原始数据,这是个循环遍历。)

    解决问题

    既然找到了问题源,于是就勒起衣袖开始动手尝试使用各种解决方案替代效率不佳的,经过多次的反复尝试,调优的效果不太明显,最后一个idea:考虑Python垃圾回收机制的影响了,最后也证明了这个想法的靠谱程度,本文后续部分将分享调优的过程与测试结果。

    浅谈Python垃圾回收机制

    在使用C语言开发时代,我们的开发效率(生产力的问题)受牵制于内存释放、泄露等问题,于是普遍的口号---“指针好难学”。时过境迁,当今的流行的语言都配套了内存自动回收机制,从而使我们有更多的精力去纠结于业务上处理。
    常用的垃圾回收(GC)算法有这几种引用计数(Reference Count)、Mark-Sweep、Copying、分代收集。在Python中使用的是前者引用计数,工作原理:为每个内存对象维护一个引用计数。因此得知每次内存对象的创建与销毁都必须修改引用计数,从而在大量的对象创建时,需要大量的执行修改引用计数操作(footprint),对于程序执行过程中,额外的性能开销是令人可怕的,由于该算法的特性问题,因此无法避免了,那么我们只能成垃圾回收时机着手了。
    谈到这里因此不得不谈谈垃圾回收的时机,根据官方的描叙,Python中,有2中方式将会触发垃圾回收:
    1、用户显示调用gc.collect()
    2、每次Python为新对象分配内存时,检查threshold阀值,当对象数量超过threshold设置的阀值就开始进行垃圾回收。

    调优之前

    为了便于描叙如前文所述的加载大量原始数据的问题,使用了虚假的数据,这部分程序片段完成的功能倒没有发生变化,以下是调优之前的程序片段:

    Python代码 复制代码 收藏代码
    1. data = range(1,5000000)   
    2. wdict = dict(zip(data,data))  
    data = range(1,5000000)
    wdict = dict(zip(data,data))

    使用time python test.py运行,我们可以看到以下结果(机器的差异,显示的结果也将不同):

    Python代码 复制代码 收藏代码
    1. real    0m39.066s  
    2. user    0m26.422s  
    3. sys     0m12.313s  
    real    0m39.066s
    user    0m26.422s
    sys     0m12.313s

    如果使用linux下的top命令,您将动态的看到内存的使用情况,该程序运行后将缓慢的吞噬内存,由于程序运行时的内存对象都是有效的,因此垃圾回收触发时,无法释放这部分内存,而垃圾回收程序却在做无用功(达到threshold阀值),显而易见,程序的执行性能将大打折扣。那么我们的调优手段也就很容易了,在程序片段运行的这段时间内禁止进行垃圾回收。

    调优之后

    以下是调优之后的程序片段(禁止程序片段的垃圾回收):

    Python代码 复制代码 收藏代码
    1. import gc   
    2. gc.disable()   
    3. data = range(1,5000000)   
    4. wdict = dict(zip(data,data))   
    5. gc.enable()  
    import gc
    gc.disable()
    data = range(1,5000000)
    wdict = dict(zip(data,data))
    gc.enable()

    使用time python test.py运行,我们可以看到以下结果(机器的差异,显示的结果也将不同):

    Python代码 复制代码 收藏代码
    1. real    0m2.760s  
    2. user    0m1.208s  
    3. sys     0m1.532s  
    real    0m2.760s
    user    0m1.208s
    sys     0m1.532s

    通过上面的运行结果对比,显而易见,调优后的程序性能明显大幅提升,如果使用Linux下的top命令,您将动态的看到内存的使用情况也是不同的,该程序运行后迅速的吞噬内存,对比调优之前的程序片段,减少了垃圾回收的频频触发。

    总结

    通过这次的调优体验,发现Python垃圾回收频频触发将会影响程序执行的性能,因此,正如很多同学所说,Python程序的执行速度慢是不是有垃圾回收机制的一份功劳呢?

  • 相关阅读:
    python基础之入门
    C#直接删除指定目录下的所有文件及文件夹(保留目录)
    删除Oracle文件、注册表
    WinRAR 激活码(KEY)
    用C#读取txt文件的方法(转)
    c# 生成 xml 文件
    Asp.Net 文件下载1——流下载(适用于大文件且防盗链)(转)
    Asp.Net异常:"由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值"的解决方法
    响应在此上下文中不可用 asp.net
    Ajax实现局部刷新
  • 原文地址:https://www.cnblogs.com/richard403/p/3003701.html
Copyright © 2020-2023  润新知