Проблемы с PHP при попытке создать большой массив - PullRequest
14 голосов
/ 22 февраля 2010

Вот мой код, который создает 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)

Есть идеи, как решить эту проблему?

Ответы [ 3 ]

29 голосов
/ 22 февраля 2010

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

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 -цикла требуется что-то около 1,5 МБ памяти - и я получаю только 131 итерацию, прежде чем скрипту не хватит памяти; а не 765, как вы хотели.

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

128*(765/131) = 747 MB

Ну, даже с

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

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


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

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


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

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

5 голосов
/ 04 февраля 2012

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

1 голос
/ 22 февраля 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...