首页/Home PHP Articles & Reviews PHP 之垃圾回收 (Garbage Collection)

PHP 之垃圾回收 (Garbage Collection)

PrintE-mail
Sunday, 20 December 2009 04:38   Review this article  Add to Technorati Favorites

很多人问到过这样的问题:简述一下 PHP 的垃圾回收机制。垃圾回收是可以简述的。但也可以论述上几个小时。我想,大多数人的意思可能只是想让你谈几点 PHP 5.3 之前的 PHP 垃圾回收机制。你在网上找到的,很多时候,是很片面的。

首先,垃圾回收,简称GC,全称 Garbage Collection (不是 Garbage Collector)。

简要引用一下大家所说的。

GC

在 PHP 中,没有任何变量指向这个对象时,这个对象就成为垃圾。PHP 会将其在内存中销毁;这是 PHP 的 垃圾处理机制,防止内存溢出。

当一个 PHP 线程结束时,当前占用的所有内存空间都会被销毁,当前程序中所有对象同时被销毁。垃圾回收进程一般都跟着一个会话而开始运行的。 回收的目的是为了在会话结束后自动销毁删除这些文件。

__destruct /unset

__destruct() 在垃圾对象被回收时执行。 unset 销毁的是指向对象的变量,而不是这个对象。

会话 (Session)

由于 PHP 的工作机制,它并没有一个 daemon 线程来定期的扫描会话信息并判断其是否失效,当一个有效的请求发生时,PHP 会根据全局变量 session.gc_probability 和 session.gc_divisor 的值,来决定是否启用垃圾回收机制。缺省情况下,session.gc_probability=1,session.gc_divisor=100。即,有1%的概率启动垃圾回收机制。

PHP垃圾回收机制的工作就是扫描所有的会话信息,用当前时间减去会话最后被修改的时间,同 session.gc_maxlifetime 参数进行比较,如果生存时间超过 gc_maxlifetime,就清除该会话。

但是,如果你的服务器有多个站点,多个站点时,垃圾回收机制可能会因为无法区分不同站点的会话信息页出错。

此时的解决方案:

1. 修改 session.save_path,或用 session_save_path() 让每个站点的会话信息保存到对应的一个专用目录;
2. 修改垃圾回收机制的启动率。PHP 垃圾回收机制的启动率提高会伴随性能的降低,不推荐。
3. 在代码中判断当前会话的生存时间,用 session_destroy() 清除。

上面所述其实可以作为初级教程。

在版本 5.3 之前,PHP 执行垃圾回收大概可归结为三种情况:

1. 当你告诉它回收时 (如 unset()mysql_free_result() );
2. 当它离开函数时 (函数内的变量不再用时);
3. 脚本处理结束时。

5.3 后,PHP 启用了新的垃圾回收 (GC) 机制。这一点也被写进了 PHP 手册。这里只是作一简单介绍。

1. PHP 变量的基本结构仍然没变,仍然沿用 "zval" 容器,保留了 is_ref 和 refcount 位;
2. 之前版本碰到环形引用 (circular reference) 时会产生内存泄漏,无法消除 (尤其是作为 daemon 运行时);
3. 新的机制创建了一个 root buffer,用来存储所有可能的 roots (zvals);
4. 缺省情况下,新的回收器是打开的 (参数 zend.enable_gc);
5. 缺省配置时,root buffer 可容 10000 个可能的 roots。此值可修改,但要重新编译 PHP (源码 Zend/zend_gc.cGC_ROOT_BUFFER_MAX_ENTRIES 常量)。
6. 可在脚本中决定是否启用新的回收机制: gc_enable(),gc_disable();
7. 可手动清理 root buffer: gc_collect_cycles();
8. 大型脚本时内存性能提升明显,时间约会多耗 7%。

参见 PHP Manual - Features - Garbage Collection.

欢迎大家斧正或补充。

 

回复

留个脚印儿吧.


回复

Copyright © 2010 PHP 架构. All Rights Reserved.