php 5.2 内存管理器
?
自 1997 年以来,Tracy Peterson 担任过 IT 项目经理和 Web 开发人员,并且目前担任 Microsoft 的 MSN Search 的运算程序主管。他目前的工作地点位于旧金山。简介:?了解如何使用 PHP V5.2 中引入的新内存管理器并开始精通于跟踪和监视内存使用情况。这将使您可以在 PHP V5.2 中更加有效地使用更多的内存。
![]()
![]()
![]()
平均分 (共 2 个评分 )
没有 memory_get_peak_usage() 的示例,因为两者十分相似,语法是相同的。但是,对于清单 1 中的示例代码,将只有一个结果,即当时的最高内存使用量。让我们看一看清单 2。
memory_get_peak_usage() 示例将结果保存到名为 function.php 的文件。现在您只能将此文件包含在需要使用它的脚本中。
回页首
动手实践
让我们来看一看使用这些设置的实际示例给我们带来的好处。可能有很多次您都想知道为什么在脚本的末尾没有正确分配内存。原因是因为一些函数本身导致了内存泄露,尤其是在仅使用内置 PHP 函数的情况下。在这里,您将了解如何发现此类问题。并且为了开始进行内存泄露查找的征战,您将创建一个测试 MySQL 数据库,如清单 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)。
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 数据库操作。在运行脚本时,我们注意到一些与内存使用量相关的奇怪行为并需要将其检查出来。为了使用内存管理函数以使我们可以检验发生错误的位置,我们将使用以下代码。
<?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();?>注:按照定义的时间间隔检查当前内存使用量。在下面的输出中,通过显示我们的脚本一直在为函数分配内存,并且在应当释放的时候没有释放内存,从而提供对内存泄露的实际测试,您可以看到每次调用时内存使用量如何增长。
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 全球站点上的 英文原文 。获得产品和技术
使用 IBM 试用软件 构建您的下一个开发项目,这些软件可以通过下载或从 DVD 中获得。