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

Для Windows 10.03.2019
Для Windows

Библиотека поддержки DNS Lookup.

  • Number4 дополнения к математической части.
  • Win32Build готовые библиотеки, необходимые для сборки.
  • Mssql библиотеки для программинга под MS SQL 6.5.
  • CVS клиент для CVS repository нужен для того, чтобы скачать исходный код PHP.
  • Также понадобятся файлы от MSVC++ 6.0 (только для пользователей MSVC++ 5.0)

    • OLE - положить в VC\include. Необходимы для СОМ поддержки.
    • HTTP - переименовать имеющиеся в *.hold, а новые положить в VC\include. Необходимы для сборки ISAPI фильтра.

    ИНСТАЛЯЦИЯ

    Инсталируем пакет CYGWIN, например в каталог C:\Program Files\Cygnus, в NT надо завести переменную среды CYGWIN со значением %SystemDrive%\Program Files\cygnus\cygwin-b20

    Делается это так: Идем в Start->Settings->Control Pannel запускаем ярлык System, выбираем карточку Environment на ней щелкаемся на окно System variables внизу две строки Variable и Value, в строке Variable пишем CYGWIN а в строке Value %SystemDrive%\Program Files\cygnus\cygwin-b20 И жмем Set а потом Apply.

    Cоздаем от корня каталог Tmp на системном диске и точно так же добавляем переменную TMP со значением %SystemDrive%\Tmp. Добавляем в переменную path путь %SystemDrive%\Tmp

    Жмем Apply и OK. После этого необходимо перегрузиться.

    Разворачиваем архив win32build.zip в каталог, например C:\Win32build

    Запускаем среду MSVC++ 5.0 идем в Tools->Options на карточку Directory и добавляем в разделы

    • Include
    • Libraries

    следующие пути соответственно:

    • C:\Program Files\cygnus\cygwin-b20\H-i586-cygwin32\bin
    • С:\Win32Build\include
    • C:\Win32Build\lib

    Разворачиваем Bindlib_w32.zip в каталог, например C:\Bindlib, ищем в нем файл проекта bindlib.dsp и собираем его из среды MSVC. В каталоге C:\Bindlib\Debug появится resolve.lib, ее надо переписать в каталог C:\Win32Build\Lib поверх старой.

    СБОРКА

    Топаем в каталог C:\Php4\Tsrm и собираем TSRM.dsp, после сборки в каталоге C:\Php4\Tsrm\Debug появится Tsrm.lib, скопировать ее в каталог C:\Win32Build\Lib.

    Переходим в каталог C:\Php4\Zend, открываем проект ZendTS.dsp и собираем его, после сборки в каталоге C:\Php4\Zend\Debug появится библиотека ZendTS.lib, копируем ее в каталог C:\Win32Build\Lib.

    Переходим в каталог C:\Php4 и открываем проект php4ts.dsp. В нем 4 проекта сначала собираем php4ts (не забудьте установить активный проект Project->Set Active Project->php4ts).

    После сборки в каталоге C:\Php4\Debug появится файл php4ts.lib, php4ts.dll, php.exe. Php4ts.lib опять копируем в C:\Win32Build\Lib. Эта библиотека нужна для сборки внешних модулей php, например для модуля поддержки mssql.

    Делаем активным проект php4isapi и собираем его. В каталоге C:\php4\sapi\isapi\debug будет лежать php4isapi.dll – фильтр для IIS.

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

    1. Через элеметы формы не постятся данные размером более 4К, не аплоадятся файлы размером больше 4К. php4.exe процесс подвисает и снимается только рестартом IISа. (Отписал в репорт баг, но когда исправят непонятно, попытаюсь поправить сам).Решение: Обходится использованием php 3.12-3.14 для обработки файлов реакции форм. Медленнее, зато работает.

    2. При выполнении динамического кода в котором происходит использование сериализованных переменных парсер выдает оштбку. Например:

    Result: parser error on line 5 …..

    Происходит это из-за того, что в четвертой версии символы {} используются для инкапсуляции переменных в строку, например $a=”Такой вот элемент {$NotSer}”;

    Но сериализованное представление массива тоже содержит символы {}.

    В примере, описанном выше парсер пытается инкапсулировать выражение, которое на самом деле выражением то и не является и естественно валится с ошибкой.

    Решение: Надо поправить в файле \php4\ext\standard\var.c код, заменив { на [ и } на ]. Ищем в файле подстроку %d:{ и заменяем ее на %d:[ (будет две замены), и меняем { на [, В строке if (**p != ":" || *((*p) + 1) != "{") замена { на [, для строк for ((*p) += 2; **p && **p != "}" && i > 0; i--) и return *((*p)++) == "}"; меняем } на ]. Потом пересобираем php4ts.dsp. После этого все нормально отрабатывает.

    Сборка модуля Php 4.03 betta для MS SQL 6.5 (mssql.dll)

    Распаковать mssql.zip. *.lib забрасываем в C:\Win32Build\Lib, а *.h в C:\Win32Build\Include.

    Что я подразумеваю под сборкой? Сборка - это процесс действий, которые выполняются над кодом проекта перед его деплоем. Она может включать в себя создание копии проекта, очистка директории с кэшем, минификация CSS и JS файлов, упаковка результата в один zip-архив. Так же возможно ещё и автоматическое развертывание проекта а удаленном сервере, но сегодня речь об этом идти не будет.

    Другими словами - это автоматизация однотипных и рутинных действий. А там где есть однотипные действия - там место автоматизации:) Сегодня мы рассмотрим на живом примере один из способов с применением PhiNG, причем всё будем делать с самого начала - скачаем исходники, интерпритатор (в нашем случае это PHP ), и всё это дело настроим.

    Подготовка

    Итак, мы работаем под Windows. Первым делом определимся с тем, как у нас всё располагается. Имеется директория %project_name% , в которой лежит директория sources с исходниками проекта (пролинкована как домашняя директория на тестовом веб-сервере ), там же лежит README.md файл, и всё это располагается в Git-е (всё всегда храним в Git-е ). Визуально это выглядит так:

    %project_name% |- .git |- sources (исходники проекта) |- .gitignore \- README.md

    В итоге нам необходимо чтоб была создана копия директории sources ; над ней были произведены действия в виде минификации JS и CSS файлов, из PHP-файлов были удалены все комментарии; и в результате она упаковалась в файл build_%timestamp%.zip , удалив старую копию.

    Ставим PhiNG

    В директории с проектом создадим ещё одну директорию, назвав её build_tools , в которую качаем крайнюю версию PhiNG (GitHub . Распаковываем из архива содержимое директории phing-master в директорию.\build_tools\phing\ , после удалив всё, кроме директорий bin , classes и etc . Из директории bin копируем phing.bat в корневую директорию проекта, и называем его build.cmd .

    Ставим PHP

    Теперь нам потребуется сам PHP. Берем его с официального сайта , выбираем версию 5.5 под Windows. Распаковываем содержимое архива в директорию.\build_tools\php-5\ , и удаляем всё, кроме файлов php.exe , php.ini и php5.dll . Всё что нам понадобится уже вкомпилено в сборку. В файле php.ini добавляем дефолтовую таймзону - сразу же после строки добавляем строку, например date.timezone = "Asia/Yekaterinburg" . Особого значения какая именно таймзона стоит - нет, но важно чтоб она была указана (иначе PhiNG будет выдавать херову кучу warning-ов ). На этом считаем что PHP у нас готов.

    Переходим к настройке

    В файле build.cmd (что уже лежит в корне проекта ) необходимо указать где у нас располагается интерпритатор и PhiNG. Для этого редатируем две строки:

    Set DEFAULT_PHING_HOME=".\build_tools\phing" ... set PHP_COMMAND=".\build_tools\php-5\php.exe" ...

    Больше тут делать ничего нам более не придется. Остается создать файл конфигурации сборки - с корне проекта создадим файл build.xml , со следующим содержимым:

    Важный момент! Для минификации JS и CSS файлов я использую Minify , который пришлось “прикручивать” отдельно, так как в дефолтовой комплектации он просто не идет. Рассказ о том как его “прикручивал” достоин отдельного поста, но сейчас об этом речи не идет. Поэтому в конце статьи будут ссылки на уже готовую сборку PhiNG вместе с PHP в одном флаконе, с файлом конфигурации и запуском сборки.

    Remove old build directory Make project copy Clear cache Clear database directory Clear logs directory Minifying JavaScript files Minifying CSS files Protect PHP files Pack to single archive Remove build directory Build complete

    Чуть-чуть поясню конфигурацию:

    • Первым делом мы объявляем имя проекта и указываем директорию где хранятся его исходники, так же указав дефолтовую цель: build .
    • После мы добавили новое свойство build_dir со значением../build/ , указав таким образом где у нас будет располагаться директория с билдом. Более того, к этому значению из конфига можно будет обращаться по ${build_dir} .
    • Секция с таймстампом мне кажется и так понятна - просто указываем формат временной метки, и после при необходимости к ней обращаемся по ${build.time}
    • Далее идут описания с “целями” (читай в данном контекте - действиями ), тут всё должно быть более и менее понятно. В любой непонятной ситуации
    • В конце мы указываем самую главную цель build (указанную в самом начале ), в зависимостях которой перечисляем те, от которых она зависит (читай - те действия, которые необходимо выполнить )

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

    И остается самый ответственный момент - запустить сборку. Выполняем файл build.cmd:

    Как видим - сборка прошла без ошибок, и у нас в директории с проектом появился файл build_%timestamp%.zip , в котором все ресурсы нежно упакованы:) Как ты уже догадываешься - возможностей у PhiNG дохрена и больше - можно как делать и автоматическую загрузку итогового архива на удаленный сервер, так и производить массу иных операций. Но сейчас мы просто ознакомились с общим функционалом.

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

    Конечно, серьезную работу не сделать без хорошей команды. Но многие начинающие веб-мастера, впервые взявшиеся за создание небольшого динамического сайта, хотели бы иметь для этой задачи простой инструмент, не слишком далеко ушедший от хорошо знакомого статического html. В этой статье я постараюсь продемонстрировать, как один человек без особого опыта в программировании может построить динамический сайт буквально за один день. В этом нам поможет технология темплейтов, реализуемая при помощи несложных скриптов на языке php.

    Идея построения сайта на темплейтах родилась довольно давно, многие компании делают свои программы и сайты именно по этой технологии. Приемы работы с темплейтами используются практически во всех html-редакторах. Темплейты сильно экономят время, позволяя веб-мастеру создавать множество страниц, пользуясь всего одним шаблоном.

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

    Если за создание каждого информационного блока отвечает php-скрипт, "встроенный" в html-код страницы, то ничего, кроме головной боли, обслуживание такого сайта вам не принесет. Любое изменение структуры сайта или способа обработки информации в одном из блоков приведет к необходимости вносить значительные коррективы сразу во множество страниц. Поэтому веб-программисты стремятся как можно сильнее отделить код сайта от его верстки и дизайна.

    Вот тут-то и возникает идея использования темплейтов как средства разделения внешнего вида и исполняемого кода сайта. Оказывается, сайт можно собрать, как домик, — шаг за шагом, кирпичик за кирпичиком. А кирпичиками являются как раз те самые составляющие сайта, о которых мы уже говорили, — меню, формы, рекламные и информационные блоки и т. п. Темплейты позволят вам в большей или меньшей степени избавиться от привязки кода к внешнему виду сайта и облегчает задачу генерации динамического html-кода страниц.

    Вариант 1. Вложения

    Задача — собрать сайт из статичных блоков.

    Для того, чтобы собрать веб-страницу по кирпичику, надо ее сначала разбить на кирпичики. Рассмотрим в качестве примера страницу http://devser.com/code/download.php, с которой, кстати, можно скачать несколько заготовок для темплейтных сайтов. Верхний блок назовем header, нижний, соответственно, — footer, меню — menu, а основной информационный текст — main. Это и будут кирпичики для нашего сайта.
    Код, соответствующий каждому блоку, поместим в отдельный файл с расширением.txt (чтобы не путать с полноценными html-страницами). Редактировать эти текстовые файлы можно в любом html-редакторе. А сборка страницы выполняется с использованием php.

    Когда веб-сервер встречает этот скрипт, он перенаправляет его интерпретатору php, который на место каждой команды include вставляет текст из соответствующего файла. Страницу, полученную в результате сборки, сервер передает пользователю.

    Конечно, генерировать подобным образом отдельную страницу нет никакого смысла. Но при большом числе страниц со сходной компоновкой некоторые блоки (в нашем случае, например, header.txt и menu.txt) будут использоваться многократно. Выигрыш от этого получается двоякий. Во-первых, при необходимости изменить, допустим, меню, редактировать придется только один файл, а во-вторых, основной текст страницы в файле main.txt не будет перегружен совершенно не относящимися к делу тегами и скриптами, значит, меньше будет риск ошибки при редактировании.

    Данный пример хорошо иллюстрирует идею "собирания" html-кода страницы из кусочков путем вложения их в основной блок страницы. Каждый из подключаемых файлов отвечает только за одну определенную функцию. Но основной смысл состоит в том, что удалось полностью избавиться от помещения html-кода внутрь php-кода, так как здесь каждая частичка html хранится в отдельном файле.

    Простота примера впечатляет, но годится такой способ только для очень несложных страниц. Главный минус этого варианта состоит в том, что связи разбитых по отдельным файлам блоков html-кода жестко заданы внутри самого php-скрипта. Для динамического сайта это не годится.

    Вариант 2. Динамическая структура

    Задача — сделать сайт с функциями динамической структуры данных.
    В этом примере мы ближе подойдем к основной задаче — создать сайт на основе темплейта.

    Вид основной странички (index.php) изменился незначительно:

    Дело в том, что все самое интересное спрятано в файле func.php (см. листинг), который подключается в первой же строчке скрипта. Файл func.php состоит из двух частей. В первой определяются значения переменных, которые понадобятся в дальнейшем, а во второй содержится описание функции text, выполняющей вставку изменяемого текста. В данном простейшем примере нам понадобилась единственная переменная $text_path, задающая путь к каталогу, из которого функция text будет брать файлы.

    Может возникнуть естественный вопрос: а как же функция text определит, какой файл следует вставить? Ведь мы создаем многостраничный сайт. Для доступа ко всем страницам используется файл index.php, а для указания, какой информацией наполнить страницу, служит параметр page, передаваемый в формате cgi-запроса, например, index.php?page=news — для ссылки на страницу с новостями или index.php?page=photo — для странички с фотоальбомом и т. д. Если имя раздела не было задано, или указанной страницы не существует, выводится текст из файла index.txt.

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

    Вариант 3. Единый темплейт для всего сайта

    Задача — полностью разделить дизайн, скрипты и содержание страниц.

    До сих пор мы исходили из того, что структура страницы может быть описана как набор последовательно идущих информационных блоков, которые можно просто вставить в файл командой include. Надо ли говорить, что на практике все обстоит гораздо сложнее? Тем не менее, для большинства веб-сайтов можно выделить с одной стороны неизменные html-конструкции, которые повторяются на всех страницах и описывают их структуру и дизайн, а с другой, варьирующиеся тексты, которые, собственно, и составляют информационное наполнение.

    То, что останется, если всю переменную информацию выкинуть, — это и есть темплейт страницы. Для создания темплейтного сайта надо просто научиться вставлять информационные блоки внутрь темплейта. На практике темплейты бывают довольно сложными, в них используются нетривиальные приемы верстки и дизайна, однако в конце концов остается просто добавить в темплейт текст. Мы не будем загромождать статью сложными примерами и рассмотрим предельно упрощенный темплейт:

    template site

    Поместим код темплейта в файл index.php. Он полностью описывает структуру нашей страницы, если не считать того, что вместо основного текста в нем содержится вызов функции text, вместо меню — вызов функции menu, а вместо блока кратких новостей — вызов функции news. Код этих функций размещен в файле func.php, который подключается директивой require в начале темплейта.

    Каждая функция, обращаясь к переменной $page, может определить, какую именно информацию нужно вывести в формируемом ею информационном блоке. Например, функция menu может исключать из меню ссылку на отображаемую в данный момент страницу. (На практике, правда, совсем удалять пункт из меню не стоит — лучше просто убрать с него ссылку, однако в данном примере для простоты ссылка со страницы на саму себя просто исключается.)

    Другой пример динамического блока — функция news. Обычно она просто помещает в отведенное ей место темплейта сводку кратких новостей сайта из файла shortnews.txt. Однако это не имеет смысла, если мы находимся на основной странице новостей. В этом случае вызывается функция banner, которая вместо новостей вставляет рекламный баннер.

    Как видите, наш сайт уже обретает динамику. Дополнительные возможности дает добавление в начало файла func.php различных переменных — параметров, значения которых используются в коде, формирующем информационные блоки. Вы можете добавить и новые функции, которые в дальнейшем будут активно применяться при формировании страниц.

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

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

    Листинг. Файл func.php

    "); } elseif($page != "news"){ echo ("Новости"); } elseif($page != "photo"){ echo ("Галерея"); } // ... } // Вывод блока кратких новостей (если мы не на основной новостной странице) function news() { if($page != "news"){ include ($text_path."shortnews.txt"); } else{ banner(); } } ?>

    Киса, вы умеете рисовать?

    Пожалуй, самый незаменимый человек в команде веб-студии — это веб-дизайнер. Вы или умеете рисовать, или нет. Как же быть, если сайт надо делать в одиночку, а по рисованию с черчением в школе у вас была натянутая тройка? В таком случае, скорее всего, вам подойдут бесплатные html-темплейты, которых в Сети довольно много. В качестве примера могу привести парочку ссылок. Например, со страницы http://winstart.com/template все можно скачать бесплатно, а перед скачиванием еще и посмотреть, как это будет выглядеть при использовании. На http://www.elcdesigns.com/ большая часть темплейтов платная, но впечатляет уровень сервиса.

    В процессе сбора данных наши сборщики будут работать сутками и нам надо следить за их работоспособностью. Например упал сервер, изменились условия сбора или просто отключили свет. Чтобы постоянно не следить за работой нужен механизм извещения о процессе работе сборщиков данных.…

    В предыдущих статьях я описал как создать многопоточные поисковые сборщики на PHP по следующим системам: Google Suggest — сборщик поисковых подсказок Google Yandex Suggest — сборщик поисковых подсказок Yandex Rambler Suggest — сборщик поисковых подсказок Rambler Nigma Suggest — сборщик поисковых подсказок Nigma…

    Идем далее по местам где можно получить поисковые подсказки. Следующая поисковая система это Rambler. С нее тоже можно получать вполне приличные поисковые запросы. Посмотрев в интернете мы найдем, что для запросов используется следующий адрес. Все это хорошо вписывается в наш…

    Еще одно место где можно получить поисковые запросы это подсказки поисковой системы Nigma.ru. Набрав в ней например «поисковые п» мы получим следующее: Поискав в интернете, определяем что запрос поисковых подсказок идет по следующему адресу. Т.е в самом конце…

    При наборе слов в Google нам выдаются определенные поисковые подсказки. Т.е например при вводе автоматизация бизнеса, гугл нам предлагает следующие варианты поисковых запросов: Поискав в интернете можно найти урл, по которому идет запрос этих данных: т.е в самом…

    В прошлых постах, я создал многопоточный сборщик поисковых результатов Google API на PHP. Из опыта использование получилось что скорость его работы сильно зависела от качества использованных проксей. Сегодня я видоизменил механизм использования проксей в этом сборщике. Для этого был полностью…

    У меня есть PHP script, который имеет большой массив людей, он захватывает свои данные с внешнего ресурса через SOAP, изменяет данные и отправляет их обратно. Из-за размера деталей я увеличил память PHP до 128 МБ. Примерно через 4 часа работы (это, вероятно, займет 4 дня), у него закончилась нехватка памяти. Вот основы того, что он делает:

    $people = getPeople(); foreach ($people as $person) { $data = get_personal_data(); if ($data == "blah") { importToPerson("blah", $person); } else { importToPerson("else", $person); } }

    После того, как у него закончилась нехватка памяти и я разбился, я решил инициализировать $data до цикла foreach , и в соответствии с top использование памяти для процесса не поднялось выше 7,8%, и оно продолжалось 12 часов.

    Итак, мой вопрос: не работает ли PHP сборщик мусора на переменных, инициализированных внутри цикла, даже если они используются повторно? Является ли система исправлением памяти, и PHP еще не отметил ее как полезную, и в конечном итоге снова рухнет (я повысил ее до 256 МБ, так что я изменил 2 вещи и не уверен, что исправил ее, я, вероятно, мог бы изменить свой script назад, чтобы ответить на этот вопрос, но не хотите ждать еще 12 часов, чтобы он упал, чтобы понять)?

    Я не использую рамки Zend, так что другой вопрос, подобный этому, я не считаю релевантным.

    EDIT: у меня нет проблемы с script или тем, что он делает. На данный момент, насколько это касается всей системы, у меня нет никаких проблем. Этот вопрос касается сборщика мусора и того, как/когда он восстанавливает ресурсы в цикле foreach и/или как система сообщает об использовании памяти в php-процессе.

    2 ответов

    Я не знаю внутренности PHP VM, но по моему опыту, это не сбор мусора, пока ваша страница работает. Это происходит потому, что он удаляет всю вашу страницу, когда она заканчивается.

    В большинстве случаев, когда на странице заканчивается память, а предел довольно высокий (а 128 Мб невысока), есть проблема с алгоритмом. Многие PHP-программисты собирают структуру данных, а затем передают ее на следующий шаг, который выполняет итерацию по структуре, обычно создавая другую. Намочите, промойте, повторите. К сожалению, этот подход представляет собой большой всплеск памяти, и вы создаете несколько копий ваших данных в памяти. Две из очень больших изменений в PHP 5 заключались в том, что объекты подсчитываются, а не копируются, а вся строковая подсистема выполняется намного быстрее. Но это все еще проблема.

    Чтобы свести к минимуму использование памяти, вы бы посмотрели на реструктуризацию своего алгоритма, чтобы он мог работать с одним куском данных от начала до конца. Затем вы получите следующее и начнете снова. Лучший сценарий - это то, что у вас никогда не было всего набора данных в памяти. Для веб-сайта с поддержкой базы данных это будет означать обработку строки данных из запроса базы данных до презентации до получения следующего. Конечно, такой подход не всегда возможен, и script просто должен хранить огромное количество данных в памяти.

    Тем не менее, вы можете сделать этот подход к экономии памяти для части данных. Фокус в том, что вы явно unset() ключевой переменной или двух в конце цикла. Это должно вернуть пространство. Другой "лучший практический" трюк состоит в том, чтобы переместить из обработки данных цикла, которая не должна находиться в цикле. Как вы, кажется, обнаружили.

    Я запускаю скрипты PHP, которые нуждаются в объеме 1 ГБ памяти. Фактически, вы можете установить ограничение памяти на script с помощью ini_set("memory_limit", "1G");



    Рекомендуем почитать

    Наверх