谈谈如何linux 手动释放内存Python的内存

python怎么让端口立即释放
按时间排序
socket.shutdown然后socket.close
在防火墙设置里面!·!!!!~ 开启端口!!~
最近在使用登陆奇兵破解软件的过程中需要释放80 端口,关闭IIS,由于期间遇到一些问题,经过一一解决后,最终顺利使用。第一步,Win7 开始菜单里面自带的“运行”命令可能无法执行CMD 的命令,输入正常命令(如ping, netstat)后提示“不是内部或外部命令,也不是可运行的程序或批处理文件”。这时,我们需要在C:\Windows\System32 下找到CMD.EXE 然后右键以管理员身份执行,这样就可以正常使用了。当然,如果为了方便使用,你可以右键复制到开始菜单,即Windows 命令处理程序。输入netstat –a –n –o,以我的电脑为例,得到如下信息:C:\Windows\System32 netstat -a -n -o活动连接协议
状态PIDTCP
0.0.0.0:80
0.0.0.0:135
0.0.0.0:445
0.0.0.0:49152
0.0.0.0:49153
0.0.0.0:49154
0.0.0.0:49155
0.0.0.0:49164
127.0.0.1:2559
192.168.1.102:139
4(后面省略)上图中可以看到第一排显示的80 端口被PID(进程号)为2564 的程序占用。第三步,启动任务管理器,选中“进程”标签,点击“查看”—“选择列”,选中 PID(进程标识符),这样就可以看到每个进程的标识符,然后Cut 掉相应的进程即可。本 文 来 自 CSDN 博 客 , 转 载 请 标 明 出 处 :
你是在做网站么,题目不清楚。帮不了你
如果是tcp client用同一个本地端口去连不同的两个服务器ip,连第二个时就会提示端口已被占用。但服务器的监听端口,可以accept多次,建立多个socket;我的问题是服务器一个端口为什么能建立多个连接而客户端却不行呢?TCP server 可以,TCP client 也可以。一个套接字只能建立一个连接,无论对于 server 还是 client。注意报错消息是:[Errno 106] (EISCONN) Transport endpoint is already connectedman 2 connect 说得很清楚了:Generally, connection-based protocol sockets may successfully connect() connectionless protocol sockets may use connect() multiple times to change their association.就是说,TCP 套接字最多只能调用 connect 一次。那么,你的监听套接字调用 connect 了几次?来点有意思的。一个套接字不能连接两次,并不代表一个本地地址不能用两次,看!****加粗文字**加粗文字**&&& import socket&&& s = socket.socket()# since Linux 3.9, 见 man 7 socket&&& s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)&&& s2 = socket.socket()&&& s2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)&&& s.bind(('127.0.0.1', 12345))&&& s2.bind(('127.0.0.1', 12345))# 都可以使用同一本地地址来连接哦&&& s.connect(('127.0.0.1', 80))&&& s2.connect(('127.0.0.1', 4321))&&& netstat -npt | grep 12345(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)tcp
0 127.0.0.1:4321
127.0.0.1:12345
ESTABLISHED 18284/python3tcp
0 127.0.0.1:12345
127.0.0.1:4321
ESTABLISHED 4568/python3tcp
0 127.0.0.1:80
127.0.0.1:12345
ESTABLISHED -tcp
0 127.0.0.1:12345
127.0.0.1:80
ESTABLISHED 4568/python3你们这些有女友的都弱爆了啦 :-(更新:大家来玩 TCP: 一个人也可以建立 TCP 连接呢 - 依云's Blog日回答 · 日更新依云21.1k 声望答案对人有帮助,有参考价值1答案没帮助,是错误的答案,答非所问内核是以一个(著名的)5元信息组来标识不同的socket的:源地址、源端口、目的地址、目的端口、协议号。任何一个不同,都不叫“同一个socket”。日回答sched_yield80 声望答案对人有帮助,有参考价值0答案没帮助,是错误的答案,答非所问首先,TCP链接是可靠的端对端的链接,每个TCP链接由4个要素组成:2组IP地址(本地和远端),2组端口地址(本地和远端)。其中如果需要跟端口信息绑定时,都需要调用bind函数,如果server端针对2个同样的IP、端口组进行同样的绑定时,第2次同样是不成功的。日回答charliecui2.4k 声望答案对人有帮助,有参考价值0答案没帮助,是错误的答案,答非所问有个相关的问题: ftp的数据传输,服务器会用20端口主动连接客户端,如果两个客户端同时在一下载东西,那ftp 服务器能用20端口去连接两个ip ?(这时ftp的服务器其实是tcp里的客户端)日回答 编辑hyanleo163 声望+1能啊,看我的实验。依云 · 日不管是服务器还是客户端,建立TCP链接,同一个端口都只能使用一次。这句话其实是**错的**!对于TCP协议,要成功建立一个新的链接,需要保证新链接四个要素组合体的唯一性:客户端的IP、客户端的port、服务器端的IP、服务器端的port。也就是说,服务器端的同一个IP和port,可以和同一个客户端的多个不同端口成功建立多个TCP链接(与多个不同的客户端当然也可以),只要保证【Server IP + Server Port + Client IP + Client Port】这个组合唯一不重复即可。& netstat -a -n -p tcp |grep 9999tcp 0 0 127.0.0.1:.0.1:9999 ESTABLISHED 2701/nc tcp 0 0 127.0.0.1:.0.1:9999 ESTABLISHED 2752/nc上述结果127.0.0.1:端口成功建立两个TCP链接,也就可以理解。**客户端**发送TCP链接请求的端口,也就是后续建立TCP链接使用的端口,所以一旦TCP链接建立,端口就被占用,无法再建立第二个链接。而**服务器端**有两类端口:侦听端口 和 后续建立TCP链接的端口。其中侦听端口只负责侦听客户端发送来的TCP链接请求,不用作建立TCP链接使用,一旦侦听到有客户端发送TCP链接请求,就分配一个端口(一般随机分配,且不会重复)用于建立TCP链接,而不是所说的服务器一个端口能建立多个连接。上述描述也比较片面,客户端如何请求及建立链接,服务器端如何侦听及是否分配新随机端口等...应该都可以在应用层面进行控制,所以上述描述可以作为建立TCP链接的一种方式,仅供参考。一些英文的参考:How do multiple clients connect simultaneously to one port, say 80, on a server?TCP : two different sockets sharing a port?------------------------------------------------------------------------------------ 提升linux下tcp服务器并发连接数限制
20:30:231、修改用户进程可打开文件数限制
在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:
[speng@as4 ~]$ ulimit -n
这表示当前用户的每个进程最多允许同时打开1024个文件,这1024个文件中还得除去每个进程必然打开的标准输入,标准输出,标准错误,服务器监听 socket,进程间通讯的unix域socket等文件,那么剩下的可用于客户端socket连接的文件数就只有大概4个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许同时1014个TCP并发连接。
对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。
修改上述限制的最简单的办法就是使用ulimit命令:
[speng@as4 ~]$ ulimit -n
上述命令中,在中指定要设置的单一进程允许打开的最大文件数。如果系统回显类似于“Operation notpermitted”之类的话,说明上述限制修改失败,实际上是因为在中指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。因此,就需要修改Linux系统对用户的关于打开文件数的软限制和硬限制。
第一步,修改/etc/security/limits.conf文件,在文件中添加如下行:
speng soft nofile 10240
speng hard nofile 10240
其中speng指定了要修改哪个用户的打开文件数限制,可用'*'号表示修改所有用户的限制;soft或hard指定要修改软限制还是硬限制;10240则指定了想要修改的新的限制值,即最大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。
第二步,修改/etc/pam.d/login文件,在文件中添加如下行:
session required /lib/security/pam_limits.so
这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。修改完后保存此文件。
第三步,查看Linux系统级的最大打开文件数限制,使用如下命令:
[speng@as4 ~]$ cat /proc/sys/fs/file-max
这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)12158个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。修改此硬限制的方法是修改/etc/rc.local脚本,在脚本中添加如下行:
echo 22158 & /proc/sys/fs/file-max
这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为22158。修改完后保存此文件。
完成上述步骤后重启系统,一般情况下就可以将Linux系统对指定用户的单一进程允许同时打开的最大文件数限制设为指定的数值。如果重启后用 ulimit- n命令查看用户可打开文件数限制仍然低于上述步骤中设置的最大值,这可能是因为在用户登录脚本/etc/profile中使用ulimit-n命令已经将用户可同时打开的文件数做了限制。由于通过ulimit-n修改系统对用户可同时打开文件的最大数限制时,新修改的值只能小于或等于上次ulimit-n 设置的值,因此想用此命令增大这个限制值是不可能的。所以,如果有上述问题存在,就只能去打开/etc/profile脚本文件,在文件中查找是否使用了 ulimit-n限制了用户可同时打开的最大文件数量,如果找到,则删除这行命令,或者将其设置的值改为合适的值,然后保存文件,用户退出并重新登录系统即可。
通过上述步骤,就为支持高并发TCP连接处理的通讯处理程序解除关于打开文件数量方面的系统限制。2、修改网络内核对TCP连接的有关限制
在Linux上编写支持高并发TCP连接的客户端通讯处理程序时,有时会发现尽管已经解除了系统对用户同时打开文件数的限制,但仍会出现并发TCP连接数增加到一定数量时,再也无法成功建立新的TCP连接的现象。出现这种现在的原因有多种。
第一种原因可能是因为Linux网络内核对本地端口号范围有限制。此时,进一步分析为什么无法建立TCP连接,会发现问题出在connect()调用返回失败,查看系统错误提示消息是“Can't assign requestedaddress”。同时,如果在此时用tcpdump工具监视网络,会发现根本没有TCP连接时客户端发SYN包的网络流量。这些情况说明问题在于本地Linux系统内核中有限制。其实,问题的根本原因在于Linux内核的TCP/IP协议实现模块对系统中所有的客户端TCP连接对应的本地端口号的范围进行了限制(例如,内核限制本地端口号的范围为之间)。当系统中某一时刻同时存在太多的TCP客户端连接时,由于每个TCP客户端连接都要占用一个唯一的本地端口号(此端口号在系统的本地端口号范围限制中),如果现有的TCP客户端连接已将所有的本地端口号占满,则此时就无法为新的TCP客户端连接分配一个本地端口号了,因此系统会在这种情况下在connect()调用中返回失败,并将错误提示消息设为“Can't assignrequested address”。有关这些控制逻辑可以查看Linux内核源代码,以linux2.6内核为例,可以查看tcp_ipv4.c文件中如下函数:
static int tcp_v4_hash_connect(struct sock *sk)
请注意上述函数中对变量sysctl_local_port_range的访问控制。变量sysctl_local_port_range的初始化则是在tcp.c文件中的如下函数中设置:
void __init tcp_init(void)
内核编译时默认设置的本地端口号范围可能太小,因此需要修改此本地端口范围限制。
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_local_port_range =
这表明将系统对本地端口范围限制设置为之间。请注意,本地端口范围的最小值必须大于或等于1024;而端口范围的最大值则应小于或等于65535。修改完后保存此文件。
第二步,执行sysctl命令:
[speng@as4 ~]$ sysctl -p
如果系统没有错误提示,就表明新的本地端口范围设置成功。如果按上述端口范围进行设置,则理论上单独一个进程最多可以同时建立60000多个TCP客户端连接。
第二种无法建立TCP连接的原因可能是因为Linux网络内核的IP_TABLE防火墙对最大跟踪的TCP连接数有限制。此时程序会表现为在 connect()调用中阻塞,如同死机,如果用tcpdump工具监视网络,也会发现根本没有TCP连接时客户端发SYN包的网络流量。由于 IP_TABLE防火墙在内核中会对每个TCP连接的状态进行跟踪,跟踪信息将会放在位于内核内存中的conntrackdatabase中,这个数据库的大小有限,当系统中存在过多的TCP连接时,数据库容量不足,IP_TABLE无法为新的TCP连接建立跟踪信息,于是表现为在connect()调用中阻塞。此时就必须修改内核对最大跟踪的TCP连接数的限制,方法同修改内核对本地端口号范围的限制是类似的:
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_conntrack_max = 10240
这表明将系统对最大跟踪的TCP连接数限制设置为10240。请注意,此限制值要尽量小,以节省对内核内存的占用。
第二步,执行sysctl命令:
[speng@as4 ~]$ sysctl -p
如果系统没有错误提示,就表明系统对新的最大跟踪的TCP连接数限制修改成功。如果按上述参数进行设置,则理论上单独一个进程最多可以同时建立10000多个TCP客户端连接。3、使用支持高并发网络I/O的编程技术
在Linux上编写高并发TCP连接应用程序时,必须使用合适的网络I/O技术和I/O事件分派机制。
可用的I/O技术有同步I/O,非阻塞式同步I/O(也称反应式I/O),以及异步I/O。在高TCP并发的情形下,如果使用同步I/O,这会严重阻塞程序的运转,除非为每个TCP连接的I/O创建一个线程。但是,过多的线程又会因系统对线程的调度造成巨大开销。因此,在高TCP并发的情形下使用同步I /O 是不可取的,这时可以考虑使用非阻塞式同步I/O或异步I/O。非阻塞式同步I/O的技术包括使用select(),poll(),epoll等机制。异步I/O的技术就是使用AIO。
从I/O事件分派机制来看,使用select()是不合适的,因为它所支持的并发连接数有限(通常在1024个以内)。如果考虑性能,poll()也是不合适的,尽管它可以支持的较高的TCP并发数,但是由于其采用“轮询”机制,当并发数较高时,其运行效率相当低,并可能存在I/O事件分派不均,导致部分 TCP连接上的I/O出现“饥饿”现象。而如果使用epoll或AIO,则没有上述问题(早期 Linux内核的AIO技术实现是通过在内核中为每个I/O请求创建一个线程来实现的,这种实现机制在高并发TCP连接的情形下使用其实也有严重的性能问题。但在最新的Linux内核中,AIO的实现已经得到改进)。
综上所述,在开发支持高并发TCP连接的Linux应用程序时,应尽量使用epoll或AIO技术来实现并发的TCP连接上的I/O控制,这将为提升程序对高并发TCP连接的支持提供有效的I/O保证。
一般情况下,服务器就是一直开的呀,你要关闭的话,只能关闭程序了。如果你需要在某个情况下关闭服务器,可以在那个条件里面close不就行了啊。比如i++;后面为了不接受太多客户端,if(i==10) server.close();也就是一旦有10个同时连接服务器的时候,服务器直接断开。这只是一个示范,你可以再别的条件下关闭嘛。
s = server.accept();发生异常。直接跳到异常块处理。没有对socket进行关闭
感谢您为社区的和谐贡献力量请选择举报类型
经过核实后将会做出处理感谢您为社区和谐做出贡献
确定要取消此次报名,退出该活动?
请输入私信内容:谈谈如何手动释放Python的内存
转载 &发布时间:日 17:22:21 & 作者:执假以为真
Python不会自动清理这些内存,这篇文章主要介绍了谈谈如何手动释放Python的内存,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
在上篇博客中,提到了对一个脚本进行的多次优化。当时以为已经优化得差不多了,但是当测试人员测试时,我才发现,踩到了Python的一个大坑。
在上文的优化中,对每500个用户,会进行一些计算并记录结果在磁盘文件中。原本以为这么做,这些结果就在磁盘文件中了,而不会再继续占用内存;但实际上,Python的大坑就是Python不会自动清理这些内存。这是由其本身实现决定的。具体原因网上多有文章介绍,这里就不copy了。
本篇博客将贴一个笔者的实验脚本,用以说明Python确实存在这么一个不释放内存的现象,另外也提出一个解决方案,即:先del,再显式调用gc.collect(). 脚本和具体效果见下。
实验环境一:Win 7, Python 2.7
from time import sleep, time
def mem(way=1):
print time()
for i in range():
if way == 1:
else: # way 2, 3
print time()
if way == 1 or way == 2:
else: # way 3
gc.collect()
print time()
if __name__ == "__main__":
print "Test way 1: just pass"
mem(way=1)
print "Test way 2: just del"
mem(way=2)
print "Test way 3: del, and then gc.collect()"
mem(way=3)
运行结果如下:
Test way 1: just pass
Test way 2: just del
Test way 3: del, and then gc.collect()
对于way 1和way 2,结果是完全一样的,程序内存消耗峰值是326772KB,在sleep 20秒时,内存实时消耗是244820KB;
对于way 3,程序内存消耗峰值同上,但是sleep时内存实时消耗就只有6336KB了。
实验环境二: Ubuntu 14.10, Python 2.7.3
运行结果:
Test way 1: just pass
Test way 2: just del
Test way 3: del, and then gc.collect()
ubuntu@my_machine:~$ ps -aux | grep test_mem
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
6.0 564 pts/1 S+ 14:39 0:03 python test_mem.py
pts/2 S+ 14:40 0:00 grep --color=auto test_mem
ubuntu@my_machine:~$ ps -aux | grep test_mem
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
6.0 564 pts/1 S+ 14:39 0:03 python test_mem.py
pts/2 S+ 14:40 0:00 grep --color=auto test_mem
ubuntu@my_machine:~$ ps -aux | grep test_mem
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
pts/1 S+ 14:39 0:05 python test_mem.py
以上说明,当调用del时,其实Python并不会真正release内存,而是将其继续放在其内存池中;只有在显式调用gc.collect()时,才会真正release内存。
其实回到上一篇博客的脚本中,也让其引入gc.collect(),然后写个监控脚本监测内存消耗情况:
while ((1)); do ps -aux | sort -n -k5,6 | grep my_ sleep 5; done
结果发现:内存并不会在每500个用户一组执行完后恢复,而是一直持续消耗到仅存约70MB时,gc才好像起作用。本环境中,机器使用的是Cloud instance,总内存2G,可用内存约为1G,本脚本内存常用消耗是900M - 1G。换句话说,对于这个脚本来说,gc并没有立即起作用,而是在系统可用内存从1 - 1.2G下降到只剩70M左右时,gc才开始发挥作用。这点确实比较奇怪,不知道和该脚本是在Thread中使用的gc.collect()是否有关,或者是gc发挥作用原本就不是可控的。笔者尚未做相关实验,可能在下篇博客中继续探讨。
但是,可以肯定的是,若不使用gc.collect(), 原脚本将会将系统内存耗尽而被杀死。这一点从syslog中可以明显看出。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
计算过程中有些暂存数据,放在数组或其他一些耗用内存的变量中;
计算结果本地化;
这时如果不释放掉内存,这些中间数据会不会常驻内存,影响后续使用?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
当然会。当没有到你放那些数据的对象的引用时,内存会自动释放。也就是说,如果你没法在代码里访问到它们了,那么它们就会被释放掉。如果还能(比如通过全局变量),那么它们就会占据内存。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
如果在内存清理的时候,这些对象还存留这引用,则不会被清理,如果已经没有引用了,在自动会被清理掉,不用担心会有多少的内存占用的。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
del + gc应该可以搞定
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。python内存释放问题/回答/疑问 - Python - language - ITeye论坛
python内存释放问题/回答/疑问
锁定老帖子
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
等级: 初级会员
来自: 上海
发表时间:&&
最后修改:
for i in range(1000 * 1000 * 10 ):
&-----&等价
l = range(1000 * 1000 * 10 )这样的内存大对象,是不会被随便释放的,直到进程退出; 我了解到一个 Boehm GC 尝试做类似的事情.GC后全部释放; 但只是Linux试验;并不是通用性解决方法;
环境:是w_xp下的虚拟机--debian下运行. 使用下面的方法: 1. &&& for i in range ( 1000000 * 10 ): ...
del i ... &&& 看能否完成你的需求? 我测试过:如果1000000,几秒就过去了. 所以我使用1000000 * 10 . 另外开一个窗口: 运行:
do ps aux | sleep 1 ; 观察mem的使用率.发现使用了47% 2.重启python运行环境. &&& def test(): ...
for i in range ( 1000000 * 10 ): ...
del i ... &&& test() 这样使用,观察mem使用率:内存上升47%,之后重复运行test(),内存只是上升20%之后就是回落到47%. 3.为什么呢?那么把这个函数定义放到一个文件里面去. "test.py" 7L, 106C
All def test():
for i in range ( 1000000 * 10 ):
del i if ( __name__ == "__main__" ):
test() 运行 python test.py 观察 mem,上升到47%--&44%--&0.2%
import time
def test():
for i in range ( 1000000 * 10 ):
if ( __name__ == "__main__" ):
while ( True ):
time.sleep( 1 )观察mem:内存维持不变!
从这点可以猜测:python不是立即释放资源的.
下面来源于:http://book.csdn.net/bookfiles/749/.shtml
在一个对象的引用计数减为0时,与该对象对应的析构函数就会被调用,但是要特别注意的是,调用析构函数并不意味着最终一定会调用free释放内存空间,如果真是这样的话,那频繁地申请、释放内存空间会使 Python的执行效率大打折扣(更何况Python已经多年背负了人们对其执行效率的不满)。一般来说,Python中大量采用了内存对象池的技术,使用这种技术可以避免频繁地申请和释放内存空间。因此在析构时,通常都是将对象占用的空间归还到内存池中。这一点在接下来对Python内建对象的实现中可以看得一清二楚。
可以解释第四次的实验结果.
查看了些资料,说这个40%的mem是能够被回收的.
这个for循环,导致的问题,确实如你所说,python不会主动释放它已经分配的过的内存.这个是它内存控制机制:减少内存分配.据说这种情况在python2.5已经解决了.但是我使用python2.5运行程序.也许是我的机器里面的python2.5可能不是最新的. 我查看到一句话:也许能够回答你的问题. "这个问题就是:Python的arena从来不释放pool。这个问题为什么会引起类似于内存泄漏的现象呢。考虑这样一种情形,申请10*个16字节的小内存,这就意味着必须使用160M的内存,由于Python没有默认将前面提到的限制内存池的WITH_MEMORY_LIMITS编译符号打开,所以Python会完全使用arena来满足你的需求,这都没有问题,关键的问题在于过了一段时间,你将所有这些16字节的内存都释放了,这些内存都回到arena的控制中,似乎没有问题。但是问题恰恰就在这时出现了。因为arena始终不会释放它维护的pool集合,所以这160M的内存始终被Python占用,如果以后程序运行中再也不需要160M如此巨大的内存, 这点内存岂不是就浪费了?" 当然,这种情形必须在大量持续申请小内存对象时才会出现,平时大家几乎不会碰到这种 情况,所以这个问题也就一直留在了Python中,但是在2004年的时候,一个叫Evan Jones的老兄不能忍受下去了。他在对一些巨大的图做某种算法操作时必须持续申请大量小块内存,这导致Python占用的内存冲上1G后就再也掉不下来。想一想,确实相当痛苦,这位老兄一番探索,终于发现问题的根源在arena这里,于是一鼓作气,搞出了一套解决方案,并在PyCon2005上做了个报告,引起了强烈的反响。但是Python的核心开发团队一直没有将这个patch并入到Python代码中,一直到2006年,才由Tim Peters(这位老兄的名头在Python社区也是响当当的,在Python的交互环境下键入import this,看到这位老兄的名号了吧,the zen of python的创造者,当然,他在Python社区的地位可不是靠这几句广告语获得的)将这个patch整理,并入到了Python代码中,加入了这个patch的Python就是我们花了这么多精力剖析的Python2.5。在Python2.4中,实际上对arena是没有区分“未使用”和“可用”两种状态的,到了Python2.5中,arena可以将自己维的pool集合释放,返回给操作系统,从而必须从“可用”状态转为“未使用”状态,这也是必须要两种状态的原因。在前面那段代码的代码[1]之后,当Python处理完pool之后,就要开始处理arena了。
个人测试代码:
-----------------------------------------------test0.py-------------------------------------
import time
def test():
for i in range ( 1000000 * 10 ):
def test_2():
#i = range ( 1000000 * 10 )
def test_3():
#i = "*" * ( 1000000 * 10 )
if ( __name__ == "__main__" ):
for i in range( 10 ):
time.sleep( 1 )
while ( True ):
time.sleep( 1 )-----------------------------------------------------test0.py--------------------------------------
运行 python test0.py
"while ( True ):
time.sleep( 1 ) "保证python不退出.
发现python的内存占用率为60%.
如何解决这个问题呢?
-----------------------------------------------test1.py-------------------------------------
#coding=utf-8import time
max_number = 1000000 * 10def test_0():
for i in range ( max_number ):
def test_1():
for i in range( 1000 ):
for i in range ( max_number / 1000 ):
if ( __name__ == "__main__" ):
#test_0()#内存使用率占40%
test_1()#内存使用率占0.2%
print "---------------------"
while ( True ):
time.sleep( 1 )
-----------------------------------------------test1.py-------------------------------------
我想问题:问题也许解决了.
这就要看你的实际需求是什么了.
我做过一个爬虫程序,如果不断往这个线程里面传递url,那么这个线程不到一会就挂了.我的改进方法:就是控制这线程能够接受的url队列长度.以及其他的优化.
如果实际情况一定非要按test1.py的test_1()函数那样运行.我想在python的上层没有什么办法帮你解决.除非
1.你修改python的内存管理机制.
2.自己写一个py与c的接口程序.具体怎么做,我还没有做过.猜想根据:python是由c实现,python与c是有接口程序的.那么有这个需求,第二种方法应该可行.
应该是这样的: def test():
tmp = range( 1000000 ) if (....):
其实这个不是循环导致的内存被python持有,而是range( n )让python分配了很多的内存.退出test(),python回收内存,但是python并不释放了,而是让pool持有内存空间.
我是找到一个方法---对方信誓旦旦说可以做到.可是好像少了东西. url:http://effbot.org/pyfaq/how-does-python-manage-memory.htm
&How does Python manage memory?& 里面好像缺少点东西:allocate_resource 我查看源码: from Carbon import Res
在代码中有一处是这样使用:
res = Res.Resource(data)
可以重新改写python源码,之后编译.可以做到.释放内存的.这个是python提供最原始的方法
不是好的办法. 以后继续关注.
本来我不准备年后再学习python源码.现在我在看它的编程方式.觉得很有意思.它的底层内存使用方式:就是内存的分配--&持有--&再利用....我觉得如果程序让python分配了太多的内存,可以针对这部分进行改进,达到不释放python持有的内存,而让python占用最低的内存使用率.
发现:python:如果这样使用:&&& l = range( 1000 * 1000 * 10 )&&& del l内存变化:60%--&47%python内存管理规则:del的时候,把list的元素释放掉,把管理元素的大对象回收到py对象缓冲池里.
由此可见:python内存管理虽然很优秀,但是比较消耗内存.
已经有了这么信息:我们应该可以按自己的愿望做点事情了:修改源码来完成我们想要的事情.
//python2.5.4-----listobject.c-----------------
static voidlist_dealloc(PyListObject *op)
/* if (num_free_lists & MAXFREELISTS && PyList_CheckExact(op)){
//printf( "free_lists[%d] = op\n", num_free_lists );
free_lists[num_free_lists++] = } else {
//printf( "free py list objects:%d\n", op-&allocated );
op-&ob_type-&tp_free((PyObject *)op);
if (num_free_lists & MAXFREELISTS && PyList_CheckExact(op)) {
if ( op-&allocated & 10000 ) {
free_lists[num_free_lists++] =
printf( "free py list objects: op-&allocated = %d & 10000 MAXFREELISTS = %d\n", op-&allocated,MAXFREELISTS );
op-&ob_type-&tp_free((PyObject *)op);
printf( "free py list objects: op-&allocated = %d MAXFREELISTS = %d \n", op-&allocated,MAXFREELISTS );
op-&ob_type-&tp_free((PyObject *)op);
编译--&安装.
打印信息告诉我们是释放了list大对象.但是查看py的内存持有量:发现并没有变化...
是什么原因呢?
---------------------------------------------decompose_while.py---------------------------------------------------------
#coding=utf-8
i = 0j = 0k = 0c = 0l = []while i & 10:
while j & 1000:
while k & 1000:
l.append( c )print "l.len = ",len( l )import timewhile True:
time.sleep( 2 )
---------------------------------------------decompose_while.py---------------------------------------------------------
[list_div]root python decompose_while.py l.len =
.....程序sleep...
我一直怀疑一个对象怎么能够占用60%的内存空间呢?而且,我实验了很多种情况,在一个py虚拟机下不断: create list--&del list --&create list .... 也发现内存维持在60% &--& 47%之间变化.
下面我们计算下:
一个1000 * 1000 * 10大的list对象,它至少应该占有多大的内存空间:
1000 * 1000 * 10 * ( sizeof(int) ) = 40,000,000
40,000,000 /
38.15 / 256 = 0.149 % (注:我是在虚拟机里运行,分配给虚拟机是256M的内存空间,不知用这个算是否对?请指正!)
(list对象应该还有一些其他变量需要分配一些内存空间吧,这里就没有做计算了)
就是说:这个list对象应该占用系统内存的0.2%左右.
那么40%可能是在创建list的时候转换到py的缓冲池里去了.
py的内存分配规则:....可以说明这个问题.各位可以去找找看,我也会在后续补充进来.(不知道这个猜测对不对!?)
跳转论坛:移动开发技术
Web前端技术
Java企业应用
编程语言技术

我要回帖

更多关于 java 手动释放内存 的文章

 

随机推荐