2012-05-26 11 views
5

En la documentación de PHP que dice:por referencia

No utilice retorno por referencia para aumentar el rendimiento. El motor optimizará automáticamente esto por sí mismo.

Deseo devolver una referencia a una matriz (que es una propiedad de mi clase). ¿Cómo optimiza PHP esto, porque la matriz no es un objeto?

Si la matriz tiene 1 billón de entradas, ¿no obtendré dos matrices con 1 billón de entradas almacenadas en la memoria si no las paso por referencia?

Respuesta

5

PHP utiliza copia en escritura. Esto significa que si pasa la gran matriz como un parámetro de función y solo lee de ella (como foreach), no le escribirá para que no tenga que hacer una copia.

$count = count($huge_array); // read the reference at the bottom 
for($i = 0; $i < $count $i++) { 
    $value = 2*$huge_array[$i]/15; 
    if($value > 3) 
     $sub_array []= $value; 
} 

El $ subarreglo que debe ser más pequeño (que es un subconjunto de la gran cantidad), sólo contendrá los datos necesarios (cambio).

Si no tiene la intención de cambiar los valores del original $ huge_array, nunca se copiará, por lo que no se utiliza memoria adicional.

Si tiene intenciones de cambiar los valores originales de la matriz, necesita para pasarla por referencia.

Si tiene la intención de realizar y devolver una versión alterada de la matriz original, entonces necesita la memoria extra que PHP le asigna.

Si tiene la intención de crear y devolver un subconjunto alterado más pequeño de la matriz original, entonces creará una nueva matriz vacía en la que copiará algunos datos de la gran matriz y deberá tener cuidado de no sobrescribir los valores de $ huge_array, por lo que evitará escribir desde $ huge_array y enfatizará en leer de él.

Este link explica que PHP se ha optimizado para casos de uso de paso por valor.

Copiar en escritura solo funciona si la variable no es una referencia que se pasa a una función que espera un valor, si es así, pasarlo dispara una copia.

Eso hace que las funciones nativas de PHP que esperan que un argumento pase por valor y reciba una variable de referencia copie el valor de la referencia.

function foo(&$data) { 
    for ($i = 0; $i < strlen($data); $i++) { 
     do_something($data{$i}); 
    } 
} 

$string = "... looooong string with lots of data ....."; 
foo(string); 

Ejecutar strlen in C implicaría iterar sobre toda la cadena para contarlo. En PHP, las cadenas tienen un valor de longitud adjunto. Así que strlen devuelve el valor leído desde allí (rápido).

Pero si le da una variable referenciada, tendrá que copiarla antes de leer su longitud, por lo que repetirá el valor para copiarla en su lista de argumentos, leer y devolver la longitud (y posteriormente liberar la memoria para el cadena recién copiada).

+0

Hay una cosa. Foreach sí cambia la matriz: cambia el puntero interno de la matriz. Por lo tanto, COW no funcionará aquí. [The prove] (http://ideone.com/F2O3y) (foreach es lo mismo que reset + next). – meze

+0

¿Estás seguro de esto? Quiero decir, sé que altera el puntero interno, pero ¿eso invalida COW? –

+0

Cambié mi respuesta a un bucle for con un índice entero. –