Как разбить большой процесс php на несколько последовательных, избежав Fatal error: Allowed memory size?
Здравствуйте. Есть скрипт который генерирует большой Excel файл (порядка 100000 строк). Для его заполнения на сервере недостаточно памяти. Поменять сервер нет возможности в данный момент.
Скажите, возможно ли как-то разбить процесс создания такого файла на "подпроцессы", например, всего 100к записей, я заношу 10к, сохраняю в файл и затем (как это сделать? м.б. cURL?) вызываю другой процесс, который добавляет ещё 10к записей в файл. Или данный выход - полный бред? Как ещё можно сделать?
А чем вы генерируете excel файл? И падает всё когда уже начало писать файл или на момент подготовки данных? Вообще тут и несколько процессов может не понадобится если к памяти относиться бережно при генерации файла.
Основные советы обычно таковы:
1. Данные подготавливать постепенно пачками
2. Данные сбрасывать на диск так же пачками
PS. Я побыстрому вроде проверил. Кушало на винде не более 15 мегабайт. Писало 1000000 строк. Писал одну и туже строку в цикле. Нагенерило файл размером 25 мегабайт.
Excel-файл нельзя записать частично, он будет невалидным.
А вот CSV-файл можно. А если правильно написать код и избежать утечек памяти, то записывать CSV-файл можно почти неограниченного размера даже при небольшой оперативной памяти.
Arekusei: Допустим, первую пачку строк записать в валидный Excel-файл можно. А как туда добавить вторую пачку? Не конкатенацией же. А если загрузить весь файл, добавить вторую пачку и сохранять заново, то опять же вылетит по памяти.
Дело в том что бы дописывать файл нету необходимости его хранить весь. Какого бы формата он не был. Просто на достижения данной цели могут требоваться различные усилия.
Да CSV в виду простоты наиболее просто генерировать постоянно дописывая файл. С ексель файлами тоже можно работать подобным образом, но тут уже становится не просто поскольку многие если не все библиотеки поддерживают от силы чтение данных пачками.
Boris Korobkov: Борис, скажите, а если записывать например 5-10к записей, сохранять файл и отправлять запрос с помощью cURL который дозапишет файл до нужного количества, как выход может быть? Потому что я попробовал сейчас так сделать и почему то память всё равно ограничена...
Octoberfest: Так будет еще хуже, и можно завалить сервер, потому что при вызове CURL предыдущий процесс не закончится, память не освободит, а будет ждать окончания, при этом новый процесс отожрет свою память, опять вызовет CURL и т.д.
Во-первых, длительные скрипты надо вызывать только из консоли (по крону).
Во-вторых, надо правильно писать код, бороться с утечками памяти, unset ненужных переменных, выбирать данные из БД не все сразу, а пачками и т.д.