Проблемы с PHP при попытке создать большой массив

Вот мой код, который создает массив 2d, заполненный нулями, размеры массива (795,6942):

function zeros($rowCount, $colCount){ $matrix = array(); for ($rowIndx=0; $rowIndx<$rowCount; $rowIndx++){ $matrix[] = array(); for($colIndx=0; $colIndx<$colCount; $colIndx++){ $matrix[$rowIndx][$colIndx]=0; } } return $matrix; } $matrix = zeros(795,6942); 

И вот ошибка, которую я получаю:

 Allowed memory size of 134217728 bytes exhausted (tried to allocate 35 bytes) 

Есть идеи, как это решить?

В качестве быстрого вычисления вы пытаетесь создать массив, который содержит:

 795*6942 = 5,518,890 

целые числа.

Если мы считаем, что одно целое число хранится на 4 байта (то есть 32 бита, с использованием PHP это не меньше) , это означает:

 5518890*4 = 22,075,560 

байт.

ОК, быстрый расчет … результат « это должно быть ОК ».

Но дело не так просто, к несчастью 🙁
Я полагаю, это связано с тем, что данные хранятся в PHP с использованием внутренней структуры данных, которая намного сложнее, чем простое 32-битное целое число

Теперь, просто любопытно, давайте изменим вашу функцию, чтобы она выводила, сколько памяти используется в конце каждого из внешних for -loop:

 function zeros($rowCount, $colCount){ $matrix = array(); for ($rowIndx=0; $rowIndx<$rowCount; $rowIndx++){ $matrix[] = array(); for($colIndx=0; $colIndx<$colCount; $colIndx++){ $matrix[$rowIndx][$colIndx]=0; } var_dump(memory_get_usage()); } return $matrix; } 

С этим я получаю такой вывод (PHP 5.3.2-dev в 64-битной системе, memory_limit установлен в 128MB – это уже много!) :

 int 1631968 int 2641888 int 3651808 ... ... int 132924168 int 133934088 Fatal error: Allowed memory size of 134217728 bytes exhausted 

Это означает, что каждая итерация внешнего for -loop требует примерно 1,5 МБ памяти – и я получаю только 131 итерации до того, как у скрипта закончится память; и не 765, как вы хотели.

Учитывая, что вы установили свой memory_limit в 128M , вам придется установить его на что-то действительно намного выше – например,

 128*(765/131) = 747 MB 

Ну, даже с

 ini_set('memory_limit', '750M'); 

его все еще недостаточно … с 800MB , кажется, достаточно 😉

Но я определенно не рекомендую устанавливать memory_limit на такое высокое значение!

(Если у вас 2 ГБ ОЗУ, ваш сервер не сможет обрабатывать более двух одновременных пользователей ^^ ;; я бы не стал проверять это, если бы на моем компьютере было 2 ГБ оперативной памяти, если честно)

Единственное решение, которое я вижу здесь, – это переосмыслить свой дизайн: нужно что-то еще сделать, чем использовать эту часть кода 🙂

(BTW: может быть, «передумать свой дизайн» означает использование другого языка PHP: PHP отлично подходит для разработки веб-сайтов, но не подходит для всех проблем)

Реализация PHP-массива по умолчанию очень интенсивно связана с памятью. Если вы просто храните целые числа (и их много), вы, вероятно, захотите посмотреть на SplFixedArray . Он использует регулярный непрерывный блок памяти для хранения данных, в отличие от традиционной хэш-структуры.

Вы должны попытаться увеличить объем памяти, доступной для PHP:

 ini_set('memory_limit', '32M'); 

в вашем PHP-файле.