php - texto - string strip_tags
En PHP(>=5.0), ¿está pasando por referencia más rápido? (8)
Ejecuté algunas pruebas sobre esto porque no estaba seguro de las respuestas dadas.
Mis resultados muestran que pasar grandes arreglos o cadenas por referencia es significativamente más rápido.
Aquí están mis resultados:
El eje Y (Ejecuciones) es cuántas veces se podría invocar una función en 1 segundo * 10
La prueba se repitió 8 veces para cada función / variable
Y aquí están las variables que utilicé:
$large_array = array_fill(PHP_INT_MAX / 2, 1000, ''a'');
$small_array = array(''this'', ''is'', ''a'', ''small'', ''array'');
$large_object = (object)$large_array;
$large_string = str_repeat(''a'', 100000);
$small_string = ''this is a small string'';
$value = PHP_INT_MAX / 2;
Estas son las funciones:
function pass_by_ref(&$var) {
}
function pass_by_val($var) {
}
En PHP, los parámetros de la función se pueden pasar por referencia al anteponer un símbolo comercial al parámetro en la declaración de la función, así:
function foo(&$bar)
{
// ...
}
Ahora, soy consciente de que esto no está diseñado para mejorar el rendimiento, sino para permitir que las funciones cambien las variables que normalmente están fuera de su alcance.
En cambio, PHP parece usar Copy On Write para evitar copiar objetos (y tal vez también matrices) hasta que se modifiquen. Por lo tanto, para las funciones que no cambian sus parámetros, el efecto debe ser el mismo que si las hubiera pasado por referencia.
Sin embargo, me preguntaba si la lógica Copiar al escribir podría estar en cortocircuito en la referencia de paso a paso y si eso tiene algún impacto en el rendimiento.
ETA: para estar seguro, supongo que no es más rápido, y soy consciente de que no se trata de referencias. Así que creo que mis propias conjeturas son bastante buenas, solo estoy buscando una respuesta de alguien que realmente sabe lo que definitivamente está sucediendo bajo el capó. En cinco años de desarrollo de PHP, siempre me ha resultado difícil obtener información de calidad sobre las funciones internas de PHP, menos que leer la fuente.
En una prueba con 100 000 iteraciones de invocar una función con una cadena de 20 kB, los resultados son:
Función que solo lee / usa el parámetro
pass by value: 0.12065005 seconds
pass by reference: 1.52171397 seconds
Función para escribir / cambiar el parámetro
pass by value: 1.52223396 seconds
pass by reference: 1.52388787 seconds
Conclusiones
Pasar el parámetro por valor es siempre más rápido
Si la función cambia el valor de la variable pasada, para fines prácticos es lo mismo que pasar por referencia que por valor
Estoy bastante seguro de que no, no es más rápido. Además, dice específicamente en el manual que no intente usar referencias para aumentar el rendimiento.
Editar: ¡No puedo encontrar dónde dice eso, pero está ahí!
He experimentado con valores y referencias de cadenas de 10k bytes pasando a dos funciones idénticas. Uno toma argumento por valor y el segundo por referencia. Eran funciones comunes: tomar argumentos, hacer un procesamiento simple y devolver un valor. Hice 100 000 llamadas de ambos y descubrí que las referencias no están diseñadas para aumentar el rendimiento: el beneficio de referencia estuvo cerca del 4-5% y crece solo cuando la cuerda se vuelve lo suficientemente grande (100k o más, que dio una mejora del 6-7%) . Entonces, mi conclusión es que no utilices referencias para aumentar el rendimiento, esto no es para eso.
Usé PHP Version 5.3.1
No es necesario agregar & operador al pasar objetos. En PHP 5+ los objetos se pasan por referencia de todos modos.
No hay nada mejor que una pieza de código de prueba
<?PHP
$r = array();
for($i=0; $i<500;$i++){
$r[]=5;
}
function a($r){
$r[0]=1;
}
function b(&$r){
$r[0]=1;
}
$start = microtime(true);
for($i=0;$i<9999;$i++){
//a($r);
b($r);
}
$end = microtime(true);
echo $end-$start;
?>
¡Resultado final! Cuanto más grande sea la matriz (o cuanto mayor sea la cantidad de llamadas), mayor será la diferencia. Entonces, en este caso, llamar por referencia es más rápido porque el valor se cambia dentro de la función.
De lo contrario, no hay una diferencia real entre "por referencia" y "por valor", el compilador es lo suficientemente inteligente como para no crear una nueva copia cada vez que no sea necesario.
Traté de compararlo con un ejemplo del mundo real basado en un proyecto en el que estaba trabajando. Como siempre, las diferencias son triviales, pero los resultados fueron algo inesperados. Para la mayoría de los puntos de referencia que he visto, la función llamada en realidad no cambia el valor pasado. Realicé un simple str_replace () en él.
**Pass by Value Test Code:**
$originalString=''''; // 1000 pseudo-random digits
function replace($string) {
return str_replace(''1'', ''x'',$string);
}
$output = '''';
/* set start time */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tstart = $mtime;
set_time_limit(0);
for ($i = 0; $i < 10; $i++ ) {
for ($j = 0; $j < 1000000; $j++) {
$string = $originalString;
$string = replace($string);
}
}
/* report how long it took */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tend = $mtime;
$totalTime = ($tend - $tstart);
$totalTime = sprintf("%2.4f s", $totalTime);
$output .= "/n" . ''Total Time'' .
'': '' . $totalTime;
$output .= "/n" . $string;
echo $output;
Pase por el código de prueba de referencia
Lo mismo a excepción de
function replace(&$string) {
$string = str_replace(''1'', ''x'',$string);
}
/* ... */
replace($string);
Resultados en segundos (10 millones de iteraciones):
PHP 5
Value: 14.1007
Reference: 11.5564
PHP 7
Value: 3.0799
Reference: 2.9489
La diferencia es una fracción de milisegundos por llamada de función, pero para este caso de uso, pasar por referencia es más rápido en PHP 5 y PHP 7.
(Nota: las pruebas de PHP 7 se realizaron en una máquina más rápida: PHP 7 es más rápido, pero probablemente no mucho más rápido).
Zend Engine usa copy-on-write, y cuando usas una referencia por ti mismo, incurre en un pequeño gasto adicional. Sin embargo, solo puede encontrar esta mención al momento de escribir, y los comentarios en el manual contienen otros enlaces.
(EDITAR) La página de manual sobre Objetos y referencias contiene un poco más de información sobre cómo las variables de objeto difieren de las referencias.