La optimización de la memoria en el array de PHP

Estoy trabajando con una matriz de gran tamaño, que es un mapa de altura, 1024×1024 y, por supuesto, estoy atascado con el límite de memoria. En mi máquina de prueba puedo aumentar el mem límite de 1gb si quiero, pero en mi pequeño VPS con solo 256 de ram, no es una opción.

He estado buscando en la pila y google y encontré varios «bien, usted está usando PHP no porque la memoria de la eficiencia, la zanja y reescribir en c++» y, honestamente, que está bien y reconozco PHP ama de memoria.

Pero, al excavar más en el interior de administración de memoria de PHP, no encontré lo de la memoria que consume cada tipo de datos. O si la conversión a otro tipo de datos, se reduce mem consumo.

El único «optimización de la técnica de» me encontré fue a unset variables y matrices, que es.

Convertir el código a c++ con algunas PHP analizadores podría resolver el problema?

Gracias!

  • Las matrices son verdaderamente memoria hambre en PHP (como en realidad son los diccionarios). Si usted puede dar algunos (muchos!) la velocidad puede falsos matrices binarias como en C, también para estructuras 2D, supongo. Pero tal vez usted realmente desea investigar la HipHop PHP a C++ compilador.
  • Cuánto de uso de memoria que usted necesita para cortar? Como usted ha leído, hay poco en el camino de la gestión de la memoria que se puede hacer en PHP. Hay «optimizaciones» se puede hacer, pero probablemente nada de lo que va a recortar tanto como usted pueda necesitar.
  • Cada una de las variables en PHP se ha sobrecarga asociada con ella. No sólo el valor de la variable tiene que ser almacenados, pero la variable nombre, tipo, etc… Incluso un simple $x[1] = 2; tiene un cuerpo grande de cosas adicionales siguientes a su alrededor.
  • ¿Qué pasa con una extensión de php?
  • Me pregunto por qué el post vinculado detenido en hex de codificación y no utiliza directamente el total de bytes de la cadena. Parece un poco de matemáticas en realidad podría ser más rápido … pero yo no uso PHP (no tendría sentido para la válida multibyte secuencias y otras cosas 🙂
  • Yo en realidad tienen otra versión, con pack() de cadenas binarias. Pero eso no es realmente más rápido; sólo ahorra el doble de la memoria. (Sólo hay tanto que se puede fingir en PHP 😉

3 Kommentare

  1. 48

    Si quieres un verdadero matriz indexada, uso SplFixedArray. Utiliza menos memoria. También, PHP 5.3, tiene un mucho mejor recolector de basura.

    Aparte de eso, bien, PHP se utiliza más memoria que una más cuidadosamente escrito en C/C++ equivalente.

    Uso de la memoria para 1024×1024 matriz de enteros:

    • Estándar de la matriz: 218,756,848
    • SplFixedArray: 92,914,208

    medida por memory_get_peak_usage()

    $array = new SplFixedArray(1024 * 1024); //array();
    for ($i = 0; $i < 1024 * 1024; ++$i)
      $array[$i] = 0;
    
    echo memory_get_peak_usage();

    Tenga en cuenta que la misma matriz en C usando números enteros de 64 bits sería 8M.

    Como otros han sugerido, usted puede empacar los datos en una cadena. Esto es más lento pero por tanto más eficiente de la memoria. Si el uso de valores de 8 bits, es súper fácil:

    $x = str_repeat(chr(0), 1024*1024);
    $x[$i] = chr($v & 0xff); //store value $v into $x[$i]
    $v = ord($x[$i]);        //get value $v from $x[$i]

    Aquí la memoria sólo será de alrededor de 1,5 MB (es decir, cuando se considera la totalidad de la sobrecarga de PHP con sólo esta entero matriz de cadena).

    Por la diversión de hacerlo, he creado un simple punto de referencia de la creación de 1024×1024 de 8 bits enteros y, a continuación, un bucle a través de ellos una vez. El envasado de las versiones de todos los utilizados ArrayAccess de modo que el código de usuario que tenía el mismo aspecto.

                       mem    write   read
    array              218M   0.589s  0.176s
    packed array       32.7M  1.85s   1.13s
    packed spl array   13.8M  1.91s   1.18s
    packed string      1.72M  1.11s   1.08s

    El envasado de las matrices utilizadas nativo de 64-bits enteros (sólo el embalaje de 7 bytes para evitar el tratamiento de los datos firmados) y de la gran cadena que se utiliza ord y chr. Obviamente, los detalles de implementación y de las características del equipo va a afectar un poco las cosas, pero yo esperaría que para obtener resultados similares.

    Así, mientras que la matriz era 6 veces más rápido que también se utiliza 125x la memoria como la siguiente mejor alternativa: lleno de cadenas de caracteres. Obviamente, la velocidad es irrelevante si se ejecuta fuera de la memoria. (Cuando he usado lleno de cadenas directamente sin necesidad de un ArrayAccess clase que sólo eran 3 veces más lento que el de los nativos de las matrices.)

    En definitiva, para resumir, me gustaría usar algo que no sea puro PHP para procesar este tipo de datos si la velocidad es de ninguna preocupación.

    • +1 Además, emulando a los índices de matriz y con un embalaje puede reducir aún más el uso de la memoria, si es aplicable. E. g. si cada altura de mapa de valor es de sólo 8 bits de la uso de la memoria debe ser considerablemente menor cuando se envasa a 32bits (o 64 bits dependiendo de PHP bits). La exacta ganancia en eficiencia varía debido a la carga/tamaño de utilización frente al valor de los gastos generales de mantenimiento de los valores de PHP utilizada. (Creo que hay 4 bytes de «sobrecarga» por valor entero, pero no estoy del todo seguro.)
    • Al parecer hay más de 4 bytes de sobrecarga … este post sugiere que puede tomar más de 36 (o 72 en x64) bytes sólo para un trivial valor. Esto indica que es muy beneficioso (en términos de uso de memoria) para empacar. Suponiendo que los 8 bits de entrada y una de 32 bits arco, 4 valores tomaría ~36bytes vs ~144bytes si lleno, mientras que en una versión de 64 bits de la máquina 8 valores tomaría ~72bytes vs ~576bytes! (¡Caramba!)
    • Así que, en conclusión … con el embalaje, 8 bits de los valores se amortizarán a ~9 bytes para un brazalete de estimación de 9MB de objeto de sobrecarga/datos, excluyendo la memoria necesaria para la inclusión en la propia matriz, etc — de despiece de los números publicados se ~22.5 MB de uso total. (Tales de embalaje puede parecer la sobre-optimización, pero teniendo en cuenta que el objetivo está limitado a 256 mb de RAM .. 😉
    • He añadido un poco sobre el embalaje de los datos en una cadena. Cuando se trata con 8 bits enteros (como tal vez el mapa de altura es entonces una cadena de matriz de enteros será, básicamente, el mismo tamaño como lo es el equivalente de C sería. Por supuesto, la velocidad va a ser mucho, mucho peor que la nativa de números enteros.
    • El embalaje en una de PHP valor integral 🙂 Velocidad debe estar cerca de la no-empaquetado para la muchos operaciones (sólo una máscara y un cambio extra) – y mucho más eficiente de la memoria-sabio (pero no tan eficiente como kludging en una cadena).
    • Lo siento, estaba confuso tuyo con mario sugerencias. Sí, con un SplFixedArray, que debe ser aproximadamente de 22MB si usted pack de 8 bits enteros. Debería ser más rápido que el de 1.5 MB lleno de cadena equivalente, aunque uno nunca sabe con PHP. (por ejemplo, Los enteros se firmó, por lo que el trato con el bit alto podría exigir algo más que simples cambios.) La memoria más rápida solución amistosa sería escribir un nativo matriz de enteros como un C de extensión y exponerlo como una clase de PHP.
    • Err, me olvidé de mis números estaban en 64-bits, por lo que el SplFixedArray con lleno enteros debe ser de alrededor de 12 MB.
    • SplFixedArray parece ofrecer el mejor beneficio/relación de trabajo (voy a tener que cambiar el nombre de todos mis índices de Cadena a entero queridos y eso es todo). Nicey! <3

  2. 11

    Además a la aceptación de respuesta y sugerencias en los comentarios, me gustaría sugerir PHP Judy implementación de matriz de.

    Rápida de las pruebas mostraron resultados interesantes. Una matriz con 1 millón de entradas que usar el array de PHP estructura de datos se lleva a ~200 MB. SplFixedArray utiliza alrededor de 90 megabytes. Judy utiliza 8 megas. Como contrapartida, en el rendimiento, Judy se lleva aproximadamente el doble del tiempo de regular array de php implementación.

    • Mal echarle un vistazo, bonito bonito! En mi caso, puedo vivir con un impacto en el rendimiento con el fin de ahorrar algo de memoria ram.
    • Exactamente lo que necesito! Judy Matriz es impresionante. Alto rendimiento y bajo uso de memoria.
    • Estoy contento de que alguien decidió utilizar este impresionante implementación de matriz 🙂
    • No es la Judy Matriz usando sólo un lleno cadena PHP internamente?
    • no, no lo es. ¿Has leído en alguna parte?
    • no, pero no parece ser otra forma de llevarlo a cabo de manera más eficiente en PHP hay?
    • Yo no entiendo realmente lo que estás preguntando.. Judy es una extensión para PHP, todos la asignación de la memoria y el trabajo es administrado por la extensión y no de PHP estructuras de datos internas, especialmente no la cadena.

  3. 0

    Un poco tarde a la fiesta, pero si usted tiene una matriz multidimensional que puede ahorrar una gran cantidad de memoria RAM cuando se almacena en el vector completo como json.

    $array = [];
    
    $data = [];
    $data["a"] = "hello";
    $data["b"] = "world";

    Para almacenar esta matriz sólo tiene que utilizar:

    $array[] = json_encode($data);

    lugar de

    $array[] = $data;

    Si quieres obtener el arrry de nuevo, sólo tiene que utilizar algo como:

    $myData = json_decode($array[0], true);

    Tenía una gran matriz con 275.000 conjuntos y ahorrar aproximadamente un 36% del consumo de RAM.

    EDITAR:
    He encontrado una mejor manera, al zip de la cadena json:

    $array[] = gzencode(json_encode($data));

    y descomprimirlo cuando la necesite:

    $myData = json_decode(gzdecode($array[0], true));

    Esto me salvó de casi el 75% de la memoria RAM máxima de uso.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea