Más de 640 000 elementos en la matriz – problema de memoria

Tengo un script que pone 803 * 803 (644 809) gráfico con 1 000 000 de valor dentro de cada uno. Con ~ 500 * 500 todo funciona bien, pero ahora falla, intenta asignar más de 64MB de memoria (cosa que no he hecho). ¿Cual es la solución? ¿De alguna manera “dividirlo” o …?

$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; } } 

* se trata del algoritmo de Dijkstra

ps no, no puedo asignar más de 64 MB

Pruebe a liberar el resultado interno de sql al final de cada ciclo, usando mysql_free_result($result2); , el script PHP puede no hacerlo por usted, dependiendo de la versión de PHP (el recolector de elementos no utilizados puede no estar habilitado o puede ser inútil debido a una versión de PHP demasiado antigua).

No instale las dos variables temporales dentro del ciclo, use el resultado mysql_fetch_array directamente como $graph[$rows["something"]][$rows2["something2"]] = 1000000; , ahorrará 2 asignaciones de memoria por ciclo.

PD: Esto es microoptimización, por lo tanto, puede ayudarle a ahorrar suficiente memoria para caber en su 64M de memoria. No olvide que con 64 * 1024 * 1024 bytes de memoria, tiene un tamaño máximo promedio de 104 bytes para cada uno de sus 644 elementos 809, más el tamaño de la matriz, más el rest de los datos temporales que puede asignar para su algoritmo .

Si no le queda, considere dividir su matriz y realizar trabajos por lotes o similares para dividir su trabajo en menos consumo de memoria pero más de un script ejecutado.

Si su ejemplo de código anterior coincide con su código real, está obteniendo el mismo resultado dos veces (el segundo incluso en un bucle). Si es el mismo conjunto de datos recuperar una vez de la base de datos, será suficiente y reducirá la carga de la base de datos, el tiempo de ejecución y la huella de memoria por completo.

Tal vez el siguiente enfoque pueda funcionar en su entorno de memoria restringida.

 $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); 

Notas:

  • Estoy usando mysql_fetch_assoc() lugar de mysql_fetch_array() porque este último devolverá cada columna dos veces (una indexada numéricamente y otra indexada por el nombre de la columna)
  • Quizás el uso de mysql_unbuffered_query() lugar de mysql_query() también reduzca la huella de memoria (dependiendo del tamaño real del conjunto de datos)

Intenta usar http://en.wikipedia.org/wiki/Adjacency_list para representar el gráfico en lugar de Adjacency Matrix (creo que estás usando matrix cause de $graph[$first][$second] = 1000000;

Para un gráfico escaso, se necesita menos memoria.

Si insistes en usar PHP para operaciones de memoria alta (lo cual no es realmente una buena idea para empezar), dividiría el gráfico en cuadrantes y usaría GD para combinar los cuadrantes. De esta manera, solo tendrá que construir el gráfico con 1/4 de la huella de memoria.

De nuevo, esto no es ideal, pero estás tratando de usar un clavo para clavar un martillo: D

    Intereting Posts