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

Пишите о найденных ошибках в эту тему

Модераторы: Xpycm, Koduc

Правила форума
ВНИМАНИЕ! Форум не является средством гарантированной поддержки клиентов и пользователей. Поэтому на быстрый ответ тут рассчитывать не нужно, как и на ответ вообще. Сотрудники отвечают по мере своих возможностей.

На форуме действует ограничение в 3 сообщения / сутки.
Если Вы хотите сказать "спасибо", то воспользуйтесь функцией "Повысить репутацию" - зелёная иконка "плюс" под ником ответившего.

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

Сообщение Cornil » 20 мар 2013, 17:32

Нашел в логах ошибки при загрузке картинок:
[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).
иначе - ошибка.
Cornil
Гражданин
Гражданин
 
Сообщения: 77
Зарегистрирован: 18 фев 2013, 22:08
Очки репутации: 14

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

Сообщение Koduc » 02 апр 2013, 08:33

Спасибо за информацию!
Когда CImageHandler не было - всёравно на некоторых хостингах бывала ошибка про нехватку памяти. Где-то это решалось на сторону хостинга (обновляли библиотеку GD), а где-то приходилось в код "костыли" вставлять.. Так что всякое бывает.
-- Меньше знаешь - крепче спишь --
Аватара пользователя
Koduc
Ведущий разработчик
Ведущий разработчик
 
Сообщения: 902
Зарегистрирован: 28 дек 2011, 09:11
Очки репутации: 20

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

Сообщение Cornil » 03 апр 2013, 10:10

Сейчас у меня проблема возникает здесь:
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%) меньше, при незначительной потере в качестве. Хотя это сильно не поможет.
Cornil
Гражданин
Гражданин
 
Сообщения: 77
Зарегистрирован: 18 фев 2013, 22:08
Очки репутации: 14

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

Сообщение Koduc » 03 апр 2013, 16:21

Ход ваших мыслей совершенно верен. Основная память съедается при создании несжатого холста.

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

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

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

Плюс хостеры могут делать "оверселл" и на деле памяти может оказываться меньше купленного.
-- Меньше знаешь - крепче спишь --
Аватара пользователя
Koduc
Ведущий разработчик
Ведущий разработчик
 
Сообщения: 902
Зарегистрирован: 28 дек 2011, 09:11
Очки репутации: 20


Вернуться в Ошибки

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 27

cron