Более 640 000 элементов в массиве – проблема с памятью

У меня есть сценарий, который ставит 803 * 803 (644 809) график с 1 000 000 значений внутри каждого. При ~ 500 * 500 все работает нормально – но теперь он падает – он пытается выделить более 64 МБ памяти (чего у меня нет). Какое решение? Как-то «раскололи» его или …?

$result=mysql_query("SELECT * FROM some_table", $connection); confirm($result); while($rows = mysql_fetch_array($result)){ $result2=mysql_query("SELECT * FROM some_table", $connection); confirm($result2); while($rows2 = mysql_fetch_array($result2)){ $first = $rows["something"]; $second = $rows2["something2"]; $graph[$first][$second] = 1000000; } } 

* Речь идет о алгоритме Дейкстры

ps нет, я не могу выделить более 64 МБ

    Попробуйте освободить свой внутренний SQL-результат в конце каждого цикла, используя mysql_free_result($result2); , скрипт PHP может не сделать этого для вас, в зависимости от версии PHP (сборщик мусора не может быть включен или может быть бесполезным из-за слишком старой версии PHP).

    Не управляйте двумя временными переменными внутри цикла, напрямую используйте результат mysql_fetch_array, например $graph[$rows["something"]][$rows2["something2"]] = 1000000; , вы сохраните 2 распределения памяти за цикл.

    PS: Это микрооптимизация, поэтому она может помочь вам сэкономить достаточно памяти, чтобы вписаться в ваш 64M памяти. Не забывайте, что с 64 * 1024 * 1024 байтами памяти у вас есть средний размер в 104 байта для каждого из ваших 644 809 элементов, а также размер массива, а также остальные временные данные, которые вы можете выделить для своего алгоритма ,

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

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

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

     $result = mysql_unbuffered_query("SELECT * FROM some_table", $connection); confirm($result); $rawData = array(); while ($rows = mysql_fetch_assoc($result)) { $rawData[] = array($rows["something"], $rows["something2"]); } mysql_free_result($result); $graph = array(); foreach ($rawData as $r1) { foreach ($rawData as $r2) { $graph[$r1[0]][$r2[1]] = 1000000; } } unset($rawData); 

    Заметки:

    • Я использую mysql_fetch_assoc() вместо mysql_fetch_array() потому что последний будет возвращать каждый столбец дважды (один индексируется по mysql_fetch_array() и индексируется по имени столбца)
    • Возможно, использование mysql_unbuffered_query() вместо mysql_query() может также уменьшить объем памяти (в зависимости от фактического размера набора данных)

    Попробуйте использовать http://en.wikipedia.org/wiki/Adjacency_list для представления графика вместо матрицы смежности (думаю, вы используете матричную причину $graph[$first][$second] = 1000000;

    Для разреженного графика требуется меньше памяти.

    Если вы настаиваете на использовании PHP для операций с большой памятью (на самом деле это не очень хорошая идея), я бы разбил график на квадранты и использовал GD для объединения квадрантов. Таким образом, вам нужно будет построить график с 1/4 объема памяти.

    Опять же, это не идеально, но вы пытаетесь использовать гвоздь для вождения молотком: D