【问题标题】:Understanding memory_get_usage() and pmap了解 memory_get_usage() 和 pmap
【发布时间】:2013-02-14 14:29:57
【问题描述】:

我正在尝试了解一些 php 进程的内存使用情况。我试过同时使用get_memory_usage()pmap,但结果似乎相差了大约一个数量级。我已经尝试过 memory_get_usage()memory_get_usage(true) 以及 memory_get_peak_usage(true),但即使使用 memory_get_peak_usage(true)(所有三个品种中最大的一个),通过 pmap 报告的内容仍然很大。

更具体地说,在我的 php 脚本中每分钟调用一次 memory_get_peak_usage(true) 会返回介于 1.75MB 和 3.5MB 之间的值,而 pmap -d PID 的典型结果是这样的:

...

b7839000       4 r---- 0000000000008000 0ca:00060 libcrypt-2.11.1.so
b783a000       4 rw--- 0000000000009000 0ca:00060 libcrypt-2.11.1.so
b783b000     156 rw--- 0000000000000000 000:00000   [ anon ]
b7864000       8 rw--- 0000000000000000 000:00000   [ anon ]
b7867000      12 r-x-- 0000000000000000 0ca:00060 libgpg-error.so.0.4.0
b786a000       4 r---- 0000000000002000 0ca:00060 libgpg-error.so.0.4.0
b786b000       4 rw--- 0000000000003000 0ca:00060 libgpg-error.so.0.4.0
b786c000       4 r---- 0000000000000000 000:00000   [ anon ]
b786d000      16 rw--- 0000000000000000 000:00000   [ anon ]
b7871000     108 r-x-- 0000000000000000 0ca:00060 ld-2.11.1.so
b788c000       4 r---- 000000000001a000 0ca:00060 ld-2.11.1.so
b788d000       4 rw--- 000000000001b000 0ca:00060 ld-2.11.1.so
bffc7000     136 rw--- 0000000000000000 000:00000   [ stack ]
f57fe000       4 r-x-- 0000000000000000 000:00000   [ anon ]
mapped: 32740K    writeable/private: 13116K    shared: 28K

如果我理解正确,可写/私有数字是最相关的数字,因为它是进程专用的内存。接近 13MB 与 memory_get_peak_usage(true) 报告的数量相差甚远。有人可以解释一下差异吗?

