Ограничение памяти PHP x86 - PullRequest
3 голосов
/ 07 марта 2019

У меня есть файл, который мне нужен для кодирования base64, это 418 МБ, но я продолжаю получать ошибки ограничения памяти.Я установил memory_limit=2048M в своем php.ini, но все еще не могу прочитать его в память как строку base64 с CLI-версией PHP для x86.

PHP Script

<?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 должны иметь возможность использовать больше памяти, чем 1 ГБ.Является ли версия php для x86 жестко запрограммированной на разрешение менее 1 ГБ?Если нет, то почему я получаю ошибку PHP Fatal error: Out of memory, когда мне нужно только 1 ГБ, но у меня есть ограничение 2 ГБ?

Ответы [ 2 ]

2 голосов
/ 07 марта 2019

Теоретически, вы должны иметь возможность выделить до 2 ГБ памяти с помощью процесса x86 в Windows.Однако есть и другие ограничения на то, сколько вы можете выделить.Критически: фрагментация памяти в доступном адресном пространстве.Поскольку base64_encode выделяет необходимую память одновременно, вам потребуется достаточно непрерывного адресного пространства для кодирования всей строки.Скорее всего, вам хватит 64-разрядного адресного пространства, поэтому 64-разрядная версия PHP работает просто отлично.

Для получения дополнительной информации в этом ответе: Максимум Javaпамять в Windows XP

Приложение: В моем тестировании я смог выделить лишь немного больше, чем у вас, но меньшие выделения адресов позволили мне приблизиться к этому пределу в 2 ГБ.

Приложение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);
0 голосов
/ 07 марта 2019

Убедитесь, что у вас достаточно памяти.Изменение ограничения и изменение объема адресуемой памяти (64 бита) не имеет значения, если у вас есть только <1 ГБ свободной системной памяти (или другие ограничения виртуальной памяти, такие как ограничения памяти контейнера) </p>

...