PHP内部内存膨胀

时间:2015-03-16 14:53:13

标签: php memory memory-management

我需要处理一些大文件,每个文件说50MB。我发现PHP函数占用了大部分内存。在下面的示例中,PHP函数使用的内存最终是文件大小的四(4)倍。我可以理解文件内存大小的两倍的瞬态使用,但不是四次。最后PHP吹灭了memory_limit。虽然我可以增加PHP memory_limit但它不是一个好的长期解决方案,因为我可能必须处理更大的文件,并且在生产环境中,每个进程的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运行PHP 5.3.3库存。

感谢您的任何见解。

1 个答案:

答案 0 :(得分:2)

您正在进行网址编码。鉴于您的PDF基本上是"随机"二进制垃圾, MANY 的字节是不可打印的。这意味着你要从一个字节"二进制"字符到3+字节的URL编码字符串。鉴于您已经获得了20meg的PDF,因此将文本数量增加三倍会使您的记忆膨胀,这并不奇怪。请记住,PHP必须在其工作时保留两份PDF副本:原始版本" raw"版本,以及您在其上进行的任何转换的工作副本。

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