读书人

php 5.2 内存储器管理器

发布时间: 2012-12-23 11:28:15 作者: rapoo

php 5.2 内存管理器

?

自 1997 年以来,Tracy Peterson 担任过 IT 项目经理和 Web 开发人员,并且目前担任 Microsoft 的 MSN Search 的运算程序主管。他目前的工作地点位于旧金山。

简介:?了解如何使用 PHP V5.2 中引入的新内存管理器并开始精通于跟踪和监视内存使用情况。这将使您可以在 PHP V5.2 中更加有效地使用更多的内存。

php 5.2 内存储器管理器php 5.2 内存储器管理器php 5.2 内存储器管理器php 5.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 中获得。

读书人网 >PHP

热点推荐