PHP 内存膨胀
PHP Internal Memory Bloat
我需要处理一些大文件,比如每个 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运行一只股票PHP5.3.3.
感谢您的任何见解。
您正在 url 编码。鉴于您的 PDF 基本上是 "random" 二进制垃圾,其中的 MANY 字节是不可打印的。这意味着您将从一个字节 "binary" 字符变为 3+ 字节 URL 编码的字符串。如果您有一个 20 兆的 PDF,那么将其中的文本量增加三倍会使您的内存膨胀也就不足为奇了。请记住,PHP 在工作时必须保留 PDF 的两个副本:原始 "raw" 版本,以及您正在对其进行的任何转换的工作副本。
假设最坏的情况 "every single character gets encoded",您的 20 兆 PDF 将转换为 60 兆 url 编码的字符串,导致 20+60 = 80 兆的峰值使用量,即使该 60 兆编码版本立即被扔掉。
我需要处理一些大文件,比如每个 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运行一只股票PHP5.3.3.
感谢您的任何见解。
您正在 url 编码。鉴于您的 PDF 基本上是 "random" 二进制垃圾,其中的 MANY 字节是不可打印的。这意味着您将从一个字节 "binary" 字符变为 3+ 字节 URL 编码的字符串。如果您有一个 20 兆的 PDF,那么将其中的文本量增加三倍会使您的内存膨胀也就不足为奇了。请记住,PHP 在工作时必须保留 PDF 的两个副本:原始 "raw" 版本,以及您正在对其进行的任何转换的工作副本。
假设最坏的情况 "every single character gets encoded",您的 20 兆 PDF 将转换为 60 兆 url 编码的字符串,导致 20+60 = 80 兆的峰值使用量,即使该 60 兆编码版本立即被扔掉。