【问题标题】:PHP Garbage Collector statisticsPHP 垃圾收集器统计
【发布时间】:2012-03-13 09:03:43
【问题描述】:

我正在做一些 PHP 内存基准测试,我想获得垃圾收集器的静态数据。

我已经按照官方文档中的这个教程:http://www.php.net/manual/en/features.gc.performance-considerations.php

我已经通过使用这个 CFLAGS 环境变量重新编译 PHP 复制了所描述的确切过程:

export CFLAGS=-DGC_BENCH=1
./config.nice
make clean
make
make install

我已经在 Debian Squeeze 6.0.4 64 位上使用 PHP 5.3.9 :http://fr.php.net/get/php-5.3.9.tar.bz2/from/a/mirror 做到了这一点。

然后我尝试在命令行中执行他们提供的示例脚本php gc.php

<?php
class Foo
{
    public $var = '3.1415962654';
}

for ( $i = 0; $i <= 1000000; $i++ )
{
    $a = new Foo;
    $a->self = $a;
}

echo memory_get_peak_usage(), "\n";
?>

正如他们所说,这应该显示在脚本的末尾,附加 gc 统计信息,例如:

GC Statistics
-------------
Runs:               110
Collected:          2072204
Root buffer length: 0
Root buffer peak:   10000

      Possible            Remove from  Marked
        Root    Buffered     buffer     grey
      --------  --------  -----------  ------
ZVAL   7175487   1491291    1241690   3611871
ZOBJ  28506264   1527980     677581   1025731

事实上,这个 gc 统计信息并没有显示出来。 看起来用这个 CFLAGS 编译 PHP 并没有做任何事情。

我错过了什么吗?

【问题讨论】:

  • 你能告诉我们实际显示的是什么吗?
  • 这个脚本只显示 PHP 分配的内存峰值(由 memory_get_peak_usage() 函数完成)。在我的情况下8012000.
  • 我注意到你做了make cleanmake,你做了make install吗?
  • 是的,我制作了make install。编辑程序。
  • 有任何与memory_get_peak_usage 调用相关的错误日志条目吗?是否有任何所需的较低级别的库(即 libxml)?

标签: php memory memory-management garbage-collection


【解决方案1】:

我在这里有一个预感,因为我没有确认这一点,但是,通过阅读您提供的 GC 链接上的文本,我没有得到memory_get_peak_usage() 应该返回基于编译 PHP 的附加信息的印象带有DGC_BENCH 标志。手册说它返回一个 int,所以我怀疑它总是返回一个 int。

然而它做了说的是:

当您使用新建的 PHP 再次运行上述示例代码时 二进制文件,您将在 PHP 完成后看到以下内容 执行:

这不是很清楚,但我的印象是额外的 GC 详细信息将打印到 stdoutstderr 而不是返回到 memory_get_peak_usage() 或作为附加输出打印到您的 PHP 脚本.

尝试从命令行调用新建的 PHP 可执行文件,看看脚本完成时是否将 GC 信息打印到控制台。

你可以尝试这样称呼它:/path/to/custom/php testfile.php

如果您将 PHP 作为 Apache 模块或 FastCGI 处理程序运行,我不确定输出此信息是否有意义,因此我怀疑您可能只能通过从控制台调用脚本来查看它,但我可能会完全错了。

更新:

我已检查以确保 GC_BENCH 编译标志仍然处于活动状态,并且确实如此。

Zend/zend.c


905 #if GC_BENCH
906     fprintf(stderr, "GC Statistics\n");
907     fprintf(stderr, "-------------\n");
908     fprintf(stderr, "Runs:               %d\n", GC_G(gc_runs));
909     fprintf(stderr, "Collected:          %d\n", GC_G(collected));
910     fprintf(stderr, "Root buffer length: %d\n", GC_G(root_buf_length));
911     fprintf(stderr, "Root buffer peak:   %d\n\n", GC_G(root_buf_peak));
912     fprintf(stderr, "      Possible            Remove from  Marked\n");
913     fprintf(stderr, "        Root    Buffered     buffer     grey\n");
914     fprintf(stderr, "      --------  --------  -----------  ------\n");
915     fprintf(stderr, "ZVAL  %8d  %8d  %9d  %8d\n", GC_G(zval_possible_root), GC_G(zval_buffered), GC_G(zval_remove_from_buffer), GC_G(zval_marked_grey));
916     fprintf(stderr, "ZOBJ  %8d  %8d  %9d  %8d\n", GC_G(zobj_possible_root), GC_G(zobj_buffered), GC_G(zobj_remove_from_buffer), GC_G(zobj_marked_grey));
917 #endif

接下来,我为 Apache2 和 CLI 编译了 PHP 5.3.9。在决定安装测试版之前,我从控制台运行了新的 PHP CLI 应用程序:

./sapi/cli/php -v

PHP 5.3.9 (cli) (built: Feb 22 2012 19:03:02) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
GC Statistics
-------------
Runs:               0
Collected:          0
Root buffer length: 0
Root buffer peak:   7

      Possible            Remove from  Marked
        Root    Buffered     buffer     grey
      --------  --------  -----------  ------
ZVAL        15         7          7         0
ZOBJ         0         0          0         0

即使我没有调用 PHP,它也有 GC 输出。接下来我 grep'd libphp5.so 并看到它确实编译了 GC 统计信息位,所以我决定实时安装它并从 Apache 拨打电话。浏览器、error_log、access_log 或任何其他日志文件中没有 GC 输出。

现在有趣的部分,我创建了一个 test.php 文件,它输出一个字符串并创建一个释放一些变量...

root@vm:/php539# php test.php
This is a test

root@vm:/php539# php < test.php
This is a test
GC Statistics
-------------
Runs:               0
Collected:          0
Root buffer length: 0
Root buffer peak:   7

      Possible            Remove from  Marked
        Root    Buffered     buffer     grey
      --------  --------  -----------  ------
ZVAL        16         7          7         0
ZOBJ         0         0          0         0

root@vm:php539# 

结论:

当使用GC_BENCH 选项编译PHP 时,当从浏览器调用时,或使用-f 选项解析PHP 文件或传递要解析的文件名时,您将无法访问基准信息。如果您在交互模式下调用 php 或通过 PHP 从stdin 读取脚本来执行脚本,您将获得基准信息。

【讨论】:

  • 我正在从命令行运行脚本并尝试使用 apache。仅显示memory_get_peak_usage()。我同意你的观点,在这一点上文档不是很清楚,我没有找到任何进一步的信息。
  • 非常感谢!它通过调用像php &lt; script.php 这样的脚本来工作。之前,我将基准测试的输出存储在一个文本文件中,例如:php script.php &gt;&gt; bench.txt,但这不会存储新的垃圾收集器信息。怎么可能存储它们?
  • 尝试这样调用它php &lt; script.php &amp;&gt; bench.txt 将您的脚本输出和 PHP 的基准信息重定向到 bench.txt
  • '&amp;&gt;' 将 stdout 和 stderr 都重定向到文件。请参阅Redirection 上的这篇维基百科文章或名为 All about redirection 的有用文章
  • 忘了提到 &lt; 读取 script.php 并通过 stdin 将其提供给 PHP,因此调用 php &lt; script.php 与调用 php 然后粘贴 script.php 的内容相同其次是^D
猜你喜欢
  • 2016-04-03
  • 1970-01-01
  • 1970-01-01
  • 2021-05-25
  • 2011-08-13
  • 2018-12-30
  • 1970-01-01
  • 1970-01-01
  • 2011-12-11
相关资源
最近更新 更多