Недостаточно памяти, хотя memory_limit достаточно велик

рассмотрим следующий простой PHP-скрипт:

<?php
print memory_get_usage()."<br />";
print ini_get("memory_limit")."<br />";
$file = imagecreatefromjpeg("image.jpg");
?>

Вывод следующий:

109848
120M

Fatal error: Out of memory (allocated 63700992) (tried to allocate 23040 bytes) in /homepages/13/d444038670/htdocs/bilderarchiv/test.php on line 4

Картинка, которую я пытаюсь прочитать, — это большая картина. Однако во второй строке указано, что memory_limit равен 120 МБ, но сценарий умирает с выделением около 64 МБ. Как это может быть? Скрипт отлично работает на другом провайдере, хотя memory_limit там тоже 120M.

0

Решение

Вам не хватает памяти, но есть решение.

Попробуйте запустить это на обоих ваших серверах, чтобы определить, сколько памяти требуется на пиксель изображения:

    <?php
$mem0 = memory_get_usage(true);
$megapix = imagecreatetruecolor(1000,1000);
$mem1 = memory_get_usage(true);
$memdif = $mem1 - $mem0;
$perpixel = $memdif / (1000 * 1000);
echo "<pre>1 million pixel memory test
before imagecreate: $mem0
after imagecreate: $mem1
image memory used: $memdif
bytes per pixel: $perpixel";
?>

Я получил эти результаты:

    1 million pixel memory test  (Linux)
before imagecreate: 524288
after imagecreate: 5505024
image memory used: 4980736
bytes per pixel: 4.980736

1 million pixel memory test (Windows)
before imagecreate: 262144
after imagecreate: 5505024
image memory used: 5242880
bytes per pixel: 5.24288

При размере 5 байт на пиксель для вашего изображения 5760×3240 потребуется 89 МБ.

Чтобы увидеть, требуется ли imagecreatefromjpeg много временной памяти сверх 89 МБ, необходимых для изображения, сравните memory_get_usage с memory_get_peak_usage сразу после загрузки изображения. В моем тестировании не было значительного.

(Старые версии GD использовали 4 байта, я думаю.)

Затем выясните, сколько памяти у вас действительно есть:

    <?php
echo 'memory_limit ??? ', ini_get('memory_limit'), '<br>';
$megs = Array();
for ( $i=0; $i < 1000; ++$i ) {     // try up to 1000MB
$megs[] = str_repeat('*', 1048000);
$mb= round(memory_get_usage(true) / 1024/1024);
echo "$mb ";
flush();
ob_flush();
}
?>

Если вы не получаете никакого вывода, вероятно, происходит буферизация, которую вы не можете отключить, поэтому просто попробуйте другие верхние пределы в for цикл, пока вы не найдете самый большой, который все еще работает.

Одно решение

Я давно отказался от GD для уменьшения больших изображений в формате JPEG и вместо этого использовал ImageMagick. Если вы выполняете его из PHP, это отдельный процесс, поэтому ограничение памяти PHP больше не применяется. Конечно, в конечном итоге существует ограничение памяти, но вы можете указать ImageMagick максимальный объем используемой памяти.

(Я также получил изображения лучшего качества, чем с GD.)

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]