Подтвердить что ты не робот

Проблемы с 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)

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

4b9b3361

Ответ 1

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

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 итерации до того, как закончится script; и не 765, как вы хотели.

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

128*(765/131) = 747 MB

Ну, даже с

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

все еще недостаточно... с 800MB, кажется, достаточно; -)


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

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


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

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

Ответ 2

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

Ответ 3

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

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

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