【问题讨论】:

    标签: php pmap


    【解决方案1】:

    我的理解是memory_get_peak_usage() 将返回您的脚本正在使用的内存量。所以这还不包括 PHP 的开销。

    返回分配给 PHP 脚本的内存峰值(以字节为单位)。

    您可以通过编译更少的扩展来减少 PHP 使用的内存。

    PHP 本身是一个大型应用程序,尤其是带有默认扩展的应用程序。我们(作为 php 开发人员)可以编写像 simplexml_load_string() 这样的简单代码并观看魔法发生,但支持这种魔法的代码正在内存中的某个地方运行。查看phpinfo() 的输出将显示安装了多少扩展。 PHP 内部包含将您的 PHP 转换为操作码的代码,然后是执行这些操作码的代码。执行时的每个 PHP 实例都将承担该开销。

    这种内存使用显然不是微不足道的,但在意料之中。如果您必须编写所有代码来处理传入的 GET/POST/FILES 管理 XML、文件和流魔术等。内存使用量会很快增加。

    因此,一种常见的性能技术是删除所有不需要的扩展来缩小可执行文件的大小。对于内存受限的服务器(大多数已加载的服务器),删除一些扩展并将内存使用量从 9 兆降至 7 兆会导致更多 apache 工作人员运行。

    这个开销是不共享的,因为每次执行实际上都是 PHP 执行的一个单独副本。使用线程安全构建可以使用替代方案,但并非所有 PHP 扩展都是线程安全的。

    删除扩展 看看你正在使用的功能。 mysqli_*? xml_*?等等。还看看 PHP 是如何构建的,这是我的配置行:

    Configure Command => './configure' '--with-apxs2=/usr/local/apache2/bin/apxs' '--with-mysql=mysqlnd' '--with-gd' '--enable-soap' '--with-libxml-dir=/usr/lib/' '--with-mysql-sock=/tmp' '--with-tidy' '--with-jpeg-dir=/usr/lib/' '--with-xsl' '--with-curl' '--with-zlib' '--enable-gd-native-ttf' '--with-openssl' '--with-mcrypt' '--with-pdo-mysql=mysqlnd' '--with-mysqli=mysqlnd' '--with-bz2' '--enable-bcmath'

    如果我要减少内存,我会首先使用 ./configure --disable-all 构建 PHP(以删除默认扩展名),然后仅显式添加我正在使用的新扩展名。我不再使用libxml 作为我的代码,也不再使用soap,所以我可以删除这些位。我可以将我的tidy 工作外包给齿轮工和命令行,所以我也会把它拉出来。然后运行我的代码(在这里进行单元测试会很棒)并查看发生了什么问题。使用所需的扩展重新构建 PHP,冲洗并重复。显然不要在生产环境中执行此操作,否则您将拥有 Bad Time

    【讨论】:

    • 我认为您所说的有些道理,但开销不应该由 所有 PHP 进程共享吗?如果我了解 pmap 的输出,则可写/私有仅引用进程独占使用的内存空间。此外,我有大约 40 个这些进程同时运行,使用的总内存(从顶部判断)大约为 275-300MB。这意味着每个进程使用 7-7.5MB。这距离 memory_get_peak_usage() 报告的内容还有很长的路要走。其他内存在哪里使用?在 linux 中,每个使用资源的活动都被标识为一个进程。
    • 对不起,不得不把它分成两个 cmets。只是想补充一下:造成这种“开销”的流程在哪里?如果我运行 ps aux | grep php 我只看到大约 40 个脚本实例。这种开销是否隐藏在其他一些进程中,如果是,是哪些?
    • 包含更多详细信息的扩展帖子
    • 好的,谢谢!现在它变得更有意义了。我仍然不明白为什么 PHP 中没有更多函数可以更全面地了解内存使用情况。所以如果我现在正确理解你,我唯一的选择是用更少的扩展重新编译 php。我不能简单地通过 php.ini 文件注释掉一些扩展(正如一些帖子中所建议的那样)。关于我可以安全删除哪些内容的任何指导?显然,这取决于我的应用程序,但我应该基本上检查 phpinfo() 的输出并开始将明显的输出放在砧板上吗?
    • 包含更多详细信息的扩展帖子。还有:一些有趣的
    【解决方案2】:

    字节与位是 10 的一个因素。因此 1.3 MBytes = 13MBits

    【讨论】:

    • 谢谢。实际上 1 字节 = 8 位,但我仔细检查了这一点。根据 pmap (linux.die.net/man/1/pmap) 的手册,内存使用情况以千字节为单位报告。 memory_get_peak_usage() 以字节为单位输出使用/分配,然后我使用从某处偷来的函数将其转换为兆字节 [$exp = floor(log($bytes) / log(1024)); $bytes/pow(1024, floor($exp));]...在使用 Google 方便的磁盘存储转换器仔细检查了一些值之后。所以我认为这不是罪魁祸首。虽然,差异有多接近令人怀疑。
    • 是的,我没有查找确切的数字,为了简单起见,我总是使用 10 倍数,我记得 :) 以 8 为底,恐怕不是我的强项。将字节转换为 kb 只需执行 bytes/1024 ,然后执行 kb /1024 即可获得 mb ,无需处理过于复杂的问题。得到mb图的方程:)
    • 13116K = 12.8 mb 这比我最初放置的基数 10 更接近基数 8 转换。我会把钱放在一个以位而不是字节返回的数字上,即使它告诉你一些不同的东西!
    猜你喜欢
    • 2013-07-08
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 1970-01-01
    相关资源
    最近更新 更多