PHP内存膨胀

PHP内存膨胀,php,memory,memory-management,Php,Memory,Memory Management,我需要处理一些大文件,比如每个50MB。我发现PHP函数占用了大量内存。在下面的示例中,PHP函数使用的内存是文件大小的四(4)倍。我可以理解两倍于文件内存大小的短暂使用,但不能理解四倍。最后PHP打破了内存限制。虽然我可以增加PHP内存限制,但这不是一个好的长期解决方案,因为我可能需要处理更大的文件,并且在生产环境中,每个进程占用的PHP内存达400MB是不可取的 代码: $buf = ''; report_memory(__LINE__); $buf = file_get_contents

我需要处理一些大文件,比如每个50MB。我发现PHP函数占用了大量内存。在下面的示例中,PHP函数使用的内存是文件大小的四(4)倍。我可以理解两倍于文件内存大小的短暂使用,但不能理解四倍。最后PHP打破了内存限制。虽然我可以增加PHP内存限制,但这不是一个好的长期解决方案,因为我可能需要处理更大的文件,并且在生产环境中,每个进程占用的PHP内存达400MB是不可取的

代码:
$buf = '';
report_memory(__LINE__);

$buf = file_get_contents('./20MB.pdf');
report_memory(__LINE__);

base64_encode($buf);
report_memory(__LINE__);

urlencode($buf);
report_memory(__LINE__);

function report_memory($line=0) {
    echo 'Line: ' . str_pad($line,3) . '  ';
    echo 'Mem: '  . str_pad(intval(memory_get_usage()/1024     ) . 'K',8) . '  ';
    echo 'Peak: ' . str_pad(intval(memory_get_peak_usage()/1024) . 'K',8) . '  ';
    echo "\n";
}
输出:

Line: 4    Mem: 622K      Peak: 627K
Line: 7    Mem: 21056K    Peak: 21074K
Line: 10   Mem: 21056K    Peak: 48302K
Line: 13   Mem: 21056K    Peak: 82358K
可以看到,对于20MB的文件,当前内存使用量徘徊在21MB,而峰值内存使用量则跃升到82MB

示例中使用的PHP函数是任意的,我可以轻松地在str_replace、is_string、gettype等中进行交换,并获得相同的结果

问题是如何阻止PHP这样做

该环境是CentOS 6.6,运行一个股票PHP5.3.3


感谢您的帮助。

您正在进行url编码。鉴于PDF基本上是“随机”二进制垃圾,其中的许多字节是不可打印的。这意味着您将从一个字节的“二进制”字符变为3+字节的URL编码字符串。如果你有一个20mg的PDF文件,那么将其中的文本量增加三倍会使你的记忆膨胀也就不足为奇了。请记住,PHP在工作时必须保留PDF的两个副本:原始“原始”版本和对其进行任何转换的工作副本


假设最坏的情况是“每个字符都被编码”,您的20meg PDF将转换为60meg url编码字符串,导致20+60=80meg峰值使用量,即使60meg编码版本立即被丢弃

假设您正在运行标准的apache+php交换到nginx+phpfpm,这将减少内存使用。或者,您也可以切换到nginx+hvm,这将使用更多内存,但进程将更快地完成。如果您通过CLI使用它,那么除了定制php编译以充分利用它之外,您可以做的事情不多,但这不会产生巨大的差异从
$buf
创建数据的base64编码副本以返回到脚本(这是您调用该函数时实际告诉PHP要做的),然后它必须将该副本存储在内存中,以便可以返回到脚本中。。。。你到底希望PHP做什么?我需要把它放在PHP的上下文中,PHP fpm和hhvm不是一个选项。我不知道nginx将如何解决PHP内存问题。为了解决这个PHP内存问题,您建议PHP的编译时选项是什么?因为内存正在再次下降到一个相当一致的级别,这些函数似乎更可能只需要大量内存,而不是某种内存泄漏。@Mark Baker:正如OP中所述,我可以理解,PHP将在处理字符串时复制字符串,有效地将内存使用率提高了一倍。这不是问题所在。内存使用率是问题的四倍。再说一次,使用哪些PHP函数,base64_编码还是其他,都无关紧要。这是一个更广泛的PHP内部问题。非常感谢。