У меня есть сценарий, который ставит 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