PHP x86内存限制

时间:2019-03-07 16:04:12

标签: php memory x86 64-bit

我有一个需要418 MB进行base64编码的文件,但是我不断收到内存限制错误。我已经在php.ini中设置了memory_limit=2048M,但是仍然无法通过x86 CLI版本的PHP将它作为base64字符串读入内存。

PHP脚本

<?php

echo "\r\n";
echo "\r\nMemory Usage\r\n" . memory_get_usage(false) . " Bytes\r\nReal " . memory_get_usage(true) . " Bytes\r\n";
echo "\r\nPeak Memory Usage\r\n" . memory_get_peak_usage(false). " Bytes\r\nReal " . memory_get_peak_usage(true) . " Bytes\r\n";
echo "\r\nMemory Limit\r\n" . ini_get('memory_limit') . "\r\n";

$file = file_get_contents('C:\Path\To\File');

echo "\r\n";
echo "\r\nMemory Usage\r\n" . memory_get_usage(false) . " Bytes\r\nReal " . memory_get_usage(true) . " Bytes\r\n";
echo "\r\nPeak Memory Usage\r\n" . memory_get_peak_usage(false). " Bytes\r\nReal " . memory_get_peak_usage(true) . " Bytes\r\n";
echo "\r\nMemory Limit\r\n" . ini_get('memory_limit') . "\r\n";

$encodedFile = base64_encode($file);

echo "\r\n";
echo "\r\nMemory Usage\r\n" . memory_get_usage(false) . " Bytes\r\nReal " . memory_get_usage(true) . " Bytes\r\n";
echo "\r\nPeak Memory Usage\r\n" . memory_get_peak_usage(false). " Bytes\r\nReal " . memory_get_peak_usage(true) . " Bytes\r\n";
echo "\r\nMemory Limit\r\n" . ini_get('memory_limit') . "\r\n";

?>

运行该脚本会产生以下结果。

PS C:\> php .\MemoryIssueTest.php


Memory Usage
382184 Bytes
Real 2097152 Bytes

Peak Memory Usage
422256 Bytes
Real 2097152 Bytes

Memory Limit
2048M


Memory Usage
447075680 Bytes
Real 448790528 Bytes

Peak Memory Usage
447084280 Bytes
Real 448790528 Bytes

Memory Limit
2048M

VirtualAlloc() failed: [0x00000008] Not enough memory resources are available to process this command.


VirtualAlloc() failed: [0x00000008] Not enough memory resources are available to process this command.

PHP Fatal error:  Out of memory (allocated 448790528) (tried to allocate 593015064 bytes) in C:\MemoryIssueTest.php on line 14
PHP Stack trace:
PHP   1. {main}() C:\MemoryIssueTest.php:0
PHP   2. base64_encode() C:\MemoryIssueTest.php:14

Fatal error: Out of memory (allocated 448790528) (tried to allocate 593015064 bytes) in C:\MemoryIssueTest.php on line 14

Call Stack:
    0.4046     382152   1. {main}() C:\MemoryIssueTest.php:0
   33.4669  447075680   2. base64_encode() C:\MemoryIssueTest.php:14

升级到64位版本的PHP后,我从同一脚本中获得以下结果。

PS C:\> php .\MemoryIssueTest.php


Memory Usage
402088 Bytes
Real 2097152 Bytes

Peak Memory Usage
444160 Bytes
Real 2097152 Bytes

Memory Limit
2048M


Memory Usage
440804144 Bytes
Real 442499072 Bytes

Peak Memory Usage
440812824 Bytes
Real 442499072 Bytes

Memory Limit
2048M


Memory Usage
1025909576 Bytes
Real 1027604480 Bytes

Peak Memory Usage
1025909760 Bytes
Real 1027604480 Bytes

Memory Limit
2048M

据我了解,x86应用程序应该能够消耗超过1GB的内存。是否将x86版本的php硬编码为仅允许小于1GB?如果没有,当我只需要消耗1GB但有2GB的限制时,为什么会出现PHP Fatal error: Out of memory错误?

2 个答案:

答案 0 :(得分:2)

从理论上讲,您应该能够在Windows上使用x86进程分配最多2GB的内存。但是,在分配多少方面还有其他限制。重要的是:可用地址空间中的内存碎片。由于base64_encode一次分配了所有需要的内存,因此您将需要足够的连续地址空间来编码整个字符串。您更有可能拥有64位地址空间,这就是为什么64位版本的PHP运行得很好的原因。

有关此答案的更多信息:Java maximum memory on Windows XP

附录:在我的测试中,我只能分配比您略多的地址,但是较小的地址分配使我更接近了2GB的限制。

附录2:如果您绝对需要使用32位版本并且要对文件进行编码,则可以通过3字节的倍数进行编码来解决此问题,然后将它们串联起来。

// Example, from memory string to file.
$current_position = 0;
$length = strlen($file);
$outputfile = fopen('testoutput.txt', 'w');
while($current_position < $length) {
  fwrite($outputfile, base64_encode(substr($file, $current_position, 60000)));
  $current_position += 60000;
}
fclose($outputfile);

或者一路走来,从一个文件到另一个文件,这会分配很少的内存:

$inputfile = fopen('test.mp4', 'rb');
$outputfile = fopen('testoutput2.txt', 'w');
while( ($str = fread($inputfile, 61440)) !== false ) {
  if($str === '') {
    break;
  }
  fwrite($outputfile, base64_encode($str));
  $current_position += 61440;
}
fclose($outputfile);

答案 1 :(得分:0)

检查是否有足够的内存。如果您只有<1gb的可用系统内存(或其他虚拟内存限制,例如容器内存限制),则更改限制和更改可寻址内存(64位)的数量将无关紧要