Python 内存不释放原理

标签: python 内存 释放 | 发表时间:2011-09-29 00:17 | 作者:(author unknown) jyf1987
出处:http://simple-is-better.com/

在maillist里面看到无数次的有人问,python速度为什么这么慢,python内存管理很差。实话说,我前面已经说过了。如果你在意内存/CPU,不要用python,改用C吧。就算C不行,起码也用个go或者java。不过今天还是说说,python的内存为什么不释放。

    首先,python的初始内存消耗比C大,而且大很多。这个主要来自python解释器的开销,没什么好解释的。用解释器,就得承担解释器运行开销。然后,python中的每个对象,都有一定的对象描述成本。因此一个long为例,在C下面一般是4个字节(不用int是因为int在不同平台下是变长的),而python下面至少是16个字节。如果你生成100W个对象,那么C的内存消耗是4M,python的是16M。这些都是常规内存消耗,搞不明白的就别问了,不再解释。
 
    下面解释一下python的内存释放情况。
 
    如果是C,通常是用long array[1024 * 1024]的方法来生成1M个对象空间。当然,实际这样是不一定能运行的。因为linux的默认栈空间是8M,而Windows默认栈空间只有1M。所以代码在linux下可以通过,而windows下会跑爆掉。怎么办?下面说。当这个函数执行完毕后,当RET的时候,会自动退栈,空间就会自动释放掉(虽然在逻辑上这部分空间还是保留没有释放的,然而空间不活跃了,不过统计的时候还是占用的)。当然,更好的办法是使用malloc。malloc会从系统中自动提取和管理空间,free自动释放。这样无论是linux还是windows,都没有栈空间不足的问题。free后就会自动交还系统(4M已经超过了交还的最大阀值,一般glibc不会自己闷掉不交给系统的)。如果你忘记free,这部分内存就会一直占用,直到进程退出未知,这就是很有名的内存泄露。
 
    python下的情况更加复杂一些,python没有直接使用malloc为对象分配细粒度内存,而是使用了三层堆结构,加上三色标记进行回收。所谓三层堆,细节我们不说了,在源码阅读笔记里面写的比较详细。但是有一点需要我们记住的——当我们分配某个大小的内存的时候,内存管理器实际上是向上对齐到8字节,然后去对应的内存池中切一块出来用的。也就是说,如果我们运气比较差,申请了10个对象,偏偏每个对象大小差8字节。这样系统就要给我们分配10个堆,而不是刚刚好。如果你的对象粒度都比较散,那么内存开销比较大也不奇怪。
 
    python下还有一个更坑爹的事情,也是大部分内存不释放的根本原因。在int/str等对象的模块中,有个模块级别的对象缓存链表,static PyObject * free_list。当对象释放的时候,压根不会还到池中,而是直接在free_list中缓存。根据我的搜索,python内部没有地方对此进行干预。就是说,一旦你真的生成了1M个数字对象,然后释放。这1M个对象会在free_list链表中等待重用,直到天荒地老,这16M内存压根不会返还。而且,int的对象缓存链表和str的还不通用。如果你又做了1M个str对象,他的开销还是会继续上涨。几乎所有的内建对象都有这种机制,因此对于大规模对象同时生成,python会消耗大量内存,并且永不释放。
 
    解决的机制,基本只有用yield来将列表对象转换为生成器对象。列表对象会同时生成所有元素,从而直接分配所有内存。而生成器则是一次生成一个元素,比较节约内存。

# 来源:shell's home


在微博上关注: 新浪, 腾讯   投稿

最新招聘

更多>>

相关 [python 内存 释放] 推荐:

python内存不释放原理

- Sosi - shell's home
    在maillist里面看到无数次的有人问,python速度为什么这么慢,python内存管理很差. 如果你在意内存/CPU,不要用python,改用C吧. 就算C不行,起码也用个go或者java. 不过今天还是说说,python的内存为什么不释放.     首先,python的初始内存消耗比C大,而且大很多.

Python 内存不释放原理

- jyf1987 - python.cn(jobs, news)
在maillist里面看到无数次的有人问,python速度为什么这么慢,python内存管理很差. 如果你在意内存/CPU,不要用python,改用C吧. 就算C不行,起码也用个go或者java. 不过今天还是说说,python的内存为什么不释放.     首先,python的初始内存消耗比C大,而且大很多.

JAVA内存释放

- - Java - 编程语言 - ITeye博客
(问题一:什么叫垃圾回收机制. ) 垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能. 当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用,以免造成内存泄露. (问题二:java的垃圾回收有什么特点. ) JAVA语言不允许程序员直接控制内存空间的使用.

python之记录一次内存溢出

- - 研发管理 - ITeye博客
手头一个系统上线后,节点机中agent应用在运行10天后,占用系统内存居然高达10GB以上,这显然是发生了严重内存泄露. python是动态语言,对用动态语言的内存分析不是很容易,尝试了一下比较经典的内存分析工具meliae,但是发现不是很好用. 查了很多资料后,发现了 https://github.com/pympler/pympler 这个工具,官方文档地址为:.

JNA中内存处理-释放动态库中分配的内存(新)

- - CSDN博客推荐文章
前面已经介绍过一次JNA中内存释放方法,后经过实际分析,这样写的代码不是很优雅,实际项目中代码实现方法如下:. 如下是libvirt java binding实现代码存在内存泄露:. 如下是解决内存泄露的代码:. 作者:greencacti 发表于2012-11-16 21:56:05 原文链接.

小技巧,快速释放Windows 7内存

- 夏天天下 - 软矿
相信很多人都会有这样的感觉,电脑开机长时间会明显变得缓慢,那是因为内存高速缓存无法刷新占用内存资源. 重启电脑自然可以将内存缓存清空但是就是得重启. 其实系统自带清空内存命令,你完全可以通过这样的方式快速实现. 快速释放Windows 7内存教程:. Step1 -右键点击桌面新建一个快捷方式;. Step2 -复制下面的Code到对象位置;.

关于Android程序退出后内存释放的问题

- - CSDN博客推荐文章
做 Android项目的时候发现一个问题:当应用程序退出了,点击"设置"查看应用程序,界面显示着可以点击"强制关闭".. 我认为造成这样的原因是还有开启的activity没有被destroy,然后做调试,之后发现开启的activity应该是全部都被. destroy了.但是结果还是显示可以点击"强制关闭"..

特征向量内存快速查找库 GitHub - spotify/annoy: Approximate Nearest Neighbors in C++/Python optimized for memory usage and loading/saving to disk

- -
还有一些其他库可以进行最近邻搜索. Annoy几乎和最快的库一样快(见下文),但实际上还有另一个功能让Annoy与众不同:它能够将静态文件用作索引. 特别是,这意味着您可以跨进程共享索引. Annoy还将创建索引与加载它们分离,因此您可以将索引作为文件传递并快速映射到内存中. Annoy的另一个好处是它试图最小化内存占用,因此索引非常小.

dropbox讲python

- chuang - Initiative
dropbox定制优化CPython虚拟机,自己搞了个malloc调度算法. 那个 !!!111cos(0). 期待这次PyCon China 2011.

Python调试

- - 企业架构 - ITeye博客
原文地址: http://blog.csdn.net/xuyuefei1988/article/details/19399137. 1、下面网上收罗的资料初学者应该够用了,但对比IBM的Python 代码调试技巧:. IBM:包括 pdb 模块、利用 PyDev 和 Eclipse 集成进行调试、PyCharm 以及 Debug 日志进行调试:.