我需要处理一些大文件,每个文件说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库存。
感谢您的任何见解。
答案 0 :(得分:2)
您正在进行网址编码。鉴于您的PDF基本上是"随机"二进制垃圾, MANY 的字节是不可打印的。这意味着你要从一个字节"二进制"字符到3+字节的URL编码字符串。鉴于您已经获得了20meg的PDF,因此将文本数量增加三倍会使您的记忆膨胀,这并不奇怪。请记住,PHP必须在其工作时保留两份PDF副本:原始版本" raw"版本,以及您在其上进行的任何转换的工作副本。
假设最坏情况"每个字符都被编码",您的20meg PDF将转换为60meg url编码的字符串,导致20 + 60 = 80 meg的峰值使用,即使60meg编码版本立即被抛弃。