Страница 1 из 1

Опять про загрузку фото и "Out of memory"

СообщениеДобавлено: 20 мар 2013, 17:32
Cornil
Нашел в логах ошибки при загрузке картинок:
[20-Mar-2013 16:01:34] PHP Fatal error: Out of memory (allocated 65011712) (tried to allocate 13056 bytes) in .......... /protected/modules/images/components/CImageHandler.php on line 175

Хостинг "Агава" на моем тарифе предполагает 64М памяти. К сожалению, скрипту этого мало, а переходить на другой тариф не хочется. Как результат: фото более 800Кб не загружаются.

Решение:
1. открываем /protected/modules/images/components/CImageHandler.php
ищем эту самую строчку - 175
Код: Выделить всё

        $this
->image = imagecreatetruecolor($this->width, $this->height);
        $this->preserveTransparency($this->image);
        imagecopy($this->image, $image['image'], 0, 0, 0, 0, $this->width, $this->height);
 


В этом месте съедается кусок памяти размером с картинку. Подозреваю, что тут GD еще что-то обрабатывает, кушает большой ресурс и вызывает Fatal, т.к. echo memory_get_usage(); показывает около 9,5Мб до и 12Мб после обработки на машине с бОльшим лимитом памяти.
Как я ни вкуривал этот код, так и не смог понять, зачем разработчик копирует содержимое картинки таким путем.
Возможно, т.к. $this->preserveTransparency, судя по названию, работает с прозрачностью, то здесь это нужно для прозрачных png. Поскольку к нашим делам все это не имеет отношения, закомментировал и его тоже.
В результате, сделал так:
Код: Выделить всё

$this
->image = $image['image'];
//        $this->image = imagecreatetruecolor($this->width, $this->height);
//        $this->preserveTransparency($this->image);
//        imagecopy($this->image, $image['image'], 0, 0, 0, 0, $this->width, $this->height);
 

Расход памяти резко уменьшился :) А главное - работает :)

P.S. Наткнулся на следующие ограничения при памяти 64М:
-- Максимальный размер файла: 5 Мб (на сервере разрешено 8Мб).
-- Максимальное разрешение снимка 10 МПикс (~ 3600x2700).
иначе - ошибка.

Re: Опять про загрузку фото и "Out of memory"

СообщениеДобавлено: 02 апр 2013, 08:33
Koduc
Спасибо за информацию!
Когда CImageHandler не было - всёравно на некоторых хостингах бывала ошибка про нехватку памяти. Где-то это решалось на сторону хостинга (обновляли библиотеку GD), а где-то приходилось в код "костыли" вставлять.. Так что всякое бывает.

Re: Опять про загрузку фото и "Out of memory"

СообщениеДобавлено: 03 апр 2013, 10:10
Cornil
Сейчас у меня проблема возникает здесь:
imagecreatefromjpeg(...);
imagecreatefrompng(...);
и т.п.

Т.е., когда GD создает холст большого размера. Предполагаю, можно рассуждать примерно так (чисто предположения):
1. на момент выполнения команды GD имеем (64-9,5)=54,5Мб свободной памяти
2. при выполнении imagecreatefromjpeg, GD сперва выделяет под пустой холст память в несжатом виде типа .bmp/32bit (для 3600x2700 = 37Мб). Остается 17,5 Мб.
3. в тот же момент времени GD создает оптимизированную структуру холста (12-9,5)=2,5Мб. Остается 15Мб.
4. вероятно, последние 15Мб уходят на сжатие и оптимизацию (ну или загрузку фото, не помню какой там код). Думаю, как раз тут у хостера и "вылетают пробки" от перегрузки.

Так что проблема не в движке и не в скрипте загрузки, а именно в GD, т.к. по другому фотки не обработать, ИМХО....
Кстати, bmp/24bit, в отличие от 32bit, "кушает" для 3600x2700 = 27,8Мб. Т.е. почти на 10Мб (27%) меньше, при незначительной потере в качестве. Хотя это сильно не поможет.

Re: Опять про загрузку фото и "Out of memory"

СообщениеДобавлено: 03 апр 2013, 16:21
Koduc
Ход ваших мыслей совершенно верен. Основная память съедается при создании несжатого холста.

Плюс еще уточню из разряда "невероятно, но факт" - 64-битные системы память кушают ощутимо больше, чем 32-битные. Так что особенно если это всё крутится на x64 - дело еще усугубляется.

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

Плюс на сайте могут еще находится люди, что может "съедать" память, доступную web-серверу, плюс утечки памяти откуда их не ждешь..
Например, mysql 5.1."не помню версию" на одном из серверов постоянно истекает памятью. Приходится раз в пару дней рестартовать демона, иначе система начинает свопить и тормозить.. Апач, впрочем, тоже иногда может таким страдать.

Плюс хостеры могут делать "оверселл" и на деле памяти может оказываться меньше купленного.