php 5.2 内存管理器
?
自 1997 年以来,Tracy Peterson 担任过 IT 项目经理和 Web 开发人员,并且目前担任 Microsoft 的 MSN Search 的运算程序主管。他目前的工作地点位于旧金山。简介:?了解如何使用 PHP V5.2 中引入的新内存管理器并开始精通于跟踪和监视内存使用情况。这将使您可以在 PHP V5.2 中更加有效地使用更多的内存。
![]()
![]()
![]()
平均分 (共 2 个评分 )
没有 memory_get_peak_usage() 的示例,因为两者十分相似,语法是相同的。但是,对于清单 1 中的示例代码,将只有一个结果,即当时的最高内存使用量。让我们看一看清单 2。
清单 2.
memory_get_peak_usage() 示例将结果保存到名为 function.php 的文件。现在您只能将此文件包含在需要使用它的脚本中。
回页首
动手实践
让我们来看一看使用这些设置的实际示例给我们带来的好处。可能有很多次您都想知道为什么在脚本的末尾没有正确分配内存。原因是因为一些函数本身导致了内存泄露,尤其是在仅使用内置 PHP 函数的情况下。在这里,您将了解如何发现此类问题。并且为了开始进行内存泄露查找的征战,您将创建一个测试 MySQL 数据库,如清单 4 所示。
清单 4. 创建测试数据库
mysql> create database memory_test;mysql> use memory_test;mysql> create table leak_test ( id int not null primary key auto_increment, data varchar(255) not null default '');mysql> insert into leak_test (data) values ("data1"),("data 2"), ("data 3"),("data 4"),("data 5"),("data6"),("data 7"), ("data 8"),("data 9"),("data 10");这将创建一个带有 ID 字段和数据字段的简单表。
在下一张清单中,想象我们坚韧不拔的程序员正在执行一些 MySQL 函数,特别是使用 mysql_query() 将结果应用到变量。当他这样做时,他将注意到即使调用 mysql_free_result(),一些内存也不会被释放,导致内存使用量随着 Apache 进程不断增长(参见清单 5)。
清单 5. 内存泄露检测示例
for ( $x=0; $x<300; $x++ ) { $db = mysql_connect("localhost", "root", "test"); mysql_select_db("test"); $sql = "SELECT data FROM test"; $result = mysql_query($sql); // The operation suspected of leaking mysql_free_result($result); mysql_close($db); }清单 5 是在任何位置都可能使用的简单 MySQL 数据库操作。在运行脚本时,我们注意到一些与内存使用量相关的奇怪行为并需要将其检查出来。为了使用内存管理函数以使我们可以检验发生错误的位置,我们将使用以下代码。
清单 6. 定标查找错误的示例
<?phpif( !function_exists('memory_get_usage') ){ include('function.php');}echo "At the start we're using (in bytes): ", memory_get_usage() , "\n<br>"; $db = mysql_connect("localhost", "user", "password");mysql_select_db("memory_test");echo "After connecting, we're using (in bytes): ", memory_get_usage(),"\n<br>"; for ( $x=0; $x<10; $x++ ) { $sql = "SELECT data FROM leak_test WHERE id='".$x."'"; $result = mysql_query($sql); // The operation // suspected of leaking. echo "After query #$x, we're using (in bytes): ", memory_get_usage(), "\n<br>"; mysql_free_result($result); echo "After freeing result $x, we're using (in bytes): ", memory_get_usage(), "\n<br>";} mysql_close($db);echo "After closing the connection, we're using (in bytes): ", memory_get_usage(), "\n<br>";echo "Peak memory usage for the script (in bytes):". memory_get_peak_usage();?>注:按照定义的时间间隔检查当前内存使用量。在下面的输出中,通过显示我们的脚本一直在为函数分配内存,并且在应当释放的时候没有释放内存,从而提供对内存泄露的实际测试,您可以看到每次调用时内存使用量如何增长。
清单 7. 测试脚本输出
At the start we're using (in bytes): 63216After connecting, we're using (in bytes): 64436After query #0, we're using (in bytes): 64760After freeing result 0, we're using (in bytes): 64828After query #1, we're using (in bytes): 65004After freeing result 1, we're using (in bytes): 65080After query #2, we're using (in bytes): 65160After freeing result 2, we're using (in bytes): 65204After query #3, we're using (in bytes): 65284After freeing result 3, we're using (in bytes): 65328After query #4, we're using (in bytes): 65408After freeing result 4, we're using (in bytes): 65452After query #5, we're using (in bytes): 65532After freeing result 5, we're using (in bytes): 65576After query #6, we're using (in bytes): 65656After freeing result 6, we're using (in bytes): 65700After query #7, we're using (in bytes): 65780After freeing result 7, we're using (in bytes): 65824After query #8, we're using (in bytes): 65904After freeing result 8, we're using (in bytes): 65948After query #9, we're using (in bytes): 66028After freeing result 9, we're using (in bytes): 66072After closing the connection, we're using (in bytes): 65108Peak memory usage for the script (in bytes): 88748
我们所做的操作是发现了执行脚本时出现的一些可疑操作,然后调整脚本使其给我们提供一些可理解的反馈。我们再次运行了脚本,在每次迭代期间使用 memory_get_usage() 查看内存使用量的变化。根据分配的内存值的增长情况,暗示了我们用脚本在某个位置建立了一个漏洞。由于 mysql_free_result() 函数不释放内存,因此我们可以认为 mysql_query() 并未正确分配内存。
回页首
结束语
PHP V5.2 版包括一些优秀的新工具,可以帮助您更好地洞察脚本的系统内存分配情况,以及重新全面控制内存管理的精确调整。当得到有效使用时,新内存管理工具将支持您的调试工作,从而重新获得一些系统资源。
参考资料
学习
您可以参阅本文在 developerWorks 全球站点上的 英文原文 。阅读 PHP V5.2 发行说明。
“How to Manage Memory in PHP” 是一篇关于 PHP 内存管理编程实践的优秀文章。
Zend Developer Zone 中有很多针对内存管理器函数的文档。
访问 PHP.net 获得 PHP 文档。
文章 “A step-by-step how-to guide to install, configure, and test a Linux, Apache, Informix, and PHP server” 包含一个关于为 Linux 编译 PHP 解析程序的部分。
查阅实际示例产生的 错误报告。
在 “PHP V5 迁移指南” 中了解如何将在 PHP V4 中开发的代码迁移到 V5。
要获得学习用 PHP 进行编程的教程,请查阅 developerWorks 的 “学习 PHP” 系列。
Planet PHP 是 PHP 开发者社区新闻资源。
PHP.net 是 PHP 开发者的资源。
查阅 “PHP 推荐读物列表”。
浏览 developerWorks 上的所有 PHP 文章 和 PHP 教程。
查阅 IBM developerWorks 的 PHP 项目资源中心 扩展 PHP 技巧。
收听针对软件开发人员的有趣访谈和讨论,一定要访问 developerWorks podcast。
随时关注 developerWorks 的 技术事件和网络广播。
查阅最近将在全球举办的面向 IBM 开放源码开发人员的研讨会、交易展览、网络广播和其他 活动。
访问 developerWorks 开源软件技术专区,获得丰富的 how-to 信息、工具和项目更新,帮助您用开放源码技术进行开发,并与 IBM 产品结合使用。
访问 Safari 在线书店 浏览开放源码技术的各种参考资料。
获得产品和技术
使用 IBM 试用软件 构建您的下一个开发项目,这些软件可以通过下载或从 DVD 中获得